components not appearing after JLayeredPane - java

I have a single class extended from JFrame. I have multiple JLayeredPanes inside it. I want to switch from one JLayeredPane to another. For that what I does is;
remove the current JLayeredPane like remove(pane1);
repaint();
add components to new JLayeredPane and set bounds
add(pane2)
This removes my current JLayeredPane and shows next JLayeredPane. But the components are not added in correct position. For example, I have a jscrollpane containing a textarea. Only the scroll pane is appearing and text area is missing. Also, the size of comboboxes has changed. Why is this happening?
Here is a zip file containing entire java files http://s000.tinyupload.com/index.php?file_id=33381866612121130517

I combined this JLayeredPane example with this CardLayout example to demonstrate multiple, selectable layered panes.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/36587584/230513
* #see https://stackoverflow.com/a/6432291/230513
* #see https://stackoverflow.com/questions/6432170
*/
public class CardPanel extends JLayeredPane {
private static final Dimension d = new Dimension(320, 240);
private static final Random random = new Random();
private static final JPanel cards = new JPanel(new CardLayout());
private static final JComboBox combo = new JComboBox();
private final String name;
public CardPanel(String name) {
this.name = name;
this.setBackground(new Color(random.nextInt()));
this.add(new LayerPanel(1 * d.height / 8), 100);
this.add(new LayerPanel(2 * d.height / 8), 101);
this.add(new LayerPanel(3 * d.height / 8), 102);
}
#Override
public Dimension getPreferredSize() {
return d;
}
#Override
public String toString() {
return name;
}
private static class LayerPanel extends JPanel {
private static final Random r = new Random();
private int n;
private Color color = new Color(r.nextInt());
public LayerPanel(int n) {
this.n = n;
this.setOpaque(false);
this.setBounds(n, n, d.width / 2, d.height / 2);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 16, 16);
g2d.setColor(Color.black);
g2d.drawString(String.valueOf(n), 5, getHeight() - 5);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
create();
}
});
}
private static void create() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
for (int i = 1; i < 9; i++) {
CardPanel p = new CardPanel("Panel " + String.valueOf(i));
combo.addItem(p);
cards.add(p, p.toString());
}
JPanel control = new JPanel();
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JComboBox jcb = (JComboBox) e.getSource();
CardLayout cl = (CardLayout) cards.getLayout();
cl.show(cards, jcb.getSelectedItem().toString());
}
});
control.add(combo);
f.add(cards, BorderLayout.CENTER);
f.add(control, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

Related

Painting method paints things from other components

I am trying to make a simple Java program with GUI using Java Swing.
I have painting panel (gPanel) in the center of the screen, panel with buttons (buttonSet) in the west and panel with labels (labelPanel) in the east. To paint over gPanel I use paintComponent method and since I have two buttons, which are supposed to draw different things (and change label on the right of the screen), I decided to put switch case in paintComponent method for it to choose the correct actual painting method.
When I run the program everything looks fine - program uses the first method to paint and there is a sampletext.png image shown in the middle of the screen with yellow background, as it should be. Button number 1 also uses this method to draw over gPanel, so pressing it draws the same thing.
Now Button number 2 uses the second painting method and this is where things go wrong. It draws sampleimage.png over the gPanel, but also parts of left and right panels (i.e. buttons from left buttonSet panel and orange colour that is background colour of side panels) are drawn, though it shouldn't happen. Also the whole gPanel becomes gray (I think it happens because of label on the right that becomes very long after pressing Button number 2, because when the label was shorter gPanel didn't turn gray and left the previously drawn things instead).
Pressing Button number 1 paints things from first method properly, so pressing it after pressing Button number 2 "reverts" the changes.
What do I have to do to make my second painting method work properly?
Also why adding border to buttonSet and labelPanel works but adding it to gPanel doesn't?
package com.inferjus.drawingproject;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.border.*;
/**
*
* #author inferjus
*/
public class DrawingProject
{
private JFrame frame;
private graphicPanel gPanel;
private JPanel buttonSet;
private JPanel labelPanel;
private JLabel label;
private int painter=0;
public static void main(String[] args)
{
DrawingProject program=new DrawingProject();
program.prepareGUI();
}
public int getPainter()
{
return painter;
}
public void setPainter(int x)
{
painter=x;
}
public void prepareGUI()
{
//setting JFrame and icon
frame=new JFrame("Drawing Project");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
try { frame.setIconImage(ImageIO.read(getClass().getResource("/resources/sampleicon.png")));}
catch (IOException e) { e.printStackTrace(); }
//border for components
Border bigBlackBorder=new LineBorder(Color.black, 3);
//setting JPanel (graphicPanel) for drawing images
gPanel=new graphicPanel();
gPanel.setBorder(bigBlackBorder); // <--- why it does not work?
//setting JPanel for buttons on the left of the screen
buttonSet=new JPanel();
buttonSet.setLayout(new BoxLayout(buttonSet, BoxLayout.Y_AXIS));
buttonSet.setBorder(bigBlackBorder);
//setting JButtons
JButton buttonOne=new JButton("Button number 1");
buttonOne.addActionListener(new buttonOneListener());
buttonSet.add(buttonOne);
buttonSet.setBackground(Color.orange);
JButton buttonTwo=new JButton("Button number 2");
buttonTwo.addActionListener(new buttonTwoListener());
buttonSet.add(buttonTwo);
//setting JLabels on the right of the screen
label=new JLabel("Default label");
label.setFont(new Font("Consolas", Font.PLAIN, 20));
labelPanel=new JPanel();
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
labelPanel.setBackground(Color.orange);
labelPanel.setBorder(bigBlackBorder);
JLabel popeLabelTitle=new JLabel("What does the label say?");
popeLabelTitle.setFont(new Font("Consolas", Font.BOLD, 24));
//adding JLabels to labelPanel
labelPanel.add(BorderLayout.NORTH, popeLabelTitle);
labelPanel.add(BorderLayout.CENTER, label);
//adding components to JFrame
frame.getContentPane().add(BorderLayout.CENTER, gPanel);
frame.getContentPane().add(BorderLayout.EAST, labelPanel);
frame.getContentPane().add(BorderLayout.WEST, buttonSet);
frame.setVisible(true);
}
class graphicPanel extends JPanel
{
private BufferedImage sampletext=null;
private BufferedImage sampleimage=null;
#Override
public void paintComponent(Graphics g)
{
//for Button One paint sampletext.png, for Button Two paint sampleimage.png
switch (painter)
{
case 0:
paintSampletext(g);
break;
case 1:
paintSampleimage(g);
break;
}
}
//paint yellow background and put sampletext.png in the middle
private void paintSampletext(Graphics g)
{
if (sampletext==null)
{
gPanel.setSampletextPNG();
}
g.setColor(Color.yellow);
g.fillRect(0,0, gPanel.getWidth(), gPanel.getHeight());
g.drawImage(sampletext, gPanel.getWidth()/2-sampletext.getWidth()/2, gPanel.getHeight()/2-sampletext.getHeight()/2, this);
g.setColor(Color.black);
g.drawRect(gPanel.getWidth()/2-sampletext.getWidth()/2, gPanel.getHeight()/2-sampletext.getHeight()/2, sampletext.getWidth(), sampletext.getHeight());
g.dispose();
}
//paint sampleimage.png over what is already displayed
private void paintSampleimage(Graphics g)
{
if (sampleimage==null)
{
gPanel.setSampleimagePNG();
}
int x=(int)((Math.random()*gPanel.getWidth())-sampleimage.getWidth());
int y=(int)((Math.random()*gPanel.getHeight())-sampleimage.getHeight());
g.drawImage(sampleimage, x, y, gPanel);
g.dispose();
}
public void setSampletextPNG()
{
try { sampletext=ImageIO.read(getClass().getResource("/resources/sampletext.png")); }
catch (IOException ex) { System.out.println("Image error"); }
}
public void setSampleimagePNG()
{
try { sampleimage=ImageIO.read(getClass().getResource("/resources/sampleimage.png")); }
catch (IOException ex) { System.out.println("Image error"); }
}
}
class buttonOneListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
label.setText("Reaction to button number 1: change of label.");
setPainter(0);
gPanel.repaint();
}
}
class buttonTwoListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
label.setText("Reaction to button number 2: change of label + drawing images over gPanel.");
setPainter(1);
gPanel.repaint();
}
}
}
Tree of my project:
DrawingProject
-JRE System Library
-src
--com.inferjus.drawingproject
---DrawingProject.java
--resources
---sampleicon.png
---sampleimage.png
---sampletext.png
what shows after running the program by default or after pressing Button One
what shows after pressing Button Two one time
what shows after pressing Button Two a few times
Introduction
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.
I went ahead and created the following GUI. I created two BufferedImages for the text image and the plain image so I wouldn't have to read any external files.
Explanation
When I create a Swing GUI, I use the model-view-controller pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.
Model
I created a model class to hold the button flag and the two BufferedImages. This is the class where you would read the resources.
You can add the JFrame icon back to this class.
Model classes are plain Java getter/setter classes.
View
All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
Class names are written in camel case and start with an upper case character. Method names are written in camel case and start with a lower case character. Field names follow the same rules as method names.
I separated the creation of the JFrame from the creation of the JPanels. This helps me to separate my concerns and makes it much easier to visually verify whether or not the code is correct. Aim to write short methods that do one thing and do it well.
You have to manually draw a border on a graphic JPanel. I added the code to your paintComponent method to paint a partial border.
Your paintComponent method should paint. Period. Nothing else. It must also start with a call to the super.paintComponent method to maintain the Swing paint chain.
I changed your JLabel in the right JPanel to a JTextArea. A JTextArea allows for longer messages to word wrap on multiple lines and not make your JFrame change size.
Controller
Your JButton controller classes were fine, except for the class names.
Code
Here's the complete runnable code. I made all the additional classes inner classes so I could post the code in one block.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class DrawingProject implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawingProject());
}
private final DrawingModel model;
private GraphicPanel graphicPanel;
private JTextArea textArea;
public DrawingProject() {
this.model = new DrawingModel();
}
#Override
public void run() {
JFrame frame = new JFrame("Drawing Project");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
graphicPanel = new GraphicPanel(model);
frame.add(createButtonPanel(), BorderLayout.WEST);
frame.add(graphicPanel, BorderLayout.CENTER);
frame.add(createTextPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBackground(Color.orange);
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
JButton buttonOne = new JButton("Button number 1");
buttonOne.addActionListener(new ButtonOneListener());
panel.add(buttonOne);
JButton buttonTwo = new JButton("Button number 2");
buttonTwo.addActionListener(new ButtonTwoListener());
panel.add(buttonTwo);
return panel;
}
private JPanel createTextPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
JLabel popeLabelTitle = new JLabel("What does the label say?");
popeLabelTitle.setFont(new Font(Font.MONOSPACED, Font.BOLD, 24));
panel.add(popeLabelTitle, BorderLayout.NORTH);
textArea = new JTextArea(4, 30);
textArea.setEditable(false);
textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 20));
textArea.setText("Default label");
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
panel.add(textArea, BorderLayout.CENTER);
return panel;
}
public class GraphicPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final DrawingModel model;
public GraphicPanel(DrawingModel model) {
this.model = model;
this.setPreferredSize(new Dimension(640, 480));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Paint border
int width = getWidth();
int height = getHeight();
int lineThickness = 3;
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
g.setColor(Color.YELLOW);
g.fillRect(0, lineThickness, width, height - 2 * lineThickness);
switch (model.getPainter()) {
case 0:
paintSampleText(g);
break;
case 1:
paintSampleImage(g);
break;
}
}
private void paintSampleText(Graphics g) {
BufferedImage image = model.getSampleText();
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g.drawImage(image, x, y, this);
}
private void paintSampleImage(Graphics g) {
BufferedImage image = model.getSampleImage();
int x = (int) ((Math.random() * getWidth()) - image.getWidth());
int y = (int) ((Math.random() * getHeight()) - image.getHeight());
g.drawImage(image, x, y, this);
}
}
public class ButtonOneListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("Reaction to button number 1: change of label.");
model.setPainter(0);
graphicPanel.repaint();
}
}
public class ButtonTwoListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("Reaction to button number 2: change of label + "
+ "drawing images over gPanel.");
model.setPainter(1);
graphicPanel.repaint();
}
}
public class DrawingModel {
private int painter;
private final BufferedImage sampleText;
private final BufferedImage sampleImage;
public DrawingModel() {
this.painter = 0;
this.sampleText = createBufferedImage(Color.BLUE);
this.sampleImage = createBufferedImage(Color.MAGENTA);
}
private BufferedImage createBufferedImage(Color color) {
BufferedImage image = new BufferedImage(64, 64,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(color);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.dispose();
return image;
}
public int getPainter() {
return painter;
}
public void setPainter(int painter) {
this.painter = painter;
}
public BufferedImage getSampleText() {
return sampleText;
}
public BufferedImage getSampleImage() {
return sampleImage;
}
}
}
Update
In order to paint multiple images, you have to save the origin of the images in a List. I've modified the application model to hold a List of origin Point instances. I also corrected the code to create a random point.
Here's the GUI with multiple images.
Here's the modified code
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class DrawingProject implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawingProject());
}
private final DrawingModel model;
private GraphicPanel graphicPanel;
private JTextArea textArea;
public DrawingProject() {
this.model = new DrawingModel();
}
#Override
public void run() {
JFrame frame = new JFrame("Drawing Project");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
graphicPanel = new GraphicPanel(model);
frame.add(createButtonPanel(), BorderLayout.WEST);
frame.add(graphicPanel, BorderLayout.CENTER);
frame.add(createTextPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBackground(Color.orange);
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
JButton buttonOne = new JButton("Button number 1");
buttonOne.addActionListener(new ButtonOneListener());
panel.add(buttonOne);
JButton buttonTwo = new JButton("Button number 2");
buttonTwo.addActionListener(new ButtonTwoListener());
panel.add(buttonTwo);
return panel;
}
private JPanel createTextPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
JLabel popeLabelTitle = new JLabel("What does the label say?");
popeLabelTitle.setFont(new Font(Font.MONOSPACED, Font.BOLD, 24));
panel.add(popeLabelTitle, BorderLayout.NORTH);
textArea = new JTextArea(4, 30);
textArea.setEditable(false);
textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 20));
textArea.setText("Default label");
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
panel.add(textArea, BorderLayout.CENTER);
return panel;
}
public class GraphicPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final DrawingModel model;
public GraphicPanel(DrawingModel model) {
this.model = model;
this.setPreferredSize(new Dimension(640, 480));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
paintMyBorder(g);
if (model.getPainter() == 1) {
createSampleImage(g);
}
paintSampleText(g);
BufferedImage image = model.getSampleImage();
List<Point> origin = model.getImageOrigin();
for (Point point : origin) {
g.drawImage(image, point.x, point.y, this);
}
}
private void paintMyBorder(Graphics g) {
int width = getWidth();
int height = getHeight();
int lineThickness = 3;
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
g.setColor(Color.YELLOW);
g.fillRect(0, lineThickness, width, height - 2 * lineThickness);
}
private void paintSampleText(Graphics g) {
BufferedImage image = model.getSampleText();
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g.drawImage(image, x, y, this);
}
private void createSampleImage(Graphics g) {
BufferedImage image = model.getSampleImage();
int x = (int) (Math.random() * (getWidth() - image.getWidth()));
int y = (int) (Math.random() * (getHeight() - image.getHeight()));
model.addNewImageOrigin(new Point(x, y));
}
}
public class ButtonOneListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("Reaction to button number 1: change of label.");
model.setPainter(0);
graphicPanel.repaint();
}
}
public class ButtonTwoListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
textArea.setText("Reaction to button number 2: change of label + "
+ "drawing images over gPanel.");
model.setPainter(1);
graphicPanel.repaint();
}
}
public class DrawingModel {
private int painter;
private final BufferedImage sampleText;
private final BufferedImage sampleImage;
private final List<Point> imageOrigin;
public DrawingModel() {
this.painter = 0;
this.sampleText = createBufferedImage(Color.BLUE);
this.sampleImage = createBufferedImage(Color.MAGENTA);
this.imageOrigin = new ArrayList<>();
}
private BufferedImage createBufferedImage(Color color) {
BufferedImage image = new BufferedImage(64, 64,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(color);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.dispose();
return image;
}
public void addNewImageOrigin(Point point) {
this.imageOrigin.add(point);
}
public int getPainter() {
return painter;
}
public void setPainter(int painter) {
this.painter = painter;
}
public BufferedImage getSampleText() {
return sampleText;
}
public BufferedImage getSampleImage() {
return sampleImage;
}
public List<Point> getImageOrigin() {
return imageOrigin;
}
}
}

