This question already exists:
How to set size for custom-made panel that will work with gridbaglayout?
Closed 6 years ago.
I have one panel whit gridBagLayout and second with null gridlayout. When I add that to main panel, and main panel to frame one panel disappears. Why is that? And how to add two panels with different layouts setings in one frame?
Here is the code main #Beowolve:
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PrikazGUI {
JFrame frejm;
JPanel k;
JButton b1,b2;
public PrikazGUI(){
frejm = new JFrame("Lala");
k = new JPanel();
KvadratPravi p = new KvadratPravi();
JPanel grid = new JPanel();
grid.setLayout(new GridBagLayout());
grid.add(p);
// Kvadrat l = new Kvadrat();
JosJedanKvadrat jos = new JosJedanKvadrat();
// k.setLayout(null);
// k.setBounds(0, 444,444, 445);
k.add(jos);
k.add(grid);
JPanel main = new JPanel();
main.setLayout(null);
k.setBounds(0, 0,1000, 1900);
main.setBounds(0, 0,1000, 1900);
main.add(k);
frejm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frejm.setSize(1900, 1000);
frejm.getContentPane().add(main);
// frejm.getContentPane().add(k);
// frejm.pack();
frejm.setVisible(true);
}
public static void main(String[] args) {
PrikazGUI a = new PrikazGUI();
}
}
Second class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JPanel;
public class KvadratPravi extends JPanel {
int sizeH = 60;
int sizeW = 60;
public GridBagConstraints cst = new GridBagConstraints();
public KvadratPravi() {
JPanel j = new JPanel();
j.setLayout(new GridBagLayout());
cst.gridx = 0;
cst.gridy = 0;
add(j,cst);
}
#Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
g.setColor(Color.PINK);
g.drawRect(0, 0, sizeH, sizeW);
g.fillRect(0, 0, sizeH, sizeW);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(sizeH,sizeW);
}
}
Third class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JPanel;
public class JosJedanKvadrat extends JPanel {
int sizeH = 60;
int sizeW = 60;
int x,y;
public JosJedanKvadrat() {
setBounds(33, 44,444, 445);
JPanel j = new JPanel();
setLayout(null);
add(j);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(!e.isMetaDown()){
x = e.getX();
y = e.getY();
}
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
if(!e.isMetaDown()){
Point p = getLocation();
setLocation(p.x + e.getX() - x,
p.y + e.getY() - y);
}
}
});
}
#Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawOval(0, 0, sizeH, sizeW);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(sizeH,sizeW);
}
}
So I whant second class be in center of panel,and to have gridBagLayout, and third class I whant to move around the objects,so that class dont have gridlayout...when I and that two panels to main pane its seems that second class whit gridBagLayout does not working.
You are currently adding two JPanel into a JFrame.
JFrame f = new JFrame();
This frame, by default, use a BorderLayout. So if you call f.add(new Panel()); multiple time only the last one will be visible since the center area of this layout can only show one JComponent. You need to use a different layout.
Related
It shows the line without jpanel on jframe, but it doesn't when I add it to jpanel. I've tried setting the layout manager of jpanel to null but no result. I want to use JComponents for drawing lines because I want them clickable.
Main.java file:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setBackground(Color.YELLOW);
panel.setLayout(null);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
panel.repaint();
frame.add(panel);
frame.setVisible(true);
}
}
class Line extends JComponent {
private final Point2D start, end;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(2.0F));
g2.draw(new Line2D.Double(start,end));
}
public Line( Point2D start, Point2D end){
this.start = start;
this.end = end;
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked");
}
});
}
}
It shows the line without jpanel on jframe, but it doesn't when I add it to jpanel
Swing components are responsible for determining their own preferred size.
When you add a component to a panel, the layout manager will then set the size/location of the component based on the rules of the layout manager.
When you add a component to the frame you really add it to the content pane of the frame which is a Jpanel which uses a BorderLayout by default. So the component is sized to fill the space available in the frame.
panel.setLayout(null);
You then added the component to a panel with a null layout. Now you are responsible for setting the size/location of the component. If you don't the size is (0, 0) so there is nothing to paint.
You should override the getPreferredSize() method of your class to return the preferred size of the component. Then layout managers can do their job.
If you really need a null layout, then the size of the component should be set in the application code, not it the Line class itself.
But now my line has a big container that listens for any clicks,
If you want hit detection then you override the contains(...) method.
Here is a basic example implementing the above suggestions:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Line extends JComponent
{
private Line2D.Double line;
public Line( Point2D start, Point2D end)
{
line = new Line2D.Double(start, end);
addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent e)
{
System.out.println("mouse clicked");
}
});
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor( Color.BLUE );
g2.setStroke( new BasicStroke(2.0F) );
g2.draw( line );
}
#Override
public Dimension getPreferredSize()
{
Rectangle bounds = line.getBounds();
int width = bounds.x + bounds.width;
int height = bounds.y + bounds.height;
return new Dimension(width, height);
}
#Override
public boolean contains(int x, int y)
{
double distance = line.ptSegDist( new Point2D.Double(x, y) );
return distance < 2;
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setBackground(Color.YELLOW);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
panel.repaint();
frame.add(panel);
frame.setVisible(true);
}
}
Add custom size in Line constructor.
public Line( Point2D start, Point2D end){ ...
this.setSize(200, 200); }
Updated to fit also with painted Graph
Advice to change from JComponent to JPanel in order to see background
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
//Parent Panel
JPanel panel = new JPanel();
panel.setSize(300,300);
frame.add(panel);
panel.setBackground(Color.YELLOW);
panel.setLayout(null);
//Add Line To Panel
Line line = new Line(new Point2D.Double(20,20), new Point2D.Double(180,180));
panel.add(line);
frame.setVisible(true);
}
}
class Line extends JPanel {
private final Point2D start, end;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setBackground(Color.RED);
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(2.0F));
g2.draw(new Line2D.Double(start,end));
Rectangle r = g2.getClipBounds();
System.out.println(r.x+":"+r.y);
}
public Line( Point2D start, Point2D end){
this.start = start;
this.end = end;
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked at "+e.getX()+":"+e.getY());
}
});
int max_x = (int) Math.max(start.getX(), end.getX());
int max_y = (int) Math.max(start.getY(), end.getY());
System.out.println("max x="+max_y+",y="+max_y);
setSize(max_x,max_y);
setVisible(true);
setBackground(Color.GREEN);
}
}
Note: Only inside_green clicks allowed !
this is my problem, I hope you will help me somehow. I have one class that extends JPanel, and that class is creating a rectangle with a paintComponent method. When I add that class to JPanel who has gridBagLayout,first is not appearing. But, when I set Dimension.getPreferredSize() in that class, I can see the rectangle...and the problem is when I call MouseListener and see that rectangle is only moving in little square in the frame. So I think that somehow that method getPreferredSize() is controlling the place where will rectangle move and be.
Here is pic of my problem:
move3
limitet showing/moving4
Here is code:
Main:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PrikazGUI {
JFrame frejm;
JPanel k;
JButton b1,b2;
public PrikazGUI(){
frejm = new JFrame("Lala");
k = new JPanel();
k.setLayout(new GridBagLayout());
Kvadrat l = new Kvadrat();
JPanel a = new JPanel();
a.add(l);
k.add(a);
frejm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frejm.setSize(1900, 1000);
frejm.getContentPane().add(k);
frejm.setVisible(true);
}
public static void main(String[] args) {
PrikazGUI a = new PrikazGUI();
}
Second class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class KvadratPravi extends JPanel {
int sizeH = 60;
int sizeW = 60;
#Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
g.setColor(Color.PINK);
g.drawRect(0, 0, sizeH, sizeW);
g.fillRect(0, 0, sizeH, sizeW);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(sizeH,sizeW);
}
}
Third class:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Kvadrat extends JPanel {
JButton b1,b2;
JPanel panel;
KvadratPravi s1 = new KvadratPravi();
int x,y;
public Kvadrat(){
GridBagConstraints cst = new GridBagConstraints();
panel = new JPanel();
panel.setLayout(new GridBagLayout());
final KvadratPravi s = new KvadratPravi();
cst.gridx = 0;
cst.gridy = 0;
s.setPreferredSize(new Dimension(40,40));
s.setBounds(0, 0, 400, 400);
panel.add(s,cst);
JosJedanKvadrat j = new JosJedanKvadrat();
j.setPreferredSize(new Dimension(40,40));
j.setBounds(0, 0, 400, 400);
cst.gridx = 0;
cst.gridy = 4;
panel.add(j,cst);
s.setPreferredSize(new Dimension(400,400));
s.setBounds(400, 400, 400, 1000);
s.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(!e.isMetaDown()){
x = e.getX();
y = e.getY();
}
}
});
s.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
if(!e.isMetaDown()){
Point p = s.getLocation();
s.setLocation(p.x + e.getX() - x,
p.y + e.getY() - y);
}
}
});
cst.gridx = 2;
cst.gridy =4;
panel.add(s1,cst);
JPanel k = new JPanel();
k.add(panel);
add(k);
}
}
Fourth class:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class JosJedanKvadrat extends JPanel {
int sizeH = 60;
int sizeW = 60;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawOval(0, 0, sizeH, sizeW);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(sizeH,sizeW);
}
}
The intention of my code is to create a rectangle when the button is clicked. The button works fine but the rectangle itself is not showing up on the screen, and there are no errors. Thank you for helping btw.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tester {
static JButton button;
static JFrame frame;
static JPanel panel;
static Rectangle rec;
static void init(){
button = new JButton();
frame = new JFrame();
panel = new JPanel();
rec = new Rectangle(30,30,30,30);
button.setVisible(true);
panel.add(button);
frame.add(panel);
frame.setVisible(true);
panel.setVisible(true);
frame.setSize(200, 200);
button.setBackground(Color.GREEN);
button.setBounds(30, 30, 20, 20);
}
public static void main(String[] args) {
init();
ActionListener listener = new RectangleMover();
button.addActionListener(listener);
}
static class RectangleMover implements ActionListener{
#Override
public void actionPerformed(ActionEvent arg0) {
RectanglePainter r = new RectanglePainter();
r.add(rec);
}
}
static class RectanglePainter extends JPanel{
void add(Rectangle r){
rec = r;
repaint();
}
protected void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Random r = new Random();
int i =r.nextInt(2);
if (i==1)
g2.setColor(Color.BLUE);
else
g2.setColor(Color.RED);
g2.fill(rec);
g2.draw(rec);
}
}
}
Your generally approach is slightly skewed, rather than using another JComponent to "act" as the shape, you should be using it to paint all the shapes through it's paintComponent method
From my "red rectangle" period...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Tester {
public static void main(String[] args) {
new Tester();
}
public Tester() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JPanel panel;
private JButton button;
private JLabel label;
private ShapePane shapePane;
public TestPane() {
setLayout(new BorderLayout());
button = new JButton("Rectangle");
panel = new JPanel();
label = new JLabel();
button.setVisible(true);
panel.add(button);
panel.add(label);
shapePane = new ShapePane();
add(shapePane);
add(panel, BorderLayout.SOUTH);
class ClickListener implements ActionListener {
private int X = 20;
private int Y = 20;
#Override
public void actionPerformed(ActionEvent arg0) {
int width = shapePane.getWidth();
int height = shapePane.getHeight();
int x = (int)(Math.random() * (width - 20)) + 10;
int y = (int)(Math.random() * (height - 20)) + 10;
int w = (int)(Math.random() * (width - x));
int h = (int)(Math.random() * (height - y));
shapePane.add(new Rectangle(x, y, w, h));
}
}
ActionListener listener = new ClickListener();
button.addActionListener(listener);
}
}
public class ShapePane extends JPanel {
private List<Shape> shapes;
public ShapePane() {
shapes = new ArrayList<>(25);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void add(Rectangle rectangle) {
shapes.add(rectangle);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
for (Shape shape : shapes) {
g2.draw(shape);
}
}
}
}
As to answer your basic question, you could have tried calling revalidate and repaint, but because of the BorderLayout I doubt it would have worked as you would have basically been trying to replace the panel with your ShapeChanger component, and there are better ways to do that
I need to create a program that allows the user to select a color from a list of checkboxes, red and blue, and then a shape from a
list of radio buttons, square or circle. When the “Draw” button is pressed the selected
shape and color are drawn. If both red and blue are chosen, the shape is drawn in purple.
should look like the following picture:
This is about as far i've gotten, stumped as to how to create the circle and print it when that option is chosen. Also how do I reorganize the labels and buttons?
any help is appreciated
import java.awt.GridBagLayout;
import java.io.PrintWriter;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Shapes
{
public static JFrame window = new JFrame("Shapes");
public static JPanel panel = new JPanel(new GridBagLayout());
public static void main(String[] args)
{
window.setBounds(0, 0,300, 300);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.add(panel);
MApp m = new MApp();
m.setBounds(100,100,100,100);
window.add(m);
Draw d = new Draw(panel) ;
d.setBounds(0, 0, window.getWidth(), 90);
window.add(d);
window.setVisible(true);
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JPanel;
public class MApp extends JPanel implements MouseListener
{
private boolean clicked;
private Rectangle r;
public MApp()
{
clicked = false;
r = new Rectangle(15, 15, 50, 50);
addMouseListener(this);
}
public void paintComponent(Graphics g)
{
if(clicked)
{
g.setColor(Color.BLUE);
}
else
{
g.setColor(Color.RED);
}
g.fillRect((int)r.getX(), (int)r.getY(),
(int)r.getWidth(), (int)r.getHeight());
}
public void mouseClicked (MouseEvent e)
{
Point p = new Point(e.getX(),e.getY());
if(r.contains(p))
{
clicked = !clicked;
}
repaint();
}
public void Circle()
{
g.fillOval(0, 0, s, s);
}
public void mousePressed (MouseEvent evnt) {}
public void mouseReleased (MouseEvent evnt) {}
public void mouseEntered (MouseEvent evnt) {}
public void mouseExited (MouseEvent evnt) {}
}
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class Draw extends JPanel implements ActionListener
{
JTextField tfInfo;
JLabel lblColor, lblShapes;
JCheckBox cbRed, cbBlue;
ButtonGroup shapes;
JRadioButton rbCircle, rbSquare;
JButton btnSubmit;
public Draw(JPanel panel)
{
GridBagConstraints c = new GridBagConstraints();
tfInfo = new JTextField("Color", 15);
tfInfo = new JTextField("Shapes", 50);
lblColor = new JLabel("Colors:");
cbRed = new JCheckBox("Red");
cbBlue = new JCheckBox("Blue");
lblShapes = new JLabel("Shapes:");
shapes = new ButtonGroup();
rbCircle = new JRadioButton("Circle");
rbSquare = new JRadioButton("Square");
btnSubmit = new JButton("Draw");
btnSubmit.addActionListener(this);
this.setBackground(Color.WHITE);
add(lblColor);
add(cbRed);
add(cbBlue);
add(lblShapes);
add(rbCircle);
add(rbSquare);
add(btnSubmit);
shapes.add(rbCircle);
shapes.add(rbSquare);
}
public void actionPerformed(ActionEvent a)
{
if(a.getSource() == btnSubmit)
{
if(cbRed.isSelected()&&cbBlue.isSelected())
{
if(rbCircle.isSelected())
{
}
else if(rbSquare.isSelected())
{
}
}
else if(cbRed.isSelected())
{
if(rbCircle.isSelected())
{
}
else if(rbSquare.isSelected())
{
}
}
else if(cbBlue.isSelected())
{
if(rbCircle.isSelected())
{
}
}
else if(rbSquare.isSelected())
{
}
}
repaint();
}
}
Start by separating your "management" code from you "painting" code
You should have a single class that only handles the painting of the shape, nothing else, it just does what it's told.
You should then have a second class which takes input from the user and when they press the Draw button, it tells the "paint" class what it should be paint, for example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawStuff extends JFrame {
public static void main(String[] args) {
new DrawStuff();
}
public DrawStuff() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ControlPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ControlPane extends JPanel {
private JRadioButton circle;
private JRadioButton square;
private DrawPane drawPane;
public ControlPane() {
setLayout(new GridBagLayout());
ButtonGroup bg = new ButtonGroup();
circle = new JRadioButton("Circle");
square = new JRadioButton("Square");
bg.add(circle);
bg.add(square);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
JPanel shape = new JPanel();
shape.add(circle);
shape.add(square);
add(shape, gbc);
JButton draw = new JButton("Draw");
draw.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (circle.isSelected()) {
drawPane.setDrawableShape(DrawableShape.CIRCLE);
} else if (square.isSelected()) {
drawPane.setDrawableShape(DrawableShape.SQUARE);
}
}
});
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(draw, gbc);
drawPane = new DrawPane();
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = gbc.BOTH;
add(drawPane, gbc);
}
}
public enum DrawableShape {
CIRCLE,
SQUARE
}
public class DrawPane extends JPanel {
private DrawableShape drawableShape;
public DrawPane() {
}
public void setDrawableShape(DrawableShape drawableShape) {
this.drawableShape = drawableShape;
repaint();
}
public DrawableShape getDrawableShape() {
return drawableShape;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
DrawableShape shape = getDrawableShape();
if (shape != null) {
int width = getWidth() - 20;
int height = getHeight() - 20;
int size = Math.min(width, height);
int x = (getWidth() - size) / 2;
int y = (getHeight() - size) / 2;
if (shape == DrawableShape.CIRCLE) {
g2d.fillOval(x, y, size, size);
} else if (shape == DrawableShape.SQUARE) {
g2d.fillRect(x, y, size, size);
}
}
g2d.dispose();
}
}
}
I'll leave you to add in the color management.
Have a closer look at:
How to Use Buttons, Check Boxes, and Radio Buttons
How to Write an Action Listeners
Painting in AWT and Swing
Performing Custom Painting
2D Graphics
for more details
So I have this problem with my code. Whenever I load up the game there is a red square in the center of the screen, and I have not programmed it to do so. I have tried to find the error for hours but I just can't see it. I think it has to do with the panels or something. The second thing is that when I press the button to draw the grid, only a small line appears. It is programmed to be much bigger than what it is, and it is not in the right location either. Below is all my code, and any help is greatly appreciated!!
package com.theDevCorner;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
public class Game extends JPanel implements ActionListener {
public static JButton grid = new JButton("Show Grid");
public static JPanel drawArea = new JPanel();
public static JMenuBar menu = new JMenuBar();
public static JPanel notDrawn = new JPanel();
public static boolean gridPressed = false;
public Game() {
grid.addActionListener(this);
}
public static void main(String args[]) {
Game game = new Game();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(new Dimension(
Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit
.getDefaultToolkit().getScreenSize().height));
frame.setTitle("Game");
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
menu.setSize(new Dimension(1600, 20));
menu.setLocation(0, 0);
notDrawn.setBackground(new Color(255, 0, 50));
notDrawn.setSize(100, 900);
notDrawn.add(grid);
notDrawn.setLayout(null);
grid.setSize(new Dimension(100, 25));
grid.setLocation(0, 25);
drawArea.setSize(new Dimension((Toolkit.getDefaultToolkit()
.getScreenSize().width), Toolkit.getDefaultToolkit()
.getScreenSize().height));
drawArea.setLocation(100, 0);
drawArea.setBackground(Color.black);
drawArea.add(menu);
drawArea.add(game);
frame.add(drawArea);
frame.add(notDrawn);
}
public void paint(Graphics g) {
Game game = new Game();
if (gridPressed) {
Game.drawGrid(0, 0, g);
}
g.dispose();
repaint();
}
public static void drawGrid(int x, int y, Graphics g) {
g.setColor(Color.white);
g.drawLine(x, y, 50, 300);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == grid && gridPressed == true) {
gridPressed = false;
System.out.println("Unpressed");
}
if (e.getSource() == grid) {
gridPressed = true;
System.out.println("Pressed");
}
}
}
There are a number of problems...
The red "square" you are seeing is actually your grid button. The reason it's red is because of your paint method.
Graphics is a shared resource, that is, each component that is painted on the screen shares the same Graphics context. Because you chose to dispose of the context and because you've failed to honor the paint chain, you've basically screwed it up.
Don't EVER dispose of a Graphics context you didn't create. It will prevent anything from being painted to it again. Always call super.paintXxx. The paint chain is complex and does a lot of very important work. If you're going to ignore it, be ready to have to re-implement it.
null layouts are vary rarely the right choice, especially when you're laying out components. You need to separate your components from your custom painting, otherwise the components will appear above the custom painting.
This frame.setSize(new Dimension(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height)) is not the way to maximize a window. This does not take into consideration the possibility of things like tasks bars. Instead use Frame#setExtendedState
As Andreas has already commented, you actionPerformed logic is wrong. You should be using an if-statement or simply flipping the boolean logic...
Updated with simple example
ps- static is not your friend here...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JPanel implements ActionListener {
private GridPane gridPane;
public Game() {
setLayout(new BorderLayout());
SideBarPane sideBar = new SideBarPane();
sideBar.addActionListener(this);
add(sideBar, BorderLayout.WEST);
gridPane = new GridPane();
add(gridPane);
}
public static void main(String args[]) {
Game game = new Game();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setTitle("Game");
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(game);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("grid")) {
gridPane.setGridOn(!gridPane.isGridOn());
}
}
public class GridPane extends JPanel {
private boolean gridOn = false;
public GridPane() {
setBackground(Color.BLACK);
}
public boolean isGridOn() {
return gridOn;
}
public void setGridOn(boolean value) {
if (value != gridOn) {
this.gridOn = value;
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (gridOn) {
g.setColor(Color.white);
g.drawLine(0, 0, 50, 300);
}
}
}
public class SideBarPane extends JPanel {
public JButton grid;
public SideBarPane() {
setBackground(new Color(255, 0, 50));
setLayout(new GridBagLayout());
grid = new JButton("Show Grid");
grid.setActionCommand("grid");
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTH;
gbc.weighty = 1;
add(grid, gbc);
}
public void addActionListener(ActionListener listener) {
grid.addActionListener(listener);
}
}
}