JLabel 文本未显示,JFrame 等待时冻结
JLabel Text not Showing, JFrame Freezing on Wait
我正在编写剪刀石头布 GUI 应用程序,在我的 JPanel
之一中,我有一个 JLabel
。这个 JLabel
应该说一秒钟石头,然后一秒钟布,然后一秒钟剪刀。到目前为止,它只在最后显示了拍摄的 JLabel
文本。我似乎无法弄清楚为什么。有人可以帮忙吗?
代码:
import javax.swing.*;
import java.awt.*;
class RockPaperScissorsShoot {
public JFrame shootFrame;
JPanel shootPanel;
JLabel shootLabel;
int flagThing = 0;
public RockPaperScissorsShoot(Window gameWindow) {
shootFrame = new JFrame();
shootFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shootFrame.setSize(250, 150);
shootPanel = new JPanel(new GridLayout(1, 1));
shootFrame.add(shootPanel);
shootLabel = new JLabel();
shootPanel.add(shootLabel);
shootFrame.setVisible(true);
shootFrame.setTitle("Rock!"); // the title changes
shootLabel.setText("Rock!"); // but the JLabel text does not
waitForMilSecs(1000);
shootFrame.setTitle("Paper!");
shootLabel.setText("Paper!");
waitForMilSecs(1000);
shootFrame.setTitle("Scissors!");
shootLabel.setText("Scissors!");
waitForMilSecs(1000);
shootFrame.setTitle("Shoot!");
shootLabel.setText("Shoot!"); //Except here, right here, the text shows up
}
public static void waitForMilSecs(long ms) {
long checkMS = System.currentTimeMillis() + ms;
while (System.currentTimeMillis() <= checkMS) {
System.out.println("Not yet!");
}
System.out.println("NOW!");
}
}
编辑:我尝试添加 SwingWorker
来处理单独线程中的等待。我仍然得到一个冻结的 GUI。代码:
import java.awt.*;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
//import javax.swing.event.ChangeEvent;
import javax.swing.SwingWorker.StateValue;
class RockPaperScissorsShoot {
public JFrame shootFrame;
JPanel shootPanel;
JLabel shootLabel;
int flagThing = 0;
public RockPaperScissorsShoot(Window gameWindow) {
shootFrame = new JFrame();
shootFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shootFrame.setSize(250, 150);
shootPanel = new JPanel(new GridLayout(1, 1));
shootFrame.add(shootPanel);
shootLabel = new JLabel();
shootPanel.add(shootLabel);
shootFrame.setVisible(true);
changeText(false, "Rock!", shootLabel, shootFrame, 1);
changeText(true, "Paper!", shootLabel, shootFrame, 1);
changeText(true, "Scissors", shootLabel, shootFrame, 1);
changeText(true, "Shoot!", shootLabel, shootFrame, 1);
}
public static void changeText(boolean wait, String text, JLabel shootLabel, JFrame shootFrame, long secondsToWait) {
while (wait) {
wait = waiter(secondsToWait * 1000);
}
shootFrame.setTitle(text);
shootLabel.setText(text);
}
private static boolean waiter(long ms) {
boolean keepGoing = false;
SwingWorker sw1 = new SwingWorker() {
@Override
protected Boolean doInBackground() throws Exception {
Thread.sleep(ms);
// String res = "Finished Execution";
return true;
}
@Override
protected void done() {
try {
System.out.println(get().toString());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
// Auto-generated catch block
e.printStackTrace();
}
}
};
// executes the swingworker on worker thread
sw1.execute();
while (sw1.getState() != StateValue.DONE) {
System.out.println("Not done (debug)");
}
System.out.println("Done!");
return false;
}
public static void waitForMilSecs(long ms) {
long checkMS = System.currentTimeMillis() + ms;
while (System.currentTimeMillis() <= checkMS) {
System.out.println("Not yet!");
}
System.out.println("NOW!");
}
public static void wait(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
System.out.println("Error waiting, cannot wait lol");
}
}
}
任何人都可以向我解释为什么我的 GUI 仍然冻结吗?
使用 [Swing] Timer。
请尝试以下操作。
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class RockPaperScissorsShoot implements ActionListener {
private JFrame shootFrame;
private JPanel shootPanel;
private JLabel shootLabel;
private int flagThing = 0;
private Timer timer;
public RockPaperScissorsShoot() {
shootFrame = new JFrame();
shootFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shootFrame.setSize(250, 150);
shootPanel = new JPanel(new GridLayout(1, 1));
shootFrame.add(shootPanel);
shootLabel = new JLabel();
shootPanel.add(shootLabel);
shootFrame.setVisible(true);
timer = new Timer(1000, this);
timer.start();
}
public void actionPerformed(ActionEvent event) {
String text;
switch (flagThing) {
case 0:
text = "Rock!";
break;
case 1:
text = "Paper!";
break;
case 2:
text = "Scissors!";
break;
case 3:
text = "Shoot!";
break;
default:
text = null;
}
if (text != null) {
shootFrame.setTitle(text);
shootLabel.setText(text);
}
flagThing++;
if (flagThing > 3) {
timer.stop();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new RockPaperScissorsShoot());
}
}
我正在编写剪刀石头布 GUI 应用程序,在我的 JPanel
之一中,我有一个 JLabel
。这个 JLabel
应该说一秒钟石头,然后一秒钟布,然后一秒钟剪刀。到目前为止,它只在最后显示了拍摄的 JLabel
文本。我似乎无法弄清楚为什么。有人可以帮忙吗?
代码:
import javax.swing.*;
import java.awt.*;
class RockPaperScissorsShoot {
public JFrame shootFrame;
JPanel shootPanel;
JLabel shootLabel;
int flagThing = 0;
public RockPaperScissorsShoot(Window gameWindow) {
shootFrame = new JFrame();
shootFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shootFrame.setSize(250, 150);
shootPanel = new JPanel(new GridLayout(1, 1));
shootFrame.add(shootPanel);
shootLabel = new JLabel();
shootPanel.add(shootLabel);
shootFrame.setVisible(true);
shootFrame.setTitle("Rock!"); // the title changes
shootLabel.setText("Rock!"); // but the JLabel text does not
waitForMilSecs(1000);
shootFrame.setTitle("Paper!");
shootLabel.setText("Paper!");
waitForMilSecs(1000);
shootFrame.setTitle("Scissors!");
shootLabel.setText("Scissors!");
waitForMilSecs(1000);
shootFrame.setTitle("Shoot!");
shootLabel.setText("Shoot!"); //Except here, right here, the text shows up
}
public static void waitForMilSecs(long ms) {
long checkMS = System.currentTimeMillis() + ms;
while (System.currentTimeMillis() <= checkMS) {
System.out.println("Not yet!");
}
System.out.println("NOW!");
}
}
编辑:我尝试添加 SwingWorker
来处理单独线程中的等待。我仍然得到一个冻结的 GUI。代码:
import java.awt.*;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
//import javax.swing.event.ChangeEvent;
import javax.swing.SwingWorker.StateValue;
class RockPaperScissorsShoot {
public JFrame shootFrame;
JPanel shootPanel;
JLabel shootLabel;
int flagThing = 0;
public RockPaperScissorsShoot(Window gameWindow) {
shootFrame = new JFrame();
shootFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shootFrame.setSize(250, 150);
shootPanel = new JPanel(new GridLayout(1, 1));
shootFrame.add(shootPanel);
shootLabel = new JLabel();
shootPanel.add(shootLabel);
shootFrame.setVisible(true);
changeText(false, "Rock!", shootLabel, shootFrame, 1);
changeText(true, "Paper!", shootLabel, shootFrame, 1);
changeText(true, "Scissors", shootLabel, shootFrame, 1);
changeText(true, "Shoot!", shootLabel, shootFrame, 1);
}
public static void changeText(boolean wait, String text, JLabel shootLabel, JFrame shootFrame, long secondsToWait) {
while (wait) {
wait = waiter(secondsToWait * 1000);
}
shootFrame.setTitle(text);
shootLabel.setText(text);
}
private static boolean waiter(long ms) {
boolean keepGoing = false;
SwingWorker sw1 = new SwingWorker() {
@Override
protected Boolean doInBackground() throws Exception {
Thread.sleep(ms);
// String res = "Finished Execution";
return true;
}
@Override
protected void done() {
try {
System.out.println(get().toString());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
// Auto-generated catch block
e.printStackTrace();
}
}
};
// executes the swingworker on worker thread
sw1.execute();
while (sw1.getState() != StateValue.DONE) {
System.out.println("Not done (debug)");
}
System.out.println("Done!");
return false;
}
public static void waitForMilSecs(long ms) {
long checkMS = System.currentTimeMillis() + ms;
while (System.currentTimeMillis() <= checkMS) {
System.out.println("Not yet!");
}
System.out.println("NOW!");
}
public static void wait(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
System.out.println("Error waiting, cannot wait lol");
}
}
}
任何人都可以向我解释为什么我的 GUI 仍然冻结吗?
使用 [Swing] Timer。
请尝试以下操作。
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class RockPaperScissorsShoot implements ActionListener {
private JFrame shootFrame;
private JPanel shootPanel;
private JLabel shootLabel;
private int flagThing = 0;
private Timer timer;
public RockPaperScissorsShoot() {
shootFrame = new JFrame();
shootFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
shootFrame.setSize(250, 150);
shootPanel = new JPanel(new GridLayout(1, 1));
shootFrame.add(shootPanel);
shootLabel = new JLabel();
shootPanel.add(shootLabel);
shootFrame.setVisible(true);
timer = new Timer(1000, this);
timer.start();
}
public void actionPerformed(ActionEvent event) {
String text;
switch (flagThing) {
case 0:
text = "Rock!";
break;
case 1:
text = "Paper!";
break;
case 2:
text = "Scissors!";
break;
case 3:
text = "Shoot!";
break;
default:
text = null;
}
if (text != null) {
shootFrame.setTitle(text);
shootLabel.setText(text);
}
flagThing++;
if (flagThing > 3) {
timer.stop();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new RockPaperScissorsShoot());
}
}