Alright, I figured out everything that I got but now I am really stuck. Every time you choose a different shape the previously selected one disappears. How do I make it so they don't disappear and stay on the screen until you exit?
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
public class ShapeStamper extends JFrame{
Random rand = new Random();
public int x;
public int y;
private JPanel panel1, panel2;
private JButton button1, button2, button3, button4;
private int option = 0;
public ShapeStamper(){
super("Shape Stamper!");
panel1 = new JPanel();
button1 = new JButton("Circle");
button2 = new JButton("Square");
button3 = new JButton("Rectangle");
button4 = new JButton("Oval");
button1.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae){
option = 1;
}
}
);
button2.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae){
option = 2;
}
}
);
button3.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae){
option = 3;
}
}
);
button4.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae){
option = 4;
}
}
);
panel2 = new JPanel();
panel2.setBackground(Color.WHITE);
MouseHandler mouse = new MouseHandler();
setVisible(true);
addMouseListener(mouse);
addMouseMotionListener(mouse);
add(panel2);
panel1.add(button1);
panel1.add(button2);
panel1.add(button3);
panel1.add(button4);
add(panel1, BorderLayout.SOUTH);
setSize(500,500);
setVisible(true);
}
private class MouseHandler extends MouseAdapter implements MouseMotionListener{
#Override
public void mousePressed(MouseEvent e){
x = e.getX();
y = e.getY();
repaint();
}
}
public void paint(Graphics g){
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g;
if(option == 0){
g.setFont(new Font("Serif", Font.BOLD, 32));
g.drawString("Shape Stamper!", 150, 220);
g.setFont(new Font("Serif", Font.ITALIC, 16));
g.drawString("Programmed by: Chris", 150, 230);
}
if(option == 1){
Color randColor1 = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
g2d.setPaint(randColor1);
g2d.drawOval(50, 50, 100, 100);
}
if(option == 2){
Color randColor2 = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
g2d.setPaint(randColor2);
g2d.drawRect(50, 50, 100, 100);
}
if(option == 3){
Color randColor3 = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
g2d.setPaint(randColor3);
g2d.draw(new Rectangle2D.Double(75,50,150,100));
}
if(option == 4){
Color randColor4 = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
g2d.setPaint(randColor4);
g2d.draw(new Ellipse2D.Double(50, 25, 100, 50));
}
}
public static void main(String[] args) {
ShapeStamper application = new ShapeStamper();
application.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
You should not be overriding paint of a top level container and then trying to painting over the top of the components you have already added.
The basic problem you will encounter is, the paint system is clever enough that it may not ever call paint of the frame, but simply update the child components directly instead.
Instead, create yourself a custom component, extending from something like JPanel and override it's paintComponent method and perform your custom painting there. Then add this component to your frame.
You will also find the the paint updates are cleaner and won't flicker when updated.
You should also make sure you are calling repaint on this custom component when ever you change one it's options to ensure that changes are painted back to the component
Take a look at Performing Custom Painting for more details.
Also, just to be clear, you should not be calling super.paintComponents from paint (or in fact anywhere except for when you override paintComponents...which there really should be a need to do...)
Related
I'm trying to add two JPanels to a JFrame, one with a simple backround and another one with buttons etc. Either I get only buttons or only the background. I can't find a solution to my problem anywhere, so any help would be appreciated. I'm still new to Java, so please don't hate.
GuiMainMenu:
public class GuiMainMenu extends JFrame implements ActionListener, KeyListener {
private static final long serialVersionUID = -7936366600070922227L;
Color blue = new Color(114, 137, 218);
Color gray = new Color(44, 47, 51);
Color white = new Color(255, 255, 255);
ImagePanel panel = new ImagePanel(new ImageIcon("image.png").getImage());
public static int width;
public static int height;
JPanel p = new JPanel();
JPanel p1 = new JPanel();
JLabel l = new JLabel();
JLabel l1 = new JLabel();
JLabel l2 = new JLabel();
JButton b = new JButton();
JButton b1 = new JButton();
JButton b2 = new JButton();
String title = "-";
public GuiMainMenu() {
setSize(m.X, m.Y);
setTitle(title);
setResizable(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(this);
p.setLayout(null);
width = getWidth();
height = getHeight();
getRootPane().addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
width = getWidth();
height = getHeight();
addButtons();
addLabels();
}
});
addLabels();
addButtons();
add(p);
add(panel);
setVisible(true);
}
public void addLabels() {
l.setSize(width, height);
l.setLocation(5, -40);
l.setText("x");
l.setHorizontalAlignment(SwingConstants.LEFT);
l.setVerticalAlignment(SwingConstants.BOTTOM);
l.setForeground(blue);
l.setFont(new Font("Trebuchet MS", Font.PLAIN, 15));
l1.setSize(width, height);
l1.setLocation(-22, -40);
l1.setText("y");
l1.setHorizontalAlignment(SwingConstants.RIGHT);
l1.setVerticalAlignment(SwingConstants.BOTTOM);
l1.setForeground(blue);
l1.setFont(new Font("Trebuchet MS", Font.PLAIN, 15));
l2.setText("test label");
l2.setSize(width, height);
l2.setLocation(0, -75);
l2.setVerticalAlignment(SwingConstants.CENTER);
l2.setHorizontalAlignment(SwingConstants.CENTER);
l2.setForeground(blue);
l2.setFont(new Font("Trebuchet MS", Font.BOLD, 26));
p.add(l);
p.add(l1);
p.add(l2);
validate();
}
public void addButtons() {
b.setText("button0");
b.setFocusable(false);
b.setBorder(null);
b.setLocation(width / 2 - 200, height / 2 - 35);
b.setSize(400, 35);
b.setForeground(white);
b.setBackground(blue);
b.addActionListener(this);
b1.setText("button1");
b1.setFocusable(false);
b1.setBorder(null);
b1.setLocation(width / 2 - 200, height / 2 + 10);
b1.setSize(400, 35);
b1.setForeground(white);
b1.setBackground(blue);
b1.addActionListener(this);
p.add(b);
p.add(b1);
validate();
}
#Override
public void actionPerformed(ActionEvent arg0) {
}
#Override
public void keyPressed(KeyEvent arg0) {
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
}
ImagePanel Class:
class ImagePanel extends JPanel {
private static final long serialVersionUID = -7270956677693528549L;
private Image img;
public ImagePanel(String img) {
this(new ImageIcon(img).getImage());
}
public ImagePanel(Image img) {
this.img = img;
}
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, GuiMainMenu.width, GuiMainMenu.height, null);
}
}
p.setLayout(null);
Don't use a null layout. Swing was designed to be used with layout managers.
Read the section from the Swing tutorial on Layout Managers for more information and working examples.
Either I get only buttons or only the background
add(p);
add(panel);
The default layout manager for a JFrame is the BorderLayout. If you don't specify a constraint both components get added to the CENTER. However only the last one added will be displayed.
Try the following to see the difference:
add(p, BorderLayout.PAGE_STRT);
add(panel, BorderLayout.CENTER);
one with a simple backround and another one with buttons etc.
However above is not what you want. Swing components have a parent/child relationship. So what you really need is:
backgroundPanel.add(buttonPanel);
add(backgroundPanel, BorderLayout.CENTER);
Note I used more meaningful names because "p" and "panel" and not descriptive. Use descriptive names for variable so people can understand what they mean.
I suppose you want to display a JFrame with a background image and various components. I think after reviewing your code that there is some misunderstanding on your part causing the problem.
I've created a short snippet of code that does the basics and maybe helps you to solve your problem. (Not tested!)
#SuppressWarnings("serial")
public class GuiMainMenu extends JFrame{
private BufferedImage imageBackground; // TODO: load your background image
public GuiMainMenu(){
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(1024, 768));
setMinimumSize(new Dimension(800, 600));
// TODO: setLayout if needed
JPanel panel = (JPanel)add(new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(imageBackground, 0, 0, this);
}
});
addOtherComponents(panel);
pack();
setLocationRelativeTo(null);
setTitle("Your Title her");
setVisible(true);
}
private void addOtherComponents(JPanel panel){
//TODO: add the needed Stuff
//panel.add ...
}
}
I am trying to add a Rectangle in the panel by button press and remove it with another one. It should work but it doesn't render anything, and I absolutely don't know why.
Can someone explain what I am doing wrong and give me some nice tips what I can improve with my code?
public class GUI extends JPanel {
public static boolean isRecVisible = false;
public static void main(String[] args) {
createGui();
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g);
g2d.drawRect(10, 10, 200, 200);
}
public static void createGui() {
int frameWidth = 550;
int frameHeight = 400;
int buttonWidth1 = 250;
int buttonHeight1 = 30;
int buttonWidth2 = 500;
int buttonHeight2 = 30;
int displayWidth = frameWidth - 20;
int displayHeight = frameHeight - 105;
GUI drawRec = new GUI();
JFrame f = new JFrame("Rectangle");
JPanel p = new JPanel();
JPanel display = new JPanel();
JButton addRec = new JButton("Add Rectangle");
JButton removeRec = new JButton("Remove Rectangle");
JButton colorRec = new JButton("Color Rectangle");
f.add(p);
p.add(addRec);
p.add(removeRec);
p.add(colorRec);
p.add(display);
display.setBackground(Color.LIGHT_GRAY);
f.setSize(frameWidth, frameHeight);
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
display.setBounds(frameWidth / 2 - displayWidth / 2, 10, displayWidth, displayHeight);
addRec.setBounds(frameWidth / 2 - buttonWidth1 / 2 - 250 / 2, frameHeight - 85, buttonWidth1, buttonHeight1);
removeRec.setBounds(frameWidth / 2 - buttonWidth1 / 2 + 250 / 2, frameHeight - 85, buttonWidth1, buttonHeight1);
colorRec.setBounds(frameWidth / 2 - buttonWidth2 / 2, frameHeight - 60, buttonWidth2, buttonHeight2);
addRec.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (isRecVisible == false) {
isRecVisible = true;
display.add(drawRec);
display.repaint();
System.out.println("Rectangle has been drawn!");
} else {
System.out.println("Rectangle has already been drawn!");
return;
}
}
});
removeRec.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (isRecVisible == true) {
isRecVisible = false;
System.out.println("Rectangle has been removed!");
} else {
System.out.println("Rectangle has already been removed");
return;
}
}
});
}
}
display.add(drawRec);
display.repaint();
When you add (or remove) components to a visible frame then the basic logic is:
display.add(...);
display.revalidate();
display.repaint(); // sometimes needed
The revalidate() is the key method because it invokes the layout manager so the size/location of the component can be set.
However, that still won't fix the problem because your custom panel doesn't have a preferred size, so there is nothing to paint for your component.
You need to override the getPreferredSize() method of your custom panel to return the preferred size of your custom component. So in your case you might set the preferred size to be (220, 220) so the rectangle is centered in the panel.
Read the section from the Swing tutorial on Custom Painting for more information and complete working examples.
Note: the tutorial example will also show you how to better structure your code to make sure the GUI is created on the Event Dispatch Thread.
Rather than adding or removing components, it would make more sense here to add the custom painted panel on construction, and use the isRecVisible boolean as a flag to test for drawing the rectangle.
Something like shown here:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUI extends JPanel {
public static boolean isRecVisible = false;
public static void main(String[] args) {
createGui();
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g);
if (isRecVisible) {
g2d.drawRect(10, 10, 200, 200);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600,400);
}
public static void createGui() {
int frameWidth = 550;
int frameHeight = 400;
GUI drawRec = new GUI();
drawRec.setBackground(Color.LIGHT_GRAY);
JFrame f = new JFrame("Rectangle");
JPanel p = new JPanel();
JButton addRec = new JButton("Add Rectangle");
JButton removeRec = new JButton("Remove Rectangle");
JButton colorRec = new JButton("Color Rectangle");
f.add(p, BorderLayout.PAGE_START);
p.add(addRec);
p.add(removeRec);
p.add(colorRec);
f.add(drawRec);
f.setSize(frameWidth, frameHeight);
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
addRec.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
isRecVisible = true;
drawRec.repaint();
}
});
removeRec.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
isRecVisible = false;
drawRec.repaint();
}
});
}
}
I have such code, where I need to create some buttoms for customizing the square. It works, but after rolling up the frame the text field moves all over the frame and I don't know why. I mean when I execute the programm for first it's located in the right position that I mentioned using method setBounds(), but then it's located above the square. So how can I fix it?
import java.awt.*;
import java.awt.event.*;
import java.text.AttributedString;
import javax.swing.*;
import java.awt.font.TextAttribute;
public class Square extends JFrame implements ActionListener {
Button butt1 = new Button("Fill with yellow");
Button butt2 = new Button("Fill with red");
Button butt3 = new Button("Add label");
Button butt4 = new Button("");
Pan contentPane = new Pan();
public Square() {
super("Square");
this.setBounds(200, 100, 670, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().add(contentPane);
contentPane.setBounds(0, 0, 670, 275);
contentPane.setBackground(Color.BLACK);
add(butt1);
butt1.setBounds(25, 300, 190, 25);
butt1.addActionListener(this);
add(butt2);
butt2.setBounds(235, 300, 190, 25);
butt2.addActionListener(this);
butt3.setBounds(440, 300, 190, 25);
butt3.addActionListener(this);
add(butt3);
add(butt4);
}
#Override
public void actionPerformed(ActionEvent e) {
Object o = e.getSource();
if (o == butt1) {
contentPane.draw(1);
}
else if (o == butt2) {
contentPane.draw(2);
}
else if (o == butt3) {
contentPane.draw(3);
}
}
public static void main(String[] args) {
Square w = new Square();
w.setVisible(true);
}
}
class Pan extends JPanel {
Graphics g;
Graphics2D g2;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(240, 70, 150, 150);
}
public void draw(int i) {
g = getGraphics();
super.paintComponent(g);
g2 = (Graphics2D) g.create();
switch(i) {
case 1: g2.setColor(Color.yellow);
g2.fillRect(240, 70, 150, 150);
break;
case 2: g2.setColor(Color.red);
g2.fillRect(240, 70, 150, 150);
break;
case 3:
g.setColor(Color.GRAY);
g.drawRect(240, 70, 150, 150);
JTextField text = new JTextField(25);
this.add(text);
Button add = new Button("Add");
add.setBounds(400, 230, 120, 25);
this.add(add);
text.setBounds(240, 230, 150, 25);
Font font = new Font("Veranda", Font.BOLD|Font.ITALIC, 24);
class AddButton extends JPanel implements ActionListener {
#Override
public void actionPerformed(ActionEvent ev) {
AttributedString label = new AttributedString(text.getText());
label.addAttribute(TextAttribute.FONT, font);
label.addAttribute(TextAttribute.FOREGROUND, Color.PINK);
g2.drawString(label.getIterator(), 240, 50);
}
}
AddButton listener = new AddButton();
add.addActionListener(listener);
break;
}
}
}
Okay lots of core issues and misunderstandings.
Swing uses layout managers. This is probably one of the first things you're butting heads again. Layout managers make decisions about how best to position components based on their individual algorithms.
Start by taking a look at Laying Out Components Within a Container for more details and make good use of them. GUIs are complex and dynamic things, with many factors going in to determining how components should be sized and positioned.
Painting. Another problem new developers have is understanding that they don't control the paint system. Swing uses a passive rendering system, which means it will paint when it feels its required.
You can provide hints when a new paint pass should be done by calling repaint, but it's up to the system to decide what and when something should be painted.
g = getGraphics(); is a bad idea on many levels. Apart from been able to return null, it's nothing more then a snapshot of the last paint pass and will be discarded when a new paint pass occurs.
Calling super.paintComponent(g); outside of a paint pass is also a bad idea. In fact, there should rarely ever be a need to call any of the paint methods directly.
This is NOT how custom painting should be done. Start by having a look at Performing Custom Painting and Painting in AWT and Swing for how painting works and how you should work with it
Also, mixing heavy weight (AWT) and light weight (Swing) components together is generally a bad idea should be avoid as much as possible.
Example...
So, I "hacked" you example into something a "little" more reasonable
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
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 java.awt.font.TextAttribute;
import java.text.AttributedString;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class Square extends JFrame implements ActionListener {
JButton butt1 = new JButton("Fill with yellow");
JButton butt2 = new JButton("Fill with red");
JButton butt3 = new JButton("Add label");
JButton butt4 = new JButton("");
Pan contentPane = new Pan();
public Square() {
super("Square");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().add(contentPane);
contentPane.setBackground(Color.BLACK);
JPanel actions = new JPanel();
actions.setBorder(new EmptyBorder(10, 10, 10, 10));
actions.add(butt1);
butt1.addActionListener(this);
actions.add(butt2);
butt2.addActionListener(this);
butt3.addActionListener(this);
actions.add(butt3);
// actions.add(butt4);
add(actions, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
}
#Override
public void actionPerformed(ActionEvent e) {
Object o = e.getSource();
if (o == butt1) {
contentPane.draw(1);
} else if (o == butt2) {
contentPane.draw(2);
} else if (o == butt3) {
contentPane.draw(3);
}
}
public static void main(String[] args) {
Square w = new Square();
w.setVisible(true);
}
}
class Pan extends JPanel {
private int state = -1;
private String text = null;
public Pan() {
Font font = new Font("Veranda", Font.BOLD | Font.ITALIC, 24);
setFont(font);
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(670, 275);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(Color.GRAY);
g2.drawRect(240, 70, 150, 150);
switch (state) {
case 1:
g2.setColor(Color.yellow);
g2.fillRect(240, 70, 150, 150);
break;
case 2:
g2.setColor(Color.red);
g2.fillRect(240, 70, 150, 150);
break;
case 3:
g.setColor(Color.GRAY);
g.drawRect(240, 70, 150, 150);
break;
}
if (text != null) {
AttributedString label = new AttributedString(text);
label.addAttribute(TextAttribute.FONT, getFont());
label.addAttribute(TextAttribute.FOREGROUND, Color.PINK);
g2.drawString(label.getIterator(), 240, 50);
}
}
public void draw(int i) {
switch (i) {
case 3:
JTextField textField = new JTextField(25);
JButton add = new JButton("Add");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.SOUTH;
this.add(textField, gbc);
gbc.gridx++;
this.add(add, gbc);
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ev) {
text = textField.getText();
remove(textField);
remove(add);
revalidate();
repaint();
}
});
revalidate();
repaint();
break;
}
state = i;
repaint();
}
}
Your code is full of, what is commonly known as, "magic numbers". These are values whose meaning is unknown.
Run the code and try resizing the window and you will see what I mean. Instead, you should be relying on "known" values, like getWidth and getHeight to make better determinations about how you should render the output
I am having two problems here. I'm making a simple program to test, basically when you click the button JColorChooser will pop up and you can choose what color you want your rectangle to be. And the second problem is i cannot position my buttons at BorderLayout.SOUTH or BorderLayout.NORTH Or anywhere. These are my code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUI extends JPanel {
private Color a = (Color.WHITE);
private Color b = (Color.WHITE);
private final JPanel panel;
private final JButton ab;
private final JButton bb;
private int x = 1;
private int y = 1;
public GUI() {
panel = new JPanel();
panel.setBackground(Color.WHITE);
ab = new JButton("Choose your first Rectangle color");
ab.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
a = JColorChooser.showDialog(null, "Pick a Color", a);
x = 2;
}
});
bb = new JButton("Choose your second Rectangle color");
bb.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
b = JColorChooser.showDialog(null, "Pick a Color", b);
y = 2;
}
});
add(ab, BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
add(bb, BorderLayout.SOUTH);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.WHITE);
if (x == 2)
g.setColor(a);
g.fillRect(50, 50, 100, 20);
if (y == 2)
g.setColor(b);
g.fillRect(50, 200, 100, 20);
}
}
And the second problem is i cannot position my buttons at BorderLayout.SOUTH or BorderLayout.NORTH Or anywhere.
JPanel uses a FlowLayout by default, try adding setLayout(new BorderLayout()) before you add any components
setLayout(new BorderLayout());
add(ab, BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
add(bb, BorderLayout.SOUTH);
I'm making a simple program to test, basically when you click the button jcolorchooser will pop up and you can choose what color you want your rectangle to be
Okay, I'm "guessing" that once you've selected a color, it's not changing the rectangle color.
Simply add a call to repaint after you've changed the color
ab.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
a = JColorChooser.showDialog(null, "Pick a Color", a);
x = 2;
repaint();
}
}
);
bb = new JButton("Choose your second Rectangle color");
bb.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
b = JColorChooser.showDialog(null, "Pick a Color", b);
y = 2;
repaint();
}
}
);
I am trying to create a simple GUI for a BST tree allowing insertions and deletions. However, I am having a lot of trouble inserting components onto the GUI during runtime.
What I thought of doing was to "refresh" the GUI every time an insertion or deletion happened. I created a method called printBst that creates Jlabels to display the numbered indexes as shown below, but they are not showing up.
I've tried to revalidate and validate the GUI afterwards but it still doesn't work. Anyone have any ideas?
package source;
import javax.swing.*;
import source.BST.BSTnode;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
public class Frame2 extends JFrame implements ActionListener{
BST bst;
JPanel displayPanel, buttonPanel, totalGUI;
JButton insertButton, deleteButton, resetButton;
JTextField insertField, deleteField;
public JPanel createContentPane (){
bst = new BST();
totalGUI = new JPanel();
totalGUI.setLayout(null);
displayPanel = new JPanel();
displayPanel.setLayout(null);
displayPanel.setLocation(10, 80);
displayPanel.setSize(400, 300);
totalGUI.add(displayPanel);
buttonPanel = new JPanel();
buttonPanel.setLayout(null);
buttonPanel.setLocation(10, 0);
buttonPanel.setSize(800, 80);
totalGUI.add(buttonPanel);
insertField = new JTextField(1);
insertField.addActionListener(this);
insertField.setLocation(0, 10);
insertField.setSize(150, 30);
buttonPanel.add(insertField);
insertButton = new JButton("Insert");
insertButton.setLocation(160, 10);
insertButton.setSize(150, 30);
insertButton.addActionListener(this);
buttonPanel.add(insertButton);
deleteField = new JTextField(1);
deleteField.addActionListener(this);
deleteField.setLocation(320, 10);
deleteField.setSize(150, 30);
buttonPanel.add(deleteField);
deleteButton = new JButton("Delete");
deleteButton.setLocation(480, 10);
deleteButton.setSize(150, 30);
deleteButton.addActionListener(this);
buttonPanel.add(deleteButton);
resetButton = new JButton("Reset");
resetButton.setLocation(640, 10);
resetButton.setSize(150, 30);
resetButton.addActionListener(this);
buttonPanel.add(resetButton);
totalGUI.setOpaque(true);
return totalGUI;
}
public void printBst(BSTnode node, int x, int x2, int y) {
if (node != null) {
JLabel current = new JLabel(""+ node.data);
current.setLocation((x+x2)/2, y);
current.setSize(100, 30);
current.setHorizontalAlignment(0);
displayPanel.add(current);
printBst(node.left, x, (x2+x)/2, y+60);
printBst(node.right, (x2+x)/2, x2, y+60);
System.out.println("here");
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == insertButton)
{
bst.insert(Integer.valueOf(insertField.getText()));
displayPanel.removeAll();
printBst(bst.root, 0, 800, 0);
totalGUI.revalidate();
validate();
}
else if(e.getSource() == deleteButton)
{
bst.delete(Integer.valueOf(deleteField.getText()));
displayPanel.removeAll();
printBst(bst.root, 0, 800, 0);
totalGUI.revalidate();
validate();
}
else if(e.getSource() == resetButton)
{
bst.clear();
displayPanel.removeAll();
printBst(bst.root, 0, 800, 0);
totalGUI.revalidate();
validate();
}
}
private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("[=] JButton Scores! [=]");
Frame2 demo = new Frame2();
frame.setContentPane(demo.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(900, 400);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Make sure you call revalidate() and repaint() after you remove components from displayPanel ie:
displayPanel.removeAll();
printBst(0, 800, 0);
displayPanel.revalidate();
displayPanel.repaint();
Also, note that:
printBst(0, 800, 0);
results in invalid (not in bounds) coordinates inside displayPanel, which size is defined as (400, 300) The top-left corner of a window is 0,0. Try the following and you should see your label somewhere in the middle of the panel:
printBst(0, 400, 0);
Absolute positioning can be very difficult to manage. Check out A Visual Guide to Layout Managers and see if you can find an appropriate layout to help you.
You may also consider ready to go frameworks that can give you 2D canvas to work on. For example JGraph, JFreeChart or Piccolo2D.