public class FaceMain extends JFrame {
CreateFace p1 = new CreateFace();
private ControlPanel panel;
public FaceMain(ControlPanel value) {
panel = value;
JFrame main = new JFrame();
main.setTitle("Face Frame");
main.setSize(new Dimension(600, 600));
main.setLocationRelativeTo(null);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setVisible(true);
Container c = main.getContentPane();
main.add(p1);
panel.eyesSetE(true);
JFrame control = new JFrame();
control.setTitle("Control Panel");
control.setSize(new Dimension(300, 300));
control.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
control.setLocationRelativeTo(main);
control.setVisible(true);
ControlPanel p2 = new ControlPanel(p1);
control.add(p2);
}
}
public class ControlPanel extends JPanel {
boolean eyesSetEdit = false, faceSetEdit = false, mouthSetEdit = false,
editEyes;
private Color purple = new Color(133, 22, 145);
private CreateFace face;
private CreateFace p1;
public ControlPanel(CreateFace value) {
face = value;
p1 = value;
setLayout(new GridLayout(4, 0));
JButton change = new JButton("Click");
add(change);
JLabel info = new JLabel("Click Above To Change Features",
JLabel.CENTER);
add(info);
JLabel info1 = new JLabel("Slide Below To Change Size", JLabel.CENTER);
add(info1);
JScrollBar slider = new JScrollBar(Scrollbar.HORIZONTAL, 0, 100, 0, 300);
add(slider);
public void eyesSetE(boolean x) {
eyesSetEdit = x;
}
public boolean getEyesSet() {
return eyesSetEdit;
}
I have expanded my class to try and change a boolean value which will be used exstensivly in the ControlPanel class to make decisions however everytime I start the program I get a nullpointerexception at the line "panel.eyesSetE(true);" Even if I try and call getEyesSet() I still recieve a nullpointer
You never change the instance of circle within the CreateCircle class, so it never changes size.
Don't use static for what should be an instance variable, instead make use of the instance of the class you created and provide a setter method to change the variable...
Basically, this example passes the instance of p1 to the ControlPanel pane so that it has some context by which to manipulate what you have previously created.
import datetest.CircleShort.ControlPanel;
import datetest.CircleShort.CreateCircle;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Scrollbar;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollBar;
public class CircleShort extends JFrame {
CreateCircle p1 = new CreateCircle();
public CircleShort() {
CreateCircle p1 = new CreateCircle();
JFrame main = new JFrame();
main.setSize(new Dimension(600, 600));
main.setLocationRelativeTo(null);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setVisible(true);
Container c = main.getContentPane();
main.add(p1);
JFrame control = new JFrame();
control.setTitle("Control Panel");
control.setSize(new Dimension(300, 300));
control.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
control.setLocationRelativeTo(main);
control.setVisible(true);
ControlPanel p2 = new ControlPanel(p1);
control.add(p2);
}
static class CreateCircle extends JComponent {
int circleX = 100;
Ellipse2D.Double circle;
public CreateCircle() {
circle = new Ellipse2D.Double(circleX, 50, 400, 350);
}
public void setCircleX(int x) {
circleX = x;
circle = new Ellipse2D.Double(circleX, 50, 400, 350);
repaint();
}
public int getCircleX() {
return circleX;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fill(circle);
}
}
class ControlPanel extends JComponent {
private CreateCircle circle;
public ControlPanel(CreateCircle value) {
circle = value;
setLayout(new GridLayout(4, 0));
JButton change = new JButton("Click");
add(change);
JLabel info = new JLabel("Click Above To Change Color",
JLabel.CENTER);
add(info);
JLabel info1 = new JLabel("Slide Below To Change Size",
JLabel.CENTER);
add(info1);
JScrollBar slider = new JScrollBar(Scrollbar.HORIZONTAL, 0, 100, 0,
300);
add(slider);
slider.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
System.out.println(e.getValue());
circle.setCircleX((circle.getCircleX() + (e.getValue() % 5)));
}
});
}
}
static class CircleRun {
public static void main(String[] args) {
new CircleShort();
}
}
}
static is evil until you truly understand how to use it. If you find yourself making some field or method static just because you can't seem to figure out how to access it, then you are likely doing something wrong, be careful with it...
The next question this actually raises is, "why?"
A JSlider would be a more appropriate control to use and would be conceptually easier for a user to understand
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 need to calculate window decorations somehow. So I override JDialog's constructor. But when I call get_decoration_size() it sometimes returns wrong values. And my thought was: window creates later than get_decoration_size() executes(strange, because both in same thread and in same constructor). So I decided to sleep for a second, and it worked, and now decorations always valid.
My question is: is there a way to "join" to the creating process(wait until window is shown by setVisible(true))? If so, it must be something to replace unsafe_sleep(1000).
package swing.window;
import db.db;
import javax.swing.*;
import java.awt.*;
import static swing.util.*;
import static util.util.unsafe_sleep;
public class calc_decor extends JDialog {
{
//some initializations
setLayout(null);
setResizable(false);
JLabel label = new JLabel("Loading...");
add(label);
setxy(label, 3, 3);
fit(label);
setsize(this, label.getWidth() + 100, label.getHeight() + 100);
window_to_center(this);
setVisible(true);//trying to draw
unsafe_sleep(1000);//without that it looks like get_decoratoin_size()
//is called before setVisible(true)
db.sysdecor = get_decoration_size();//trying to get decorations
dispose();
}
private Dimension get_decoration_size() {
Rectangle window = getBounds();
Rectangle content = getContentPane().getBounds();
int width = window.width - content.width;
int height = window.height - content.height;
return new Dimension(width, height);
}
}
I had to assume a lot to create a runnable example.
Here's the result of your getDecorationSize method. The line didn't print until I closed the JDialog.
java.awt.Dimension[width=16,height=39]
And here's the code I used.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JDialogTest implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JDialogTest());
}
private JFrame frame;
#Override
public void run() {
frame = new JFrame("JDialog Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(
150, 100, 150, 100));
panel.setPreferredSize(new Dimension(400, 400));
JButton button = new JButton("Open JDialog");
button.addActionListener(new ButtonListener());
panel.add(button);
return panel;
}
public class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
new CalculateDecor(frame, "Spash Screen");
}
}
public class CalculateDecor extends JDialog {
private static final long serialVersionUID = 1L;
public CalculateDecor(JFrame frame, String title) {
super(frame, true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle(title);
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(200, 200));
JLabel label = new JLabel("Loading...");
label.setHorizontalAlignment(JLabel.CENTER);
panel.add(label);
add(panel);
pack();
setLocationRelativeTo(frame);
setVisible(true);
System.out.println(getDecorationSize());
}
private Dimension getDecorationSize() {
Rectangle window = getBounds();
Rectangle content = getContentPane().getBounds();
int width = window.width - content.width;
int height = window.height - content.height;
return new Dimension(width, height);
}
}
}
I've intended to create a simple gui that would draw an oval in the top third of the window, display a name in the middle third, and draw a rectangle in the bottom third(to be done later)
So far, the only parts I've been able to create and make visible are four buttons that are eventually meant to toggle the visibility of the objects and label.
The problem I'm having is that I cannot get the label or the oval to appear, and I'm not sure what I'm missing preventing either to be visble
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
public class Gui extends JFrame
implements ActionListener
{
private JButton bottomLeftButton;
private JButton bottomMiddleLeftButton;
private JButton bottomRightButton;
private JButton bottomMiddleRightButton;
private OtherPanel mypanel;
private JLabel name;
private JPanel panelOne;
private boolean visible;
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == bottomLeftButton)
{
visible = name.isVisible();
name.setVisible(visible);
}
else if(e.getSource() == bottomMiddleLeftButton)
{
}
else if (e.getSource() == bottomMiddleRightButton)
{
}
else if (e.getSource() == bottomRightButton)
{
}
repaint();
}
public Gui()
{
setTitle("First GUI");
setSize(800,800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = this.getContentPane();
contentPane.setLayout(new BorderLayout());
JPanel BottomPanel = new JPanel(new GridLayout(1,4));
contentPane.add(BottomPanel, BorderLayout.SOUTH);
bottomLeftButton = new JButton("Name");
bottomLeftButton.addActionListener(this);
BottomPanel.add(bottomLeftButton);
bottomMiddleLeftButton = new JButton("Oval");
bottomMiddleLeftButton.addActionListener(this);
BottomPanel.add(bottomMiddleLeftButton);
bottomMiddleRightButton = new JButton("Square");
bottomMiddleRightButton.addActionListener(this);
BottomPanel.add(bottomMiddleRightButton);
bottomRightButton = new JButton("Special");
bottomRightButton.addActionListener(this);
BottomPanel.add(bottomRightButton);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(3,1));
panelOne = new OtherPanel();
name = new JLabel("Name");
name.setHorizontalAlignment(SwingConstants.CENTER);
JLabel label3 = new JLabel("Label3");
centerPanel.add(panelOne);
centerPanel.add(name);
centerPanel.add(label3);
}
public static void main(String[] args)
{
Gui gui = new Gui();
gui.setVisible(true);
}
}
(meant to draw the oval)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class OtherPanel extends JPanel
{
public void paintComponent(Graphics g)
{
int x = 10;
int y = 10;
int width = getWidth(); //ten pixels of spaces
int height = getHeight();
g.fillOval(x, y, width, height);
}
}
was missing a line of code to add the objects to the contentPane
contentPane.add(centerPanel); goes at the end of the gui() method
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;
}
}
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().