I would like to create 4 JPanels, draw a white rectangular on each
and then put them inside one, big JPanel. Big JPanel is inside the main frame.
However, the following code does not work. Please, tell me, how to fix this problem?
import javax.swing.*;
import java.awt.Graphics;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
public class Main extends JFrame
{
public void GUI () {
setBounds(0, 0, 480, 960);
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
System.exit(0);
}
});
setMinimumSize(new Dimension(480, 960));
setResizable(false);
JPanel mainPanel = new JPanel();
GridLayout GL = new GridLayout(4,0);
mainPanel.setLayout(GL);
JPanel panel1 = new MyCanvas();
JPanel panel2 = new MyCanvas();
JPanel panel3 = new MyCanvas();
JPanel panel4 = new MyCanvas();
mainPanel.add(panel1);
mainPanel.add(panel2);
mainPanel.add(panel3);
mainPanel.add(panel4);
add(mainPanel);
setVisible(true);
}
public static void main(String args[]) throws IOException
{
new Main().GUI();
}
class MyCanvas extends JPanel {
public void drawCanvas(Graphics g) {
super.paintComponent( g ); // call superclass's paintComponent
Graphics2D g2 = ( Graphics2D ) g; // cast g to Graphics2D
g2.setColor(Color.WHITE);
double x = 100;
double y = 100;
double width = x + 200;
double height = y + 50;
g2.fillRect(50, 50, 380, 200);
}
}
}
What is this supposed to do?:
public void drawCanvas(Graphics g) {
....
}
This method overrides no JPanel drawing method and so will not routinely get called when the JVM decides to paint your MyCanvas JPanel.
I think that instead you want to override the class's paintComponent(...) method which can easily be done by simply renaming your method to paintComponent(...). If/when you do this, don't forget to use the #Override annotation to be sure that you're overriding the method with the correct signature. You'll also want to change the method's access specifier to protected, not public.
Next you'll want to do something with those double variables that you're creating.
Related
I have been trying to learn how to draw to a Jpanel for a game. I want to draw to it from different classes (like a class that manages maps and a class that manages player models).
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main
{
public static void main (String[] args)
{
JFrame frame = new JFrame ("Java Game");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setSize (1000, 600);
JPanel panel = new JPanel();
panel.setBackground (Color.WHITE);
Dimension size = new Dimension(1000,500);
panel.add (new Player()); // Class with paintComponent method.
panel.setPreferredSize(size);
panel.setBackground(Color.BLUE);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
}
next class
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
#SuppressWarnings ("serial")
public class Player extends JComponent
{
int x = 50;
int y = 450;
public void paintComponent (Graphics g)
{
super.paintComponent(g);
g.setColor (Color.BLACK);
g.fillRect (x, y, 50, 50);
}
}
You probably want to extend JPanel. It's already opaque, and it can handle the background color for you. Also give your panel a size like they do here, then you can do the drawing relative to the size.
Player p = new Player();
p.setBackground(Color.cyan);
frame.add(p);
frame.pack();
frame.setVisible(true);
…
public class Player extends JPanel {
private static final int X = 320;
private static final int Y = 240;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(getWidth() / 2 - 25, getHeight() / 2 - 25, 50, 50);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(X, Y);
}
}
When I run this code. The result is a window with the name. Fully blank. I tried editing background color and adding graphics (rectangle) etc but the same result keeps occurring .
Question: This ends up as a white screen on a window. No graphics or background color. Even though I added it to panel and added panel. How do I fix this?
Main.java
package ball.tec.main;
import javax.swing.JFrame;
import ball.tec.frame.Frame;
public class Main {
public static void main(String[] args) {
String Version = "0.1.2";
Frame f = new Frame();
f.setVisible(true);
f.add();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
f.setSize(1500, 1000);
f.setTitle("RedBall V: " + Version);
}
}
Frame.java
package ball.tec.frame;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Frame extends JFrame{
private static final long serialVersionUID = 1L;
public boolean debug = false;
//Creating panel object
JPanel panel = new JPanel();
//Graphics displayed
public void paintComponent(Graphics g) {
//Firstly Nothing pops up
g.setColor(Color.RED);
g.drawRect(20, 40, 10, 10);
//And this doesn't work.
this.setBackground(Color.RED);
}
//Add everything to 'panel'
public void add() {
add(panel);
//Even if I put it here it doesn't work ;-;
this.setBackground(Color.RED);
this.pack();
}
}
You don't use paintComponent() in a JFrame. What you probably intended to do was create a third class, extending JPanel. Add your paintComponent() there.
public class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.drawRect(20, 40, 10, 10);
this.setBackground(Color.RED);
}
}
f.add(new MyPanel());
This what I am doing but is nothing is getting displayed on Jframe window. I have not extended class JFrame to do my, is it necessary to do so for displaying objects on window.
public class testGraphics {
static JFrame workingFrame = null;
public static void main(String args[])
{
JFrame workingManager = new JFrame("Hello");
workingManager.setSize(500, 500);
workingManager.setVisible(true);
Graphics g = workingManager.getGraphics();
JPanel jp = (JPanel) workingManager.getContentPane();
workingManager.paintComponents(g);
g.fillOval(0, 0, 30, 30);
g.drawOval(0, 50, 30, 30);
g.setColor(Color.CYAN);
}
}
Do not ever call getGraphics() or explicitly call paintXxx() to do custom painting. The correct way to do custom painting is to override the paintComponent method of the panel to paint on. The overriden method will be implicitly called for you. Then add that panel to the frame. Also you should override the getPreferredSize() of the panel, so it has a preferred size, so you can just pack the frame
class PaintPanel extends JPanel {
#Override
protected paintComponent(Grapchics g) {
super.paintComponent(g);
g.drawString(....);
}
#Override
public Dimension getPreferredSize() {'
return new Dimension(300, 300);
}
}
Then add it to the frame (or if you want to set it as the content pane of the frame, do that instead)
PaintPanel panel = new PaintPaint();
frame.add(panel);
...
frame.pack();
See more at Performing Custom Painting
I made several changes to your code to get it to work properly.
I changed your main method to call the SwingUtilities invokeLater method to make sure that the Swing components were defined and used on the Event Dispatch thread.
I created a drawing JPanel. I set the color first, then drew the ovals.
I added a JFrame default close operation. You must specify a default close operation, or else your Java application will continue running after you close the JFrame.
I moved the size to the drawing panel. The frame size will be calculated when you call the JFrame pack method.
And here's the modified code:
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestGraphics implements Runnable{
private JFrame workingManager;
private JPanel drawingPanel;
#Override
public void run() {
workingManager = new JFrame("Hello");
workingManager.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingPanel = new DrawingPanel();
workingManager.add(drawingPanel, BorderLayout.CENTER);
workingManager.pack();
workingManager.setLocationByPlatform(true);
workingManager.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new TestGraphics());
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID =
-3701718376300985046L;
public DrawingPanel() {
this.setPreferredSize(new Dimension(500, 500));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.CYAN);
g.fillOval(0, 0, 30, 30);
g.drawOval(0, 50, 30, 30);
}
}
}
The setSize() and setVisible() must be at the bottom of the method:
JFrame workingManager = new JFrame("Hello");
Graphics g = workingManager.getGraphics();
JPanel jp = (JPanel) workingManager.getContentPane();
workingManager.paintComponents(g);
g.fillOval(0, 0, 30, 30);
g.drawOval(0, 50, 30, 30);
g.setColor(Color.CYAN);
workingManager.setSize(500, 500);
workingManager.setVisible(true);
In the below example, how can I get the JPanel to take up all of the JFrame? I set the preferred size to 800x420 but it only actually fills 792x391.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BSTest extends JFrame {
BufferStrategy bs;
DrawPanel panel = new DrawPanel();
public BSTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout()); // edited line
setVisible(true);
setSize(800,420);
setLocationRelativeTo(null);
setIgnoreRepaint(true);
createBufferStrategy(2);
bs = getBufferStrategy();
panel.setIgnoreRepaint(true);
panel.setPreferredSize(new Dimension(800,420));
add(panel, BorderLayout.CENTER); // edited line
panel.drawStuff();
}
public class DrawPanel extends JPanel {
public void drawStuff() {
while(true) {
try {
Graphics2D g = (Graphics2D)bs.getDrawGraphics();
g.setColor(Color.BLACK);
System.out.println("W:"+getSize().width+", H:"+getSize().height);
g.fillRect(0,0,getSize().width,getSize().height);
bs.show();
g.dispose();
Thread.sleep(20);
} catch (Exception e) { System.exit(0); }
}
}
}
public static void main(String[] args) {
BSTest bst = new BSTest();
}
}
If you are having only one panel in frame and nothing else then try this:
Set BorderLayout in frame.
Add panel in frame with BorderLayout.CENTER
May be this is happening because of while loop in JPanel.(Not sure why? finding actual reason. Will update when find it.) If you replace it with paintComponent(g) method all works fine:
public BSTest() {
//--- your code as it is
add(panel, BorderLayout.CENTER);
//-- removed panel.drawStuff();
}
public class DrawPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
System.out.println("W:" + getSize().width + ", H:" + getSize().height);
g2d.fillRect(0, 0, getSize().width, getSize().height);
}
}
//your code as it is.
Here's an alternative using pack instead.
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PackExample extends JFrame {
public PackExample(){
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(800,600));
panel.setBackground(Color.green);
add(panel);
pack();
setVisible(true);
}
public static void main(String[] args){
new PackExample();
}
}
This took me forever to figure out but its actually the simplest code ever.
Just create a parent panel and pass GridLayout then add your child panel like this.
JPanel parentPanel= new JPanel(new GridLyout());
JPanel childPanel= new JPanel();
parentPanel.add(childPanel);
If you want to fill the JFrame with the whole of JPanel you need to setUndecorated to true i.e. frame.setUndecorated(true);. But now you have to worry about your MAXIMIZE< MINIMIZE, and CLOSE Buttons, towards the top right side(Windows Operating System)
I am a beginner, starting a simple project on GUI. The RectangleComponent should draw a Rectangle on the form with a button click. A rectangle won't draw with the following code, but if I put the same 2 lines of code outside the listener, it certainly works. I would appreciate any help.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class EllipseRectViewer {
/**
* #param args
*/
public static void main(String[] args)
{
final JFrame frame = new JFrame();
final int FRAME_WIDTH = 400;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Rectangle and Ellipse Draw");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel panel = new JPanel();
frame.add(panel, BorderLayout.NORTH);
class RectangleDrawListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
RectangleComponent r2 = new RectangleComponent();
frame.add(r2);
}
}
JButton rectButton = new JButton("Rectangle");
ActionListener rectDrawListener = new RectangleDrawListener();
rectButton.addActionListener(rectDrawListener);
panel.add(rectButton);
frame.setVisible(true);
}
}
import java.awt.Rectangle;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
public class RectangleComponent extends JComponent
{
Rectangle rect;
public RectangleComponent()
{
rect = new Rectangle(20, 20, 30, 30);
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.draw(rect);
}
}
Thank you.
After adding the RectangleComponent to the frame, either revalidate the newly added component or the frame's root pane:
public void actionPerformed(ActionEvent event) {
RectangleComponent r2 = new RectangleComponent();
frame.add(r2);
// Option 1
r2.revalidate();
// Option 2
frame.getRootPane().revalidate();
}
Note1: the frame itself can't be revalidated (upto JDK 1.6)
Note2: the frame itself can be revalidated (JDK 1.7+)
i think you need to revalidate() the frame.
frame.revalidate();
put it like this:
public void actionPerformed(ActionEvent event)
{
RectangleComponent r2 = new RectangleComponent();
frame.add(r2);
frame.revalidate();
}
Try to use LineBorder. Create a JPanel with LineBorder and add the JButton to the JPanel.
rect = new Rectangle(20, 20, 30, 30);
A second problem is that your component doesn't have a preferred size. Your component displays in a simple frame because you add the comonent to the center of a BorderLayout so the preferred size of the component is ignored. However, this won't work if you try to use the component when using other layout managers.
You should also override the getPreferredSize() method to return the preferred size of your component at a minimum you need to use:
return new Dimension(50, 50);
to accomodate the size and location of the painted rectangle.