Hi I would like to have the following user interface:
And when the user clicks on start, I would like to add dynamically a JPanel underneath these elements. Something like this:
I am able to generate the grid in an empty JFrame, but when I try to add it when there are more elements inside the JFrame it appears, but very small.
This is the code that I have tried. The class UITable creates the buttons and input text
public UITable(){
jfrm = new JFrame("Plants experiment");
jfrm.setLayout(new FlowLayout());
jfrm.setSize(1000, 1000);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JLabel titles for input texts
JLabel jlab_plants = new JLabel(" Enter nÂș plants: ");
JLabel jlab_time = new JLabel(" Enter evolution time: ");
jlab_prueba = new JLabel("");
//Input texts
jtf_plants = new JTextField(10);
jtf_plants.setActionCommand("numPlants");
jtf_time = new JTextField(10);
jtf_time.setActionCommand("time");
//Buttons
jbtnStart = new JButton("Start");
//Add components
jfrm.add(jlab_plants);
jfrm.add(jtf_plants);
jfrm.add(jlab_time);
jfrm.add(jtf_time);
jfrm.add(jbtnStart);
jfrm.add(jlab_prueba);
//Set visibility
jfrm.setVisible(true);
}
Adding dynamically the grid:
#Override
public void actionPerformed(ActionEvent ae) {
// ...
this.view.jfrm.add(new Grid());
this.view.jfrm.revalidate();
this.view.jfrm.repaint();
}
This is the Grid class:
public class Grid extends JPanel{
//Change Point to Plant in order to have a different color for each object
private List<Plant> fillCells;
public Grid() {
//fillCells = new ArrayList<>(25);
fillCells = PlantsControler.myPlants;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Width: "+getWidth()+" Height: "+ getHeight());
---- //Returns Width: 10 Height: 10 ------
g.clearRect(0, 0, getWidth(), getHeight());
for (Plant fillCell : fillCells) {
int cellX = 10 + (fillCell.getX() * 10);
int cellY = 10 + (fillCell.getY() * 10);
g.setColor(fillCell.getColor());
g.fillRect(cellX, cellY, 10, 10);
}
g.setColor(Color.BLACK);
g.drawRect(10, 10, 800, 500);
for (int i = 10; i <= 800; i += 10) {
g.drawLine(i, 10, i, 510);
}
for (int i = 10; i <= 500; i += 10) {
g.drawLine(10, i, 810, i);
}
}
public void fillCell(int x, int y, Color color) {
fillCells.add(new Plant(x, y, color));
repaint();
}
public void fillCell(Plant plant){
fillCells.add(plant);
repaint();
}
public void fillCell(){
repaint();
}
public void clearGrid(){
fillCells.clear();
}
Thanks in advance!!!
You can try something like below.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class DemoFrame extends JFrame {
JTextField field = new JTextField();
public DemoFrame() {
setLayout(new BorderLayout());
JPanel controlsPane = new JPanel(new FlowLayout());
controlsPane.add(new JLabel("I m a Label"));
field.setPreferredSize(new Dimension(100,20));
controlsPane.add(field);
JButton button = new JButton("I am add drawPanel");
controlsPane.add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent paramActionEvent) {
DemoFrame.this.add(new DrawPanel(), BorderLayout.CENTER);
DemoFrame.this.revalidate();
}
});
add(controlsPane,BorderLayout.NORTH);
}
public static void main(String[] args) {
DemoFrame frame = new DemoFrame();
frame.setVisible(true);
frame.pack();
}
class DrawPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawString(field.getText(), this.getWidth()/2, this.getHeight()/2);
}
}
}
Related
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();
}
I'm trying to create a Java program that draws a circle, sliders can resize the circle, 3 other sliders control RGB settings. The problem is that i cannot get the stats (diameter, area and circumference) to display in the JTextBox. Please help its driving me mad!!!
Thanks!
CircleModifier.java
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
#SuppressWarnings("serial")
public class CircleModifier extends JFrame implements ChangeListener {
public DrawingPanel drawingPanel;
public InfoPanel infoPanel;
public JPanel sizePanel;
private JPanel sliderPanel;
private JSlider sizeSlider, redColorSlider, greenColorSlider,
blueColorSlider;
private JLabel sizeLabel, redLabel, greenLabel, blueLabel;
public CircleModifier() {
super("Circle Modifier Application");
setLayout(new BorderLayout());
drawingPanel = new DrawingPanel();
add(drawingPanel, BorderLayout.CENTER);
sliderPanel = new JPanel();
add(sliderPanel, BorderLayout.EAST);
sliderPanel.setBackground(Color.WHITE);
infoPanel = new InfoPanel();
add(infoPanel, BorderLayout.SOUTH);
sliderPanel.setLayout(new GridLayout(2, 4, 0, 1));
sizeLabel = new JLabel("-Size-");
sizeLabel.setForeground(Color.BLACK);
setSizeSlider(new JSlider(JSlider.VERTICAL, 0, 350, 10));
getSizeSlider().setMajorTickSpacing(50);
getSizeSlider().setMinorTickSpacing(25);
getSizeSlider().setPaintTicks(true);
getSizeSlider().setPaintLabels(true);
getSizeSlider().setBackground(Color.WHITE);
getSizeSlider().addChangeListener(this);
redColorSlider = new JSlider(JSlider.VERTICAL, 0, 255, 0);
redColorSlider.setMajorTickSpacing(20);
redColorSlider.setMinorTickSpacing(5);
redColorSlider.setPaintTicks(true);
redColorSlider.setPaintLabels(true);
redColorSlider.setBackground(Color.WHITE);
redColorSlider.addChangeListener(this);
redLabel = new JLabel("-Red-");
redLabel.setForeground(Color.RED);
greenColorSlider = new JSlider(JSlider.VERTICAL, 0, 255, 0);
greenColorSlider.setMajorTickSpacing(20);
greenColorSlider.setMinorTickSpacing(5);
greenColorSlider.setPaintTicks(true);
greenColorSlider.setPaintLabels(true);
greenColorSlider.setBackground(Color.WHITE);
greenColorSlider.addChangeListener(this);
greenLabel = new JLabel("-Green-");
greenLabel.setForeground(Color.GREEN);
blueColorSlider = new JSlider(JSlider.VERTICAL, 0, 255, 0);
blueColorSlider.setMajorTickSpacing(20);
blueColorSlider.setMinorTickSpacing(5);
blueColorSlider.setPaintTicks(true);
blueColorSlider.setPaintLabels(true);
blueColorSlider.setBackground(Color.WHITE);
blueColorSlider.addChangeListener(this);
blueLabel = new JLabel("-Blue-");
blueLabel.setForeground(Color.BLUE);
sliderPanel.add(sizeLabel);
sliderPanel.add(redLabel);
sliderPanel.add(greenLabel);
sliderPanel.add(blueLabel);
sliderPanel.add(getSizeSlider());
sliderPanel.add(redColorSlider);
sliderPanel.add(greenColorSlider);
sliderPanel.add(blueColorSlider);
setSize(800, 500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void stateChanged(ChangeEvent e) {
int size = getSizeSlider().getValue();
drawingPanel.setDiameter(size);
sizeLabel.setText("-Size-");
int red = redColorSlider.getValue();
int green = greenColorSlider.getValue();
int blue = blueColorSlider.getValue();
drawingPanel.setNewCircleColor(red, green, blue);
redLabel.setText("-Red-");
greenLabel.setText("-Green-");
blueLabel.setText("-Blue-");
}
public static void main(String[] args) {
new CircleModifier();
}
public JSlider getSizeSlider() {
return sizeSlider;
}
public void setSizeSlider(JSlider sizeSlider) {
this.sizeSlider = sizeSlider;
}
}
InfoPane.java
import javax.swing.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import java.awt.*;
import java.awt.event.*;
import java.awt.*;
#SuppressWarnings("serial")
public class InfoPanel extends JPanel {
JTextArea textarea;
JLabel label;
private JTextArea display;
public InfoPanel() {
setLayout(new FlowLayout());
label = new JLabel("Information");
add(label);
display = new JTextArea(5, 30);
display.setText("The Radius is: " + "\nThe Diameter is: "
+ "Dynamic diameter to display here!" + "\nThe Area is: "
+ "\nThe Circumference is: ");
add(display);
}
}
DrawingPanel.java
import javax.swing.*;
import java.awt.*;
#SuppressWarnings("serial")
public class DrawingPanel extends JPanel {
public static String size;
int diameter = 1;
int red = 255, green = 255, blue = 255;
Color newCircleColor = new Color(red, green, blue);
public void paintComponent(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(newCircleColor);
g.fillOval(10, 10, diameter, diameter);
}
public void setDiameter(int newSize) {
diameter = newSize;
repaint();
}
public void setNewCircleColor(int red, int green, int blue) {
newCircleColor = new Color(red, green, blue);
repaint();
}
}
Give InfoPanel a public method,
public void textareaSetText(String text) {
textarea.setText(text);
}
And inside of this, set the text of the JTextArea variable.
Then call this method from within CircleModifier's stateChanged(...) method. If you want to append text, you could also give InfoPanel a similar textareaAppendText(String text) method.
I have one class Names and it has a JTextField. I am trying to place getText from this textfield and save it in the variable nameString1. I then want the other class Game to call Names and place the string collected from ``the JTextField onto a label. For some reason it is not displaying. Please let me know if there are any rookie errors, I am only year 10.
Names
package com.aqagame.harrykitchener;
import java.awt.BorderLayout;
import java.awt.GridLayout;
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.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Names
{
private JLabel player1Label;
private JTextField player1Input;
private JButton nextButton;
public String nameString1;
public Names()
{
final JFrame window = new JFrame("Player 1 username");
JPanel firstPanel = new JPanel(new GridLayout(3,2));
player1Label = new JLabel("Player 1");
player1Input = new JTextField();
nextButton = new JButton("Next");
firstPanel.add(player1Label);
firstPanel.add(player1Input);
firstPanel.add(nextButton);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
nameString1 = player1Input.getText();
System.out.print(nameString1);
Names2 names2Call = new Names2();
window.dispose();
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(firstPanel);
window.setSize(250, 150);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Names();
}
});
}
}
Game
package com.aqagame.harrykitchener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Game
{
private JLabel player1Str, player2Str;
public Game()
{
JFrame window = new JFrame ("Main Game");
JPanel drawPanel = new JPanel(new GridLayout(3, 1))
{
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() / 4;
int height = getHeight() / 11;
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
}
};
Names namesCall2 = new Names();
player1Str = new JLabel(namesCall2.nameString1);
drawPanel.add(player1Str);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawPanel);
window.setSize(700, 600);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Game();
}
});
}
}
The problem is that you are setting the label without getting the textfield text. The JLabel on your Game wont change by the time you click the button..
Okie I made some change in you classes What I did is that I maid an interface which will be called when your button is pressed
Here is the interface:
public interface Lawl {
public void changename(String name);
}
I then implemented this interface to the game:
public class Game implements Lawl
{
private JLabel player1Str, player2Str;
JPanel drawPanel;
Names namesCall2;
public Game()
{
JFrame window = new JFrame ("Main Game");
drawPanel = new JPanel(new GridLayout(3, 1))
{
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() / 4;
int height = getHeight() / 11;
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
}
};
// Names namesCall2 = new Names(this);
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
namesCall2 = new Names(Game.this);
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawPanel);
window.setSize(700, 600);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Game();
}
});
}
#Override
public void changename(String name) {
System.out.println("I am clicked");
player1Str = new JLabel(name);
drawPanel.add(player1Str);
drawPanel.revalidate();
}
}
In the names class:
public class Names
{
private JLabel player1Label;
private JTextField player1Input;
private JButton nextButton;
public String nameString1;
public Names(){}
public Names(final Lawl game)
{
final JFrame window = new JFrame("Player 1 username");
JPanel firstPanel = new JPanel(new GridLayout(3,2));
player1Label = new JLabel("Player 1");
player1Input = new JTextField();
nextButton = new JButton("Next");
firstPanel.add(player1Label);
firstPanel.add(player1Input);
firstPanel.add(nextButton);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
nameString1 = player1Input.getText();
System.out.print(nameString1);
game.changename(nameString1);
// Names2 names2Call = new Names2();
window.dispose();
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(firstPanel);
window.setSize(250, 150);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
How it works??
I created an interface and implemented it to the game class then pass the reference of the interface to the Names class which will then be called when button is clicked..
when it is called game.changename(nameString1);by the button clicked it will then be called on the game class as you could see there is an method from the implemented inteface in the game class that will be called when you click the button..
If you want to chain data dont create a new Main thread to just execute a new Window.. just use the one I did in the code..
replace
public final static JTextField player1Input;
instead of
private JTextField player1Input;
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().
I am developing a program where if the menu item "show grid line" is clicked, the drawing area below the menu bar will draw grid lines on the grid.
EDIT: Below are the components to the program. I turned any parts that are not important for this issue into comments.
import java.awt.Color;
import java.awt.Image;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
//main initializer
public class lineFollower {
frameDesign frame;
//private static Image icon = new ImageIcon("images/icon copy.jpg").getImage();
public static void main(String[] args) {
//make new frame
JFrame frame = new frameDesign();
frame.setSize(1000,700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setLocale(null);
frame.setTitle("Line Follower Program 1.0");
//frame.setIconImage(icon);
}
}
This is the frame design (omitting parts as well):
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.*;
public class frameDesign extends JFrame {
//data fields
//JPanel DataPanel;
//ListPanel ListPanel;
DrawingPanel DrawingPanel;
grid gridbox;
menuPanel menu;
//ArrayList<Rectangle> Rectangles;
//ArrayList<Circle> Circles;
//ArrayList<Triangle> Triangles;
public int newvalue = 0;
public int[] griddim;
public int gridwidth, gridheight;
BorderLayout layout;
//combine data into frame
public frameDesign(){
//Rectangles = new ArrayList<Rectangle>();
//Circles = new ArrayList<Circle>();
//Triangles = new ArrayList<Triangle>();
//Layout: Border
BorderLayout layout = new BorderLayout();
setLayout(layout);
//Assemble the Menu
menu = new menuPanel();
//Assemble the List Panel which also includes the animation buttons
//ListPanel = new ListPanel();
//Create the gridbox
gridbox = new grid();
gridbox.setPreferredSize(new Dimension(200,200));
gridbox.setSize(500,200);
griddim = gridbox.getgriddim();
gridwidth = griddim[0];
gridheight = griddim[1];
//Data Panel consists of ListPanel, AnimatePanel, and DrawingPanel
//DataPanel = new JPanel(new FlowLayout());
//DataPanel.add(DrawingPanel= new DrawingPanel());
//DataPanel.add(ListPanel = new ListPanel());
//DataPanel.setSize(250,700);
//DataPanel.setBackground(Color.getHSBColor(150f, 100f, 100f));
//DataPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
add(gridbox, BorderLayout.CENTER);
add(menu, BorderLayout.NORTH);
//add(DataPanel, BorderLayout.EAST);
//getPoints pointfinder = new getPoints();
//pointgrabber pointfinder2 = new pointgrabber();
//gridbox.addMouseListener(pointfinder2);
//gridbox.addMouseMotionListener(pointfinder);
//ActionListeners for Menus
menu.ShowLine.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
//show the grid
if (gridbox.isgridline()==true){
gridbox.gridline(false);
}
else if (gridbox.isgridline()==false){
gridbox.gridline(true);
}
}
});
}
The next pile of code is for the grid creation:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.BorderFactory;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
/*
* This is the design for the grid
*/
public class grid extends JPanel {
//data fields
boolean isgridline;
private static int startX = 50;
private static int startY = 50;
private int intervalline;
private int[] griddim;
//gridPanel
grid(){
setBorder(BorderFactory.createLineBorder(Color.BLACK));
griddim = new int[2];
griddim[0] = 500;
griddim[1] = 500;
isgridline = false;
intervalline = 20;
}
//Paints grid
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
//GridBox
g.setColor(Color.BLACK);
g.drawRect(50, 50, griddim[0], griddim[1]);
g.setColor(Color.WHITE);
g.fillRect(50, 50, griddim[0], griddim[1]);
//draw grid lines
if (isgridline){
g.setColor(Color.getHSBColor(150, 150, 200));
//vertical lines
for (int v = 0; v <griddim[0]; v = v+intervalline){
g.drawLine(startX, 50,
startX, 50+griddim[1]);
startX = startX+intervalline;
}
//horizontal lines
for (int v=0; v<griddim[1]; v=v+intervalline){
g.drawLine(50, startY, 50+griddim[0], startY);
startY = startY+intervalline;
}
}
}
//set grid dimensions
public void setgridbox(int[] dim){
griddim=dim;
}
//get grid dimensions
public int[] getgriddim(){
return griddim;
}
//set the grid line true or false
public void gridline(boolean islines){
isgridline=islines;
repaint();
}
//get gridline true or false
public boolean isgridline(){
return isgridline;
}
//set grid line intervals
//public void setinterval(int interval){
//intervalline=interval;
//repaint();
//}
}
Lastly, the menu:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.EventListener;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.event.MenuEvent;
/*
* Class just for the menu panel
*/
public class menuPanel extends JMenuBar {
JMenuItem New, Save, Open, Exit;
JMenu fileMenu, gridMenu;
JMenuItem GridDim, GridLine, ShowLine;
menuPanel(){
//Assemble file menu
fileMenu = new JMenu("File");
New = new JMenuItem("New");
Save = new JMenuItem("Save");
Open = new JMenuItem("Open");
Exit = new JMenuItem("Exit");
fileMenu.add(New);
fileMenu.add(Save);
fileMenu.add(Open);
fileMenu.addSeparator();
fileMenu.add(Exit);
add(fileMenu);
//Assemble grid menu
gridMenu = new JMenu("Grid");
GridDim = new JMenuItem("Dimension");
GridLine = new JMenuItem("Change Grid Line Interval");
ShowLine = new JMenuItem("Show Grid Lines");
gridMenu.add(GridDim);
gridMenu.add(GridLine);
gridMenu.add(ShowLine);
add(gridMenu);
}
}
When the "show grid lines" button in the menu bar under grid is clicked, it turns on the grid lines and turns off the grid lines once each. It stops working after that... What can I do such that the grid lines show up on and off again more than just once?
I did a really quick test, but because you've not provided us with runnable example, it's not possible to reproduce your problem.
What I "suspect" is your for-loop is crashing for some reason (the griddim is null or there's an out bounds exception) which is causing the EDT to become unstable.
Until you enlighten use with a repeatable, runnable example, we're never going to be sure
public class TestGridLine {
public static void main(String[] args) {
new TestGridLine();
}
public TestGridLine() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new GridPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GridPane extends JPanel {
private boolean gridline;
public GridPane() {
setLayout(new GridBagLayout());
JButton btn = new JButton("Grid");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setGridLine(!isGridLine());
}
});
add(btn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth() - 1;
int height = getHeight() - 1;
//GridBox
g.setColor(Color.BLACK);
g.drawRect(0, 0, width - 1, height - 1);
g.setColor(Color.WHITE);
g.fillRect(1, 1, width - 1, height - 1);
//draw grid lines
if (gridline) {
g.setColor(Color.getHSBColor(150, 150, 200));
//vertical lines
for (int v = 0; v < width - 2; v += 10) {
g.drawLine(v, 1, v, height - 2);
}
//horizontal lines
for (int v = 0; v < height - 2; v += 10) {
g.drawLine(1, v, width - 2, v);
}
}
}
//returns boolean gridline
public boolean isGridLine() {
return gridline;
}
//set the grid line true or false
public void setGridLine(boolean islines) {
if (islines != gridline) {
gridline = islines;
repaint();
}
}
}
}