Can't get absolute JLabel location

My JFrame uses a BorderLayout and it has a JLabel nested in several panels with different layout managers. I've tried several methods, however, cannot get the true position of where it sits in the frame.
I made a test UI and it seems like when other components are added the getX and getY parameters do not update. Other methods like getLocation do not provide a correct result either. Is there any way to obtain the exact location without manually calculating every possible offset from each component.
I am tracking the stated positions of the label (content) using a similar sized panel called content2 in the glass pane which I want to sit underneath content perfectly.
public class test {
private Dimension pSize = new Dimension(100,100);
private JFrame frame = new JFrame();
public static void main(String[] args) {
new test();
}
public test() {
//setup frame basics
frame.setPreferredSize(new Dimension(500,500));
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// setup GUI
JMenuBar j = new JMenuBar();
JMenuItem a = new JMenuItem("lol");
j.add(a);
JPanel j2 = new JPanel();
//setup main panel
JPanel main = new JPanel();
main.setBackground(Color.DARK_GRAY);
//setup side panel
FlowLayout f1 = new FlowLayout(FlowLayout.LEADING);
f1.setHgap(10);
f1.setVgap(0);
JPanel side = new JPanel();
side.setLayout(new BorderLayout());
side.setBackground(Color.gray);
side.setPreferredSize(new Dimension(150,100));
//setup JLabel (the main focus)
JLabel content = new JLabel("a");
content.setOpaque(true);
content.setBackground(Color.blue);
content.setPreferredSize(pSize);
// Setup the internal panels of side
JPanel top = new JPanel();//The panel where CONTENT is, the main focus
JPanel bot = new JPanel();
top.setBackground(Color.WHITE);
bot.setBackground(Color.orange);
top.setLayout(f1);
top.add(content);
side.add(top, BorderLayout.NORTH);
side.add(bot, BorderLayout.CENTER);
frame.add(main, BorderLayout.CENTER);
frame.add(side, BorderLayout.WEST);
frame.add(j2, BorderLayout.NORTH);
frame.setJMenuBar(j);
frame.pack();
frame.setVisible(true);
//Setting up the glass panel
JPanel pane = new JPanel();
pane.setLayout(null);
pane.setOpaque(false);
JPanel content2 = new JPanel();
content2.setBackground(Color.red);
content.revalidate();
int x = content.getX();
int y = content.getY();
// y = (int) content.getLocation().getY(); //returns a completely wrong location
//y = (int) content.getLocationOnScreen(); //returns a completely wrong location
/*
Point p = new Point();
p.setLocation(x, y);
p = SwingUtilities.convertPoint(content2, x, y, frame);
//SwingUtilities.convertPoint(content, p, frame);
y = (int) p.getY();
*
* Tried multiple SwingUtility converions to no avail
*
*/
// y = y +j.getHeight() + j2.getHeight(); // Manually calculating the Y off set works successfully but is too tedious for large project
y = y + content.getHeight();
content2.setBounds(x,y,100,100);
pane.add(content2);
frame.setGlassPane(pane);
frame.getGlassPane().setVisible(true);
frame.pack();
}
}
//frame.getContentPane().add(content);
//frame.add(content);
frame.setPreferredSize(new Dimension(500,500));
content.setBorder(BorderFactory.createEmptyBorder());
side.setLayout(new BorderLayout());
JPanel top = new JPanel();
JPanel bot = new JPanel();
top.setBackground(Color.WHITE);
bot.setBackground(Color.orange);
side.add(top, BorderLayout.NORTH);
top.setLayout(f1);
top.add(content);
side.add(bot, BorderLayout.CENTER);
frame.add(main, BorderLayout.CENTER);
frame.add(j2, BorderLayout.NORTH);
frame.add(side, BorderLayout.WEST);
frame.pack();
frame.setVisible(true);
JPanel pane = new JPanel();
pane.setLayout(null);
pane.setOpaque(false);
JPanel content2 = new JPanel();
content2.setBackground(Color.red);
content.revalidate();
int x = content.getX();
int y = content.getY();
// y = y +j.getHeight() + j2.getHeight();
y = y + content.getHeight();
content2.setBounds(x,y,100,100);
pane.add(content2);
frame.setGlassPane(pane);
frame.getGlassPane().setVisible(true);
frame.pack();
}
}
Conceptually you could make use of SwingUtilities.convertPoint or SwingUtilities.convertRectangle to convert between container contexts, for example...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GlassPane glassPane = new GlassPane();
JFrame frame = new JFrame();
frame.setGlassPane(glassPane);
frame.add(new MainPane(glassPane));
glassPane.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface Tracker {
public void addTrackable(Trackable trackable);
public void removeTrackable(Trackable trackable);
}
public interface Trackable {
public JComponent[] getTrackedComponents();
}
public class MainPane extends JPanel {
private JLabel label = new JLabel("Catch me if you can");
public MainPane(Tracker tracker) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(32, 32, 32, 32));
add(label);
tracker.addTrackable(new Trackable() {
#Override
public JComponent[] getTrackedComponents() {
return new JComponent[] { label };
}
});
}
}
public class GlassPane extends JPanel implements Tracker {
private List<Trackable> trackables = new ArrayList<>(8);
public GlassPane() {
setOpaque(false);
}
#Override
public void addTrackable(Trackable trackable) {
trackables.add(trackable);
revalidate();
repaint();
}
#Override
public void removeTrackable(Trackable trackable) {
trackables.remove(trackable);
revalidate();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
for (Trackable trackable : trackables) {
for (JComponent component : trackable.getTrackedComponents()) {
Rectangle relativeBounds = SwingUtilities.convertRectangle(component.getParent(), component.getBounds(), this);
g2d.draw(relativeBounds);
}
}
g2d.dispose();
}
}
}
Well, that's pretty boring, it's one component inside one container, let's trying something a little more complicated...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GlassPane glassPane = new GlassPane();
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(2, 2, 8, 8));
frame.add(new MainPane(glassPane));
frame.add(new MainPane(glassPane));
frame.add(new MainPane(glassPane));
frame.add(new MainPane(glassPane));
frame.setGlassPane(glassPane);
glassPane.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface Tracker {
public void addTrackable(Trackable trackable);
public void removeTrackable(Trackable trackable);
}
public interface Trackable {
public JComponent[] getTrackedComponents();
}
public class MainPane extends JPanel {
private JLabel label = new JLabel("Catch me if you can");
public MainPane(Tracker tracker) {
setLayout(new GridBagLayout());
setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY, 1, true), new EmptyBorder(32, 32, 32, 32)));
add(label);
tracker.addTrackable(new Trackable() {
#Override
public JComponent[] getTrackedComponents() {
return new JComponent[]{label};
}
});
}
}
public class GlassPane extends JPanel implements Tracker {
private List<Trackable> trackables = new ArrayList<>(8);
private List<Color> masterColors = new ArrayList<>(Arrays.asList(new Color[]{
Color.RED,
Color.GREEN,
Color.BLUE,
Color.CYAN,
Color.DARK_GRAY,
Color.GRAY,
Color.MAGENTA,
Color.ORANGE,
Color.PINK,
Color.YELLOW,}));
public GlassPane() {
setOpaque(false);
}
#Override
public void addTrackable(Trackable trackable) {
trackables.add(trackable);
revalidate();
repaint();
}
#Override
public void removeTrackable(Trackable trackable) {
trackables.remove(trackable);
revalidate();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
List<Color> colors = new ArrayList<>(masterColors);
for (Trackable trackable : trackables) {
for (JComponent component : trackable.getTrackedComponents()) {
if (colors.isEmpty()) {
colors = new ArrayList<>(masterColors);
}
g2d.setColor(colors.remove(0));
Rectangle relativeBounds = SwingUtilities.convertRectangle(component.getParent(), component.getBounds(), this);
g2d.draw(relativeBounds);
}
}
g2d.dispose();
}
}
}
Here is a new smipler example program, trying to keep as close to your code as possible, that uses the convertRectangle but I can't manage to run it correctly
int y = (int) (r.getY() + r.getHeight()); ... are you deliberately trying to offset the "overlay"? This seems weird to me.
Another issue is, how does the GlassPane know when the child has changed position/size
So, I modified your code, getting rid of the "modification" to the x/y position (so I'm 100% sure that the conversion between context spaces is correct) and added a ComponentListener to monitor changes to the "target" component
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
public class Main {
private Dimension pSize = new Dimension(100, 100);
private JFrame frame = new JFrame();
private JLabel content = new JLabel("Grief");
private JPanel content2 = new JPanel();
private SidePane sidePane = new SidePane();
private GlassPane glass = new GlassPane();
private Menu menu = new Menu();
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
content.setBackground(Color.green);
content.setPreferredSize(pSize);
content.setOpaque(true);
//setup frame basics
frame.setPreferredSize(new Dimension(500, 500));
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setGlassPane(glass);
frame.add(new MainPane());
// glass.setNewLocation();
// glass.revalidate();
frame.getGlassPane().setVisible(true);
// glass.setNewLocation();
frame.pack();
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
public MainPane() {
//this.setBackground(Color.orange);
this.setLayout(new BorderLayout());
this.add(sidePane, BorderLayout.WEST);
this.add(menu, BorderLayout.NORTH);
}
}
public class SidePane extends JPanel {
public SidePane() {
FlowLayout f1 = new FlowLayout(FlowLayout.LEADING);
this.setLayout(f1);
this.setBackground(Color.blue);
this.add(content);
}
}
public class Menu extends JPanel {
public Menu() {
this.setBackground(Color.orange);
}
}
public class GlassPane extends JPanel {
private Rectangle target;
public GlassPane() {
this.setOpaque(false);
setLayout(null);
content2.setBackground(Color.BLACK);
content2.setPreferredSize(pSize);
content2.setOpaque(true);
add(content2);
content.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
updateOverlay();
}
#Override
public void componentMoved(ComponentEvent e) {
updateOverlay();
}
});
}
protected void updateOverlay() {
// Rectangle t = new Rectangle();
// t.setBounds((int) content.getLocation().getX(), (int) content.getLocation().getY(), content.getWidth(), content.getHeight());
// Rectangle r = SwingUtilities.convertRectangle(content.getParent(), content.getBounds(), this);
// Rectangle r = SwingUtilities.convertRectangle(content.getParent(), content.getBounds(), this);
target = SwingUtilities.convertRectangle(content.getParent(), content.getBounds(), this);
content2.setBounds(target);
// r = SwingUtilities.convertRectangle(content.getParent(), t, this);
// int x = (int) r.getBounds().getX();
// x = (int) r.getX();
// int y = (int) (r.getY() + r.getHeight());
//
// content2.setBounds(x, y, 100, 100);
// this.add(content2);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g.create();
if (target != null) {
g2d.setColor(Color.RED);
g2d.draw(target);
}
g2d.dispose();
}
}
}
If you have the coordinate within the component, transfer it to screen coordinates using your component's convertPointToScreen(). Afterwards you can transfer back to see where in the window it sits by using the frame's convertPointFromScreen().
Or eliminate one of the two steps by directly using convertPoint().
Fixed the positioning issue using #MadProgrammer 's method of SwingUtilities.convertRectangle and called a new method at the end of the constructor which positioned the tracker panel.
Created a separate class for the glass pane
private class GlassPane extends JPanel {
public GlassPane() {
this.setLayout(null);
}
public void setNewLocation() {
Rectangle r = SwingUtilities.convertRectangle(top, content.getBounds(), this);
JPanel content2 = new JPanel();
int x = (int) r.getBounds().getX();
x = (int) r.getX();
int y = (int) (r.getY() + r.getHeight() + 1);
content2.setBounds(x, y, 100,100);
this.add(content2);
}
}
And added a call to the new method setNewLocation() at the end of the constructor
public test() {
**...**
frame.pack();
frame.setVisible(true);
glass.setNewLocation();
}

