Reputation: 23
https://i.sstatic.net/XvHm5.png
When I click the On button it should start spamming 1's across the JTextField. Instead The entire GUI freezes, including the close button. I am using a while loop that will stop when you click the jButton again. Because the jButton is frozen i cannot stop this program. I have read that Threads and Multithreading would help but all of the tutorials are too complex for me to understand. They say to put the loop and GUI on different threads. I want to understand this to fix another program that I am working on which is much more complex. Thats why I made a simple example to show my problem.
https://i.sstatic.net/tbNAF.png
This is how the program shows. (The jTextField is not even updated. What I am asking is if someone knows a way to fix this, whether using threads or not. My code for this program is below.
public class whileLoop extends javax.swing.JFrame {
public whileLoop() {
initComponents();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jTextField1 = new javax.swing.JTextField();
jToggleButton1 = new javax.swing.JToggleButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jToggleButton1.setText("On");
jToggleButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jToggleButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jToggleButton1)
.addGap(18, 18, 18)
.addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE)
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jToggleButton1))
.addContainerGap(12, Short.MAX_VALUE))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if (jToggleButton1.isSelected()) {
jToggleButton1.setText("Off");
while (jToggleButton1.isSelected()) {
jTextField1.setText(jTextField1.getText() + "1");
}
} else {
jToggleButton1.setText("On");
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new whileLoop().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel jPanel1;
private javax.swing.JTextField jTextField1;
private javax.swing.JToggleButton jToggleButton1;
// End of variables declaration
}
The main area of the code is:
private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if (jToggleButton1.isSelected()) {
jToggleButton1.setText("Off");
while (jToggleButton1.isSelected()) {
jTextField1.setText(jTextField1.getText() + "1");
}
} else {
jToggleButton1.setText("On");
}
}
Upvotes: 0
Views: 4663
Reputation: 11006
You have an infinite loop. The state of the toggle button is never changed after being set to true.
Java's UI (and all UI I've worked with) is driven by a single thread. User input is fed back to you on this single thread. Rendering is also done on this single thread.
The reason the textfield is never updated is the UI thread is never getting to render the screen again, as its tied up in your infinite loop.
Yes, you need to put this code in a separate thread, and start it when the toggle button becomes selected. Then, you need to update the textfield from this separate thread. Look into SwingWorker.
Upvotes: 5