Question: Write JFrame that when you press the "start" button draws, and keep drawing random colored and sized filled ovals until the "stop" button is pressed. Problem: loop inside the actionPerformed method() Doesn't Work. The Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class p6 extends JFrame implements ActionListener
{
String str;
JButton start,stop;
int h=0,w=0;
p6()
{
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(1500,1000);
start= new JButton("Start");
stop= new JButton("Stop");
setLayout(null);
start.setBounds(500, 50, 100,30);
stop.setBounds(610, 50, 100,30);
add(start);
add(stop);
start.addActionListener(this);
stop.addActionListener(this);
}
public void actionPerformed(ActionEvent ae)
{
String c=ae.getActionCommand();
if(c=="Start")
{
while(c!="Stop")
{
h =20;
w =20;
}
repaint();
}
str=" " h " " w;
}
public void paint(Graphics g)
{
super.paintComponents(g);
g.drawString(str, 100, 100);
//g.drawOval(100, 100, 100, 100);
g.drawOval((int)Math.random()*2000,(int) Math.random()*2000, w,h);
}
public static void main(String[] args)
{
new p6();
}
}
CodePudding user response:
Image from How to Use Root Panes
And you really should make the time to learn how to use layout managers, see Laying Out Components Within a Container. They will save many hours of frustration. The following examples makes use of both a BorderLayout
and CardLayout
.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private CardLayout cardLayout;
private JPanel showPane;
private DrawingPane drawingPane;
public TestPane() {
setLayout(new BorderLayout());
cardLayout = new CardLayout();
showPane = new JPanel(cardLayout);
showPane.add(new EmptyPane(), "Empty");
drawingPane = new DrawingPane();
showPane.add(drawingPane, "Drawing");
cardLayout.show(showPane, "Empty");
add(showPane);
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
stopButton.setEnabled(false);
JPanel actionsPane = new JPanel();
actionsPane.add(startButton);
actionsPane.add(stopButton);
add(actionsPane, BorderLayout.SOUTH);
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
startButton.setEnabled(false);
stopButton.setEnabled(true);
drawingPane.start();
cardLayout.show(showPane, "Drawing");
}
});
stopButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
startButton.setEnabled(true);
stopButton.setEnabled(false);
drawingPane.stop();
cardLayout.show(showPane, "Empty");
}
});
}
}
public class EmptyPane extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public class DrawingPane extends JPanel {
private int h = 0, w = 0;
private Timer timer;
private Random rnd = new Random();
public DrawingPane() {
}
public void start() {
if (timer == null) {
timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
h = 20;
w = 20;
repaint();
}
});
}
timer.start();
}
public void stop() {
if (timer != null) {
timer.stop();
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
int x = 0;
int y = 0;
if (w < getWidth() && h < getHeight()) {
x = rnd.nextInt(0, getWidth() - w);
y = rnd.nextInt(0, getHeight() - w);
}
g2d.drawOval(x, y, w, h);
g2d.dispose();
}
}
}
Why make use of
CardLayout
?
Based on the original code, when not painting, nothing is shown. So I made use of a CardLayout
to switch to an "empty" state. Now, it wouldn't be very hard to derive a model to hold the state information and share that between the "empty" and "running" states and show something different on the "empty" state. Equally, we could make use of the glassPane
, but I think we're drifting of course.
The purpose is to demonstrate ONE possible solution for showing different states.
Why use two different panes?
First, we don't "need" EmptyPane
, we could get away with just an instance of JPanel
, but, if you wanted to display something else when not drawing, this is one approach you could take.
The original code had a if
statement which means that when not drawing, nothing is painted, so why waste the time and instead just show a "empty" pane instead.
Again, this is just a demonstration of one possible solution.
CodePudding user response:
You have to add these lines before actionPerformed method,
start.setActionCommand("start");
stop.setActionCommand("stop");