Java application creating Rectangle when button is pressed

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

Image not appearing in jbutton with wordGen

The image isn't being painted when this is run with WordGen, how do i fix this?
When I run this without wordgen I can get the image to appear. I'm not sure what i'm doing wrong since i'm not getting any errors.
Any help is appreciated.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class tfot extends JComponent{
private static final long serialVersionUID = 1L;
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showGUI(args);
}
});
}
public static void showGUI(String[] args) {
JPanel displayPanel = new JPanel();
JButton okButton = new JButton("Did You Know?");
okButton.setFont(new Font("Times", Font.TRUETYPE_FONT, 100));
final JLabel jLab = new JLabel();
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jLab.setText(wordGen());
}
});
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
content.add(okButton, BorderLayout.SOUTH);
content.add(jLab, BorderLayout.NORTH);
JFrame window = new JFrame("Window");
window.setContentPane(content);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(Toolkit.getDefaultToolkit().getImage("Pictures/background1.png"), 0, 0, this);
}
public static String wordGen() {
String[] wordListOne = {"generic text","hi",};
int oneLength = wordListOne.length;
int rand1 = (int) (Math.random() * oneLength);
String phrase = wordListOne[rand1] + " ";
return phrase;
}
}
First...
Don't load resources or perform long running tasks within the paint methods, these may be called a number of times in quick succession. Instead, load the images before hand and paint them as needed...
public Tfot() {
setLayout(new BorderLayout());
try {
background = ImageIO.read(new File("pictures/background1.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
g.drawImage(background, 0, 0, this);
}
}
Generally, you are discouraged from overriding paint and instead should use paintComponent, lots of reasons, but generally, this is where the background is painted...
Second...
You need to add Tfot to something that is displayable, otherwise it will never be painted
JFrame window = new JFrame("Window");
window.setContentPane(new Tfot());
window.add(content);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
Thrid...
JPanel by default is not transparent, you need to set it's opaque property to false
JPanel displayPanel = new JPanel();
displayPanel.setOpaque(false);
//...
JPanel content = new JPanel();
content.setOpaque(false);
Then it will allow what ever is below it to show up (ie, the background image)
Take a look at Painting in AWT and Swing, Performing Custom Painting and Reading/Loading an Image for more details
Fourth...
You need to learn the language basics for embarking on advance topics like GUI and custom painting, without this basic knowledge, this topics will bite you hard.
You need to declare background as a instance field of the class Tfot
private BufferedImage background;
public Tfot() {
Updated - Fully runnable example
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Tfot extends JComponent {
private static final long serialVersionUID = 1L;
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showGUI(args);
}
});
}
public static void showGUI(String[] args) {
JPanel displayPanel = new JPanel();
displayPanel.setOpaque(false);
JButton okButton = new JButton("Did You Know?");
okButton.setFont(new Font("Times", Font.TRUETYPE_FONT, 100));
final JLabel jLab = new JLabel();
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jLab.setText(wordGen());
}
});
JPanel content = new JPanel();
content.setOpaque(false);
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
content.add(okButton, BorderLayout.SOUTH);
content.add(jLab, BorderLayout.NORTH);
Tfot tfot = new Tfot();
tfot.setLayout(new BorderLayout());
tfot.add(content);
JFrame window = new JFrame("Window");
window.setContentPane(tfot);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
}
private BufferedImage background;
public Tfot() {
try {
background = ImageIO.read(new File("Pictures/background1.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, this);
}
public static String wordGen() {
String[] wordListOne = {"generic text", "hi",};
int oneLength = wordListOne.length;
int rand1 = (int) (Math.random() * oneLength);
String phrase = wordListOne[rand1] + " ";
return phrase;
}
}

actionPerformed skip a step

I want everytime i click on the button "bouton" to execute the function
boutonPane.Panel2(h, ....) which is supposed to display h circles. So i want 2 then 3 then 4, then 5... circles.
The problem is that it is not displaying the step with number 4. I see the function is called in the console but on the screen it does really 2, (press button) 3, (press button) 5, (press button)9. I dont see 4. I dont see 6,7,8.. Could you tell me what is the problem please? Here is the code:
public class Window extends JFrame implements ActionListener {
int lg = 1000; int lrg = 700;
int h = 2;
Panel b = new Panel();
private JButton btn = new JButton("Start");
JButton bouton = new JButton();
private JPanel container = new JPanel();
public Window(){
this.setTitle("Animation");
this.setSize(300, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
btn.addActionListener(this);
top.add(btn);
container.add(top);
this.setContentPane(container);
this.setVisible(true);
}
public void Window2()
{
System.out.println("windows2");
this.setTitle("ADHD");
this.setSize(lg, lrg);
this.setLocationRelativeTo(null);
bouton.addActionListener(this);
if(h<11)
{
Panel boutonPane = new Panel();
boutonPane.Panel2(h, Color.BLUE ,lg, lrg, this.getGraphics());
System.out.println("draw"+h);
boutonPane.add(bouton);
this.add(boutonPane);
this.setContentPane(boutonPane);
this.revalidate();
this.repaint();
}
this.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
if((JButton)e.getSource()==btn)
{
System.out.println("pressed0");
Window2();
}
if((JButton)e.getSource()==bouton)
{
h++;
System.out.println("pressed"+h);
Window2();
}
}
}
Here is a the Panel class:
public class Panel extends JPanel
{
int m;
int i=1;
int a=0, b=0, tremp=0;
Color cc;
int lgi, lrgi;
int [] ta;
int [] tb;
Graphics gi;
int u=0;
Panel()
{
}
public void Panel2(int n, Color c, int lg, int lrg, Graphics g){
m=n;
cc=c;
gi=g;
lgi=lg;
lrgi=lrg;
ta = new int [n]; ta[0]=0;
tb = new int [n]; tb[0]=0;
}
public void paintComponent( final Graphics gr){
gr.setColor(Color.red);
for(int it=0; it<m;it++)
{
ta[it]=100*it;
tb[it]=100*it;
gr.fillOval(ta[it],tb[it], 150, 150);
}
}
}
"But would you have an idea of another, correct, way to do what I want please?"
You should only have one panel for the circles. There's absolutely no need to keep creating new panel.
Use a List for Ellipse2D objects. Just loop through them in the paintComponent method.
When you want to add a new circle, just add a new Ellipse2D object to the List and call repaint()
Here's an example.
NOTE Accept Gijs Overvliet's answer, as his was the one that answered your problem. I just wanted to share some insight.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class EllipseList extends JPanel {
private static final int D_W = 700;
private static final int D_H = 500;
private static final int CIRCLE_SIZE = 50;
private List<Ellipse2D> circles;
private double x = 0;
private double y = 0;
private CirclePanel circlePanel = new CirclePanel();
public EllipseList() {
circles = new ArrayList<>();
JButton jbtAdd = createButton();
JFrame frame = new JFrame();
frame.add(jbtAdd, BorderLayout.NORTH);
frame.add(circlePanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JButton createButton() {
JButton button = new JButton("Add");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
circles.add(new Ellipse2D.Double(x, y, CIRCLE_SIZE, CIRCLE_SIZE));
x += CIRCLE_SIZE * 0.75;
y += CIRCLE_SIZE * 0.75;
circlePanel.repaint();
}
});
return button;
}
public class CirclePanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(Color.RED);
for (Ellipse2D circle : circles) {
g2.fill(circle);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_W, D_H);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new EllipseList();
}
});
}
}
Try this:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame implements ActionListener
{
int lg = 1000;
int lrg = 700;
int h = 2;
Panel b = new Panel();
private JButton btn = new JButton("Start");
JButton bouton = new JButton();
private JPanel container = new JPanel();
Panel boutonPane = new Panel();
public Window()
{
this.setTitle("Animation");
this.setSize(300, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
btn.addActionListener(this);
top.add(btn);
container.add(top);
this.setContentPane(container);
this.setVisible(true);
}
public void Window2()
{
System.out.println("windows2");
this.setTitle("ADHD");
this.setSize(lg, lrg);
this.setLocationRelativeTo(null);
bouton.addActionListener(this);
if (h < 11)
{
boutonPane.Panel2(h, Color.BLUE, lg, lrg, this.getGraphics());
System.out.println("draw" + h);
boutonPane.add(bouton);
this.add(boutonPane);
this.setContentPane(boutonPane);
updateWindow2();
}
this.setVisible(true);
}
public void updateWindow2()
{
boutonPane.Panel2(h, Color.BLUE, lg, lrg, this.getGraphics());
this.revalidate();
this.repaint();
}
public void actionPerformed(ActionEvent e)
{
if ((JButton) e.getSource() == btn)
{
System.out.println("pressed0");
Window2();
}
if ((JButton) e.getSource() == bouton)
{
h++;
System.out.println("pressed" + h);
updateWindow2();
}
}
public static void main(String[] args)
{
Test t = new Test();
}
}
What you did wrong was adding a new BoutonPane every time you clicked the button. The next time you clicked the button, you didn't click ONE button, but TWO buttons, adding two more boutonPanes, and two more buttons. This multiplies very quickly.
What I did was the following:
make boutonPane a class member variable
call window2() only once
create a method updateWindow2() for updating the circles. Call that method from window2() and actionPerformed().

Categories