Reputation:
I am creating a simple java program with a GUI built with the help of window builder. The GUI consists of just a button.
On button click,start a thread that will print to the random number infinitely until it is stopped by clicking the same button again.
Here is my code
LoopTest.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class LoopTest extends JFrame implements ActionListener {//******
private JButton startB, stopB;
private JTextArea oa;
Start sta;
public LoopTest(){
super("Final Exam: Question ");
Container c = getContentPane();
c.setLayout(new FlowLayout());
startB = new JButton("START"); c.add(startB);
stopB = new JButton("STOP"); c.add(stopB);
oa = new JTextArea(5,20); c.add(oa);
c.add(new JScrollPane(oa));
registerEvents();
sta = new Start("Loop", oa);
}
public void registerEvents(){
startB.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae){
if(startB.isEnabled() == true )
sta.setLoopFlag(true);
if(!sta.isAlive())
sta.start();
startB.setEnabled(false);
}
}
);
stopB.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent ae){
if(stopB.isEnabled()==true){
sta.setLoopFlag(false);
}
}
}
);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
public static void main(String[] args){
LoopTest app = new LoopTest();
app.setSize(300,300);
app.setLocationRelativeTo(null);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
}
Start.java
public class Start extends Thread {
private JTextArea ta;
private boolean loopFlag;
public Start(String name, JTextArea ta){
super(name);
this.ta = ta;
ta.setText("");
loopFlag = true;
}
public void run(){
int num=0;
while(true)
while(loopFlag){
num = 1+ (int)(Math.random()*100);
ta.append(num + "\n");
}
}
public void setLoopFlag(boolean value){
loopFlag = value;
}
}
Stop.java
public class Stop extends Thread {
public Stop( String name ){
super(name);
}
public void run(){
}
}
Thanks in advance.
Upvotes: 1
Views: 1831
Reputation: 285405
Your code breaks Swing threading rules as you're making mutational changes to Swing components off of the Swing event thread. Suggestions:
repaint()
off of the Swing event thread.while (true)
is a "tight" loop -- it has no Thread.sleep
within it, and that means that it risks typing up the CPU in its tight loop, something that can hamper your program and your computer.start()
and stop()
methods. For example:
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class StartStop extends JPanel {
private static final int TIMER_DELAY = 300;
private StartAction startAction = new StartAction();
private StopAction stopAction = new StopAction();
private JButton button = new JButton(startAction);
private DefaultListModel<Integer> model = new DefaultListModel<>();
private JList<Integer> jList = new JList<>(model);
private Timer timer = new Timer(TIMER_DELAY, new TimerListener());
public StartStop() {
JPanel btnPanel = new JPanel();
btnPanel.add(button);
jList.setFocusable(false);
jList.setVisibleRowCount(10);
jList.setPrototypeCellValue(100000);
JScrollPane scrollPane = new JScrollPane(jList);
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int num = 1 + (int) (Math.random() * 100);
model.addElement(num);
}
}
private class StartAction extends AbstractAction {
public StartAction() {
super("Start");
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
@Override
public void actionPerformed(ActionEvent e) {
timer.start();
button.setAction(stopAction);
}
}
private class StopAction extends AbstractAction {
public StopAction() {
super("Stop");
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
@Override
public void actionPerformed(ActionEvent e) {
timer.stop();
button.setAction(startAction);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Start Stop");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new StartStop());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Upvotes: 4