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
Related
I am a noob in java and am trying to make a kind of text adventure game. I want to be able to have the program have some kind of fade ability as it transitions from one layout of the UI to another.
I really have no idea what the best approach to this problem would be or if its really even feasible, but I have so far been trying to have a Jpanel that covers the entire window and uses a timer to fade in to cover everything else in black, or fades out from black to transparency thereby revealing everything underneath.
I have been testing this idea by trying to fade in/out the program at the start just to get the logic for the fade system working before trying to have it as a transition effect. The fade-out kind of works, but I have the program output the alpha level and the screen is turning black at around alpha 50 out of 255 which is confusing me. The fade-in does not work at all.
Here is the code for the fade method:
static int opacityCounter = 0;
public void fadeOut(JPanel frame){
System.out.println(opacityCounter);
opacityCounter = 0;
fadeTimer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.setBackground(new Color(0,0,0,opacityCounter));
opacityCounter++;
gui.window.add(frame);
if(opacityCounter >= 255){
opacityCounter = 255;
fadeTimer.stop();
}
System.out.println(opacityCounter);
}
});
fadeTimer.start();
}
This is the code where the "fadePanel" that covers the window is created and deployed in the method.
fadeScreen = new JPanel();
fadeScreen.setBounds(0,0,800,600);
fadeScreen.setBackground(Color.black);
window.add(fadeScreen);
game.visibilityManager.fadeOut(this.fadeScreen);
To clarify I want something that goes from a UI layout like this:
fades to black, before fading back to a UI that looks like this
This is a minimal reproducible example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test {
JFrame window;
JPanel fadeScreen, screen1, screen2;
JLabel text1, text2;
Timer fadeTimer;
public Test(){
//Frame Window
window = new JFrame();
window.setSize(800,600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().setBackground(Color.blue);
//Screen 1
screen1 = new JPanel();
screen1.setBounds(100, 100, 600, 125);
screen1.setBackground(Color.white);
text1 = new JLabel("Text1");
screen1.add(text1);
window.add(screen1);
//Screen 2
screen2 = new JPanel();
screen2.setBounds(100, 400, 600, 125);
screen2.setBackground(Color.white);
text2 = new JLabel("Text2");
screen2.add(text2);
window.add(screen2);
//Cover Panel
fadeScreen = new JPanel();
fadeScreen.setBounds(0,0,800,600);
fadeScreen.setBackground(Color.black);
window.add(fadeScreen);
window.setVisible(true);
//Comment out which method you don't want to use
fadeOut(this.fadeScreen);
//fadeIn(this.fadeScreen);
}
//Fade methods
int opacityCounter = 0;
public void fadeOut(JPanel frame){
System.out.println(opacityCounter);
opacityCounter = 0;
fadeTimer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.setBackground(new Color(0,0,0,opacityCounter));
opacityCounter++;
window.add(frame);
if(opacityCounter >= 255){
opacityCounter = 255;
fadeTimer.stop();
}
System.out.println(opacityCounter);
}
});
fadeTimer.start();
}
public void fadeIn(JPanel frame){
System.out.println(opacityCounter);
opacityCounter = 255;
fadeTimer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.setBackground(new Color(0,0,0,opacityCounter));
opacityCounter--;
window.add(frame);
if(opacityCounter <= 0){
opacityCounter = 0;
fadeTimer.stop();
}
System.out.println(opacityCounter);
}
});
fadeTimer.start();
}
public static void main(String[] args){
new Test();
}
}
Thanks in advance!
I would try these things:
Use the GlassPane of the top-level window and make a section of it darker where you want to cover things up, using a Swing Timer.
Use a CardLayout to swap the underlying components, and make the swap when the covering JPanel is darkest.
Then undarken the covering panel after the swap.
For example (to write more code explanation later):
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Test2 extends JPanel {
public static final String PANEL_1 = "panel 1";
public static final String PANEL_2 = "panel 2";
private CardLayout cardLayout = new CardLayout();
private JPanel cardPanel = new JPanel(cardLayout);
private JPanel panel1 = new JPanel();
private JPanel panel2 = new JPanel();
private Action fadeAction = new FadeAction(cardPanel);
public Test2() {
JLabel label = new JLabel("Panel 1");
label.setFont(label.getFont().deriveFont(Font.BOLD, 100f));
panel1.setLayout(new GridBagLayout());
int gap = 40;
panel1.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
panel1.add(label);
panel1.setBackground(Color.PINK);
label = new JLabel("Panel 2");
label.setFont(label.getFont().deriveFont(Font.BOLD, 100f));
panel2.setLayout(new GridBagLayout());
panel2.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
panel2.add(label);
panel2.setBackground(new Color(131, 238, 255));
cardPanel.add(panel1, PANEL_1);
cardPanel.add(panel2, PANEL_2);
JButton startFadeBtn = new JButton(fadeAction);
JPanel buttonPanel = new JPanel();
buttonPanel.add(startFadeBtn);
setLayout(new BorderLayout(5, 5));
add(cardPanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
}
private static class FadeAction extends AbstractAction {
private static final int FADE_DELAY = 20;
private static final int UNFADE_VALUE = 255;
private JPanel cardPanel;
private JComponent glassPane;
private JPanel coverPanel = new JPanel();
private Timer fadeTimer;
private int counter = 0;
private boolean fade = true;
public FadeAction(JPanel cardPanel) {
super("Start Fade");
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
this.cardPanel = cardPanel;
}
#Override
public void actionPerformed(ActionEvent e) {
counter = 0;
fade = true;
setEnabled(false);
CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, PANEL_1);
Window topLevelWindow = SwingUtilities.getWindowAncestor(cardPanel);
glassPane = (JComponent) ((RootPaneContainer) topLevelWindow).getRootPane().getGlassPane();
glassPane.setVisible(true);
glassPane.setLayout(null);
coverPanel.setSize(cardPanel.getSize());
int x = cardPanel.getLocationOnScreen().x - glassPane.getLocationOnScreen().x;
int y = cardPanel.getLocationOnScreen().y - glassPane.getLocationOnScreen().y;
Point coverPanelPoint = new Point(x, y);
coverPanel.setLocation(coverPanelPoint);
glassPane.add(coverPanel);
fadeTimer = new Timer(FADE_DELAY, e2 -> fadeTimerActionPerformed(e2));
fadeTimer.start();
}
private void fadeTimerActionPerformed(ActionEvent e) {
coverPanel.setBackground(new Color(0, 0, 0, counter));
glassPane.repaint();
if (fade) {
counter++;
} else if (counter > 0) {
counter--;
} else {
glassPane.remove(coverPanel);
glassPane.setVisible(false);
setEnabled(true);
((Timer) e.getSource()).stop();
}
if (counter >= UNFADE_VALUE) {
fade = false;
CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, PANEL_2);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Test2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Concurrency in Swing and the Laying Out Components Within a Container sections.
This is Hovercraft Full Of Eels' answer. All I did was clean up the GUI creation and demonstrate how this would work with more than two JPanels.
I created five JPanels and displayed them in order with the fade-out/fade-in effect.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class FadeEffectsTesting {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Fade Effects Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FadeEffectsTesting().getMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
public static final String[] PANEL_SEQUENCE = { "Panel 1", "Panel 2", "Panel 3", "Panel 4",
"Panel 5" };
private int sequence = 0;
private CardLayout cardLayout;
private FadeAction action;
private JPanel cardPanel, mainPanel;
public FadeEffectsTesting() {
this.mainPanel = new JPanel(new BorderLayout(5, 5));
this.cardPanel = createCardPanel();
this.action = new FadeAction(cardPanel);
mainPanel.add(cardPanel, BorderLayout.CENTER);
mainPanel.add(createButtonPanel(), BorderLayout.PAGE_END);
}
private JPanel createCardPanel() {
cardLayout = new CardLayout();
JPanel panel = new JPanel(cardLayout);
panel.add(createTextPanel(Color.PINK, PANEL_SEQUENCE[0]),
PANEL_SEQUENCE[0]);
panel.add(createTextPanel(new Color(131, 238, 255),
PANEL_SEQUENCE[1]), PANEL_SEQUENCE[1]);
panel.add(createTextPanel(Color.PINK, PANEL_SEQUENCE[2]),
PANEL_SEQUENCE[2]);
panel.add(createTextPanel(new Color(131, 238, 255),
PANEL_SEQUENCE[3]), PANEL_SEQUENCE[3]);
panel.add(createTextPanel(Color.PINK, PANEL_SEQUENCE[4]),
PANEL_SEQUENCE[4]);
return panel;
}
private JPanel createTextPanel(Color color, String text) {
JPanel panel = new JPanel(new FlowLayout());
panel.setBackground(color);
int gap = 40;
panel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
JLabel label = new JLabel(text);
label.setFont(label.getFont().deriveFont(Font.BOLD, 72f));
panel.add(label);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
setFadeAction();
JButton startFadeBtn = new JButton(action);
panel.add(startFadeBtn);
return panel;
}
public void setFadeAction() {
action.setFromPanel(PANEL_SEQUENCE[sequence]);
action.setToPanel(PANEL_SEQUENCE[sequence + 1]);
}
public JPanel getMainPanel() {
return mainPanel;
}
public class FadeAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private static final int FADE_DELAY = 20;
private static final int UNFADE_VALUE = 255;
private JPanel cardPanel;
private JComponent glassPane;
private JPanel coverPanel;
private Timer fadeTimer;
private int alphaValue;
private boolean fadeOut;
private String fromPanel, toPanel;
public FadeAction(JPanel cardPanel) {
super("Start Fade");
this.putValue(MNEMONIC_KEY, KeyEvent.VK_S);
this.cardPanel = cardPanel;
this.alphaValue = 0;
this.fadeOut = true;
}
public void setFromPanel(String fromPanel) {
this.fromPanel = fromPanel;
}
public void setToPanel(String toPanel) {
this.toPanel = toPanel;
}
#Override
public void actionPerformed(ActionEvent event) {
alphaValue = 0;
fadeOut = true;
setEnabled(false);
CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, fromPanel);
Window topLevelWindow = SwingUtilities.getWindowAncestor(cardPanel);
glassPane = (JComponent) ((RootPaneContainer) topLevelWindow).getRootPane()
.getGlassPane();
glassPane.setLayout(null);
coverPanel = new JPanel();
coverPanel.setSize(cardPanel.getSize());
glassPane.add(coverPanel);
glassPane.setVisible(true);
fadeTimer = new Timer(FADE_DELAY, e2 -> fadeTimerActionPerformed(e2));
fadeTimer.start();
}
private void fadeTimerActionPerformed(ActionEvent event) {
coverPanel.setBackground(new Color(0, 0, 0, alphaValue));
glassPane.repaint();
if (fadeOut) {
alphaValue += 3;
} else if (alphaValue > 0) {
alphaValue -= 3;
} else {
glassPane.remove(coverPanel);
glassPane.setVisible(false);
((Timer) event.getSource()).stop();
if (++sequence < (PANEL_SEQUENCE.length - 1)) {
setFadeAction();
setEnabled(true);
}
}
if (alphaValue >= UNFADE_VALUE) {
fadeOut = false;
CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, toPanel);
}
}
}
}
I am trying to make minesweeper. When I click on the JButton I want the button to hide. I have accomplished this but the button does not cover the entire JPanel. It always leaves some of the panel on the top visible.
I have tried setting the preferred size, vertical and horizontal alignment.
Why is it doing this? How can I fix it?
class canvas extends JFrame {
public static JPanel[] panels;
public static Tile[] tiles;
canvas(int size){
JFrame theGUI = new JFrame();
panels = new JPanel[size*size]; //creates panels and tiles, the tiles contain color, if it is
a bomb ect.
tiles = new Tile[size*size];
Container con = theGUI.getContentPane();
Graphics g;
for(int i = 0; i < panels.length; i++) {
JPanel temp = new JPanel();
temp.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));//adds borders
temp.setBorder(BorderFactory.createLineBorder(Color.black,1));
JButton button = new JButton();
button.setBackground(Color.GRAY);
button.setAlignmentY(0.0f);//tried to see if vertical align would fix it, it didnt
button.setPreferredSize(new Dimension(70,70));
button.addActionListener(new Action() {
public void actionPerformed(ActionEvent event) {
button.setVisible(false);
}
});
temp.add(button);
Tile tempTile = new Tile();
panels[i] = temp;
tiles[i] = tempTile;
tiles[i].color = Color.green;
panels[i].setBackground(tiles[i].color);
con.add(panels[i]);
}
con.setLayout(new GridLayout(size,size));
theGUI.setTitle("mine sweeper");
theGUI.setSize(size*40, size*40);
theGUI.setVisible(true);
}
}
The problem I am trying to fix:
I think you can achieve your goal with simpler code. You just need to add the JButtons directly to a JPanel that uses GridLayout as its layout manager. Consider the following code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
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.JPanel;
import javax.swing.WindowConstants;
public class MineSweeper implements ActionListener, Runnable {
private JFrame frame;
public void actionPerformed(ActionEvent event) {
Object obj = event.getSource();
if (obj instanceof JButton) {
JButton button = (JButton) obj;
button.setVisible(false);
}
}
public void run() {
showGui();
}
private JButton createButton() {
JButton button = new JButton();
button.setPreferredSize(new Dimension(40, 40));
button.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
button.addActionListener(this);
return button;
}
private JPanel createMineField() {
JPanel mineField = new JPanel(new GridLayout(10, 10));
mineField.setBackground(Color.GREEN);
for (int i = 0; i < 100; i++) {
mineField.add(createButton());
}
return mineField;
}
private void showGui() {
frame = new JFrame("Mine Sweeper");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createMineField(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
/**
* Start here.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new MineSweeper());
}
}
So i have three panels that i have three different buttons for to change them each to their respective colors. I need to add a fourth button that will return all three panels to their original default light gray color. I add this "reset" button and it only changes the first panel back. What am i doing wrong?
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.FlowLayout;
import java.awt.Color;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class PanelDemo extends JFrame implements ActionListener
{
public static final int WIDTH = 300;
public static final int HEIGHT = 200;
private JPanel redPanel;
private JPanel whitePanel;
private JPanel bluePanel;
public static void main(String[] args)
{
PanelDemo gui = new PanelDemo();
gui.setVisible(true);
}
public PanelDemo()
{
super("Panel Demonstration");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel biggerPanel = new JPanel();
biggerPanel.setLayout(new GridLayout(1, 3));
redPanel = new JPanel();
redPanel.setBackground(Color.LIGHT_GRAY);
biggerPanel.add(redPanel);
whitePanel = new JPanel();
whitePanel.setBackground(Color.LIGHT_GRAY);
biggerPanel.add(whitePanel);
bluePanel = new JPanel();
bluePanel.setBackground(Color.LIGHT_GRAY);
biggerPanel.add(bluePanel);
add(biggerPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
buttonPanel.setBackground(Color.LIGHT_GRAY);
buttonPanel.setLayout(new FlowLayout());
JButton redButton = new JButton("Red");
redButton.setBackground(Color.RED);
redButton.addActionListener(this);
buttonPanel.add(redButton);
JButton whiteButton = new JButton("White");
whiteButton.setBackground(Color.WHITE);
whiteButton.addActionListener(this);
buttonPanel.add(whiteButton);
JButton blueButton = new JButton("Blue");
blueButton.setBackground(Color.BLUE);
blueButton.addActionListener(this);
buttonPanel.add(blueButton);
JButton resetButton = new JButton("Reset");
resetButton.setBackground(Color.LIGHT_GRAY);
resetButton.addActionListener(this);
buttonPanel.add(resetButton);
add(buttonPanel, BorderLayout.SOUTH);
}
#Override
public void actionPerformed(ActionEvent e)
{
String buttonString = e.getActionCommand();
if (buttonString.equals("Red"))
redPanel.setBackground(Color.RED);
else if (buttonString.equals("White"))
whitePanel.setBackground(Color.WHITE);
else if (buttonString.equals("Blue"))
bluePanel.setBackground(Color.BLUE);
else if (buttonString.equals("Reset"))
redPanel.setBackground(Color.LIGHT_GRAY);
else if (buttonString.equals("Reset"))
bluePanel.setBackground(Color.LIGHT_GRAY);
else if (buttonString.equals("Reset"))
whitePanel.setBackground(Color.LIGHT_GRAY);
else
System.out.println("Unexpected error.");
}
}
Here was your problem. You had if else's on each panel for the reset. Compare the code below to what you have. It was just a simple logic issue.
public void actionPerformed(ActionEvent e) {
String buttonString = e.getActionCommand();
if (buttonString.equals("Red"))
redPanel.setBackground(Color.RED);
else if (buttonString.equals("White"))
whitePanel.setBackground(Color.WHITE);
else if (buttonString.equals("Blue"))
bluePanel.setBackground(Color.BLUE);
else if (buttonString.equals("Reset")) {
redPanel.setBackground(Color.LIGHT_GRAY);
bluePanel.setBackground(Color.LIGHT_GRAY);
whitePanel.setBackground(Color.LIGHT_GRAY);
}
else
System.out.println("Unexpected error.");
And a couple of suggestions.
Don't extend JFrame. Just use an instance of it. It's better technique.
Put the following as the last statement in your constructor. It will center the panel on your screen.
setLocationRelativeTo(null);
// or when using a frame instance.
frame.setLocationRelativeTo(null);
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 trying to create a GUI that will take in the number of circles to draw, and draw them in drawPanel with random locations/sizes. On my actionListener, when I try to draw the circle, it gives me red lines on my drawOval
1st class:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
/**
*
* #author Chris
*
*/
public class CirclesPanel extends JPanel{
private JButton draw, clear;
private JTextArea textArea;
private JPanel panel, drawPanel, buttonPanel;
private int count;
/**constructor
* builds the frame
*/
public CirclesPanel(){
//creates buttons and textArea
draw = new JButton("Draw");
clear = new JButton("Clear");
textArea = new JTextArea(1,10);
textArea.setBorder(BorderFactory.createTitledBorder("Circles"));
//creats panel
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
setPreferredSize(new Dimension(620, 425));
//creates subpanel drawPanel
JPanel drawPanel = new JPanel();
drawPanel.setPreferredSize(new Dimension(450,400));
drawPanel.setBackground(Color.BLACK);
//creates subpanel buttonPanel
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(3,1));
//adds all the content to the frame
add(panel);
add(buttonPanel, BorderLayout.WEST);
add(drawPanel, BorderLayout.EAST);
buttonPanel.add(textArea);
buttonPanel.add(draw);
buttonPanel.add(clear);
//reads if the draw button is clicked
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count =Integer.parseInt(textArea.getText());//takes the count in
repaint();//repaints the picture to add the circles
}
});
//reads if the clear button is clicked
clear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count=0;//sets the count to 0 so nothing is painted
repaint();//repaints the window
}
});
}
/**Paint component
* draws the random circles
*/
public void paintComponent(Graphics g) {
Random generator = new Random();
int x, y, diameter;
for(int i = 0; i < count; i++){ //loop that takes the count and does this "x" times
g.setColor(Color.BLUE);//sets color to blue
x = generator.nextInt(90);//random location for x
y = generator.nextInt(90);//random location for y
diameter = generator.nextInt(30);//random size
g.fillOval(x, y, diameter, diameter);//draws the circle
}
}
}
2nd class
import javax.swing.JFrame;
public class Circles {
public static void main(String[]args){
JFrame frame = new JFrame("Cicles HW9");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CirclesPanel());
frame.pack();
frame.setVisible(true);
}
}
So in your, I did little addition, first of all, I made the whole program in one class(CIRLCES PANEL), IF You want to use the second class, you can use it....
Problem is coming, your program is not the reading the ActionPerformed method for the drawing, means it is not located with the button, now I directly added it with your button(DRAW), now whenever you click on the button, it automatically reads the your textArea value, and draw your circles. I made your text area FINAL, So you can use it anywhere......
Now things that you need to do----
- this program is drawing circle on the whole frame, means not on your drawing Panel, you need to set the values, so it will draw on your draw panel area
- Also you need to add color for your oval, because it will either draw black color circle, which you will not able to see.....
and also one thing I forget to mentioned you, is that your, you also need to add code for your clear method...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class CirclesPanel extends JPanel{
private JButton draw, clear;
private JTextArea textArea;
private JPanel panel, drawPanel, buttonPanel;
private int count;
public CirclesPanel(){
JButton draw = new JButton("Draw");
JButton clear = new JButton("Clear");
final JTextArea textArea = new JTextArea(1,10);
textArea.setBorder(BorderFactory.createTitledBorder("Circles"));
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
setPreferredSize(new Dimension(620, 425));
JPanel drawPanel = new JPanel();
drawPanel.setPreferredSize(new Dimension(450,400));
drawPanel.setBackground(Color.BLACK);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(3,1));
add(panel);
add(buttonPanel, BorderLayout.WEST);
add(drawPanel, BorderLayout.EAST);
buttonPanel.add(textArea);
buttonPanel.add(draw);
buttonPanel.add(clear);
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count =Integer.parseInt(textArea.getText());
repaint();
}
});
}
public void paintComponent(Graphics g) {
Random generator = new Random();
int x, y, diameter;
for(int i = 0; i < count; i++){
x = generator.nextInt(90);
y = generator.nextInt(90);
diameter = generator.nextInt(30);
g.drawOval(x, y, diameter, diameter);
}
}
}
What you want to do is drawing some random circles on the drawPanel when button clicked. I write you a simplified version to show how things work.
I only keep the drawButton and paintPanel to keep things simple.
public class PaintFrame extends JFrame {
private JPanel content = new JPanel();
private JButton drawButton = new JButton("Draw");
private PaintPanel paintPanel = new PaintPanel();
public PaintFrame() {
getContentPane().add(content);
content.setLayout(new BorderLayout());
drawButton.setSize(100, 500);
drawButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// drawButton is fired, repaint the paintPanel
paintPanel.repaint();
}
});
content.add(drawButton, BorderLayout.WEST);
content.add(paintPanel, BorderLayout.CENTER);
}
}
You need a new class extending the JPanel and override the paintComponent method to do the paint job for you. This makes sure you are drawing on the panel.
class PaintPanel extends JPanel {
public PaintPanel() {
setSize(500, 500);
setBackground(Color.BLACK);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Random random = new Random();
g.setColor(Color.WHITE);
// draw 5 random circles
int count = 5;
for (int i = 0; i < count; i++) {
g.drawOval(random.nextInt(250), random.nextInt(250),
random.nextInt(250), random.nextInt(250));
}
}
}
Main class
public class DrawMain {
public static void main(String[] args) {
JFrame frame = new PaintFrame();
frame.setDefaultCloseOperation(PaintFrame.EXIT_ON_CLOSE);
frame.setSize(600, 500);
frame.setVisible(true);
}
}