【发布时间】:2020-07-04 08:53:46
【问题描述】:
我已经用 Java 制作了一个 GUI,并查看了如何减慢循环速度。在线的所有方法都不起作用,并且 GUI 在触发循环时冻结,这也发生在没有行来减慢循环的情况下。这是我的代码(主要位和变量更改为 coin 系统):
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUI implements ActionListener {
static int coins = 0;
static int autoCoinsLevel = 0;
int autoCoinsNextLevelUpgradeCost = 100;
String versionRing = "Alpha";
String versionNumber = "1.2";
JLabel coinText;
JFrame frame;
JPanel panel;
JLabel autoCoinsCostText;
public GUI() {
frame = new JFrame();
JButton button = new JButton("Click me!");
JButton autoClickUpgradeButton = new JButton("Auto Generator - Level " + autoCoinsLevel);
button.addActionListener(this);
autoCoinsUpgradeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(coins >= autoCoinsNextLevelUpgradeCost && autoCoinsLevel < 9) {
autoCoinsLevel++;
autoCoinsUpgradeButton.setText("Auto Coin Maker - Level " + autoClickLevel);
coins = coins - autoCoinsNextLevelUpgradeCost;
coinText.setText("Coins: " + coins);
autoCoinsNextLevelUpgradeCost = autoCoinsNextLevelUpgradeCost * 10;
autoCoinsCostText.setText("Auto Coin Maker Upgrade Cost: " + autoCoinsNextLevelUpgradeCost + " Coins");
frame.pack();
while(autoCoinsLevel > 0) {
if(autoCoinsLevel == 1) {
coins++;
// delay 1 seconds
} else if(autoCoinsLevel == 2) {
coins++;
// delay .75 seconds
}
// and so on until `autoCoinsLevel == 9`
}
}
}
});
coinText = new JLabel("Coins: 0");
autoCoinsCostText = new JLabel("Auto Coin Maker Upgrade Cost: " + autoCoinsNextLevelUpgradeCost + " Coins");
panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(60, 100, 30, 100));
panel.setLayout(new GridLayout(0, 1));
panel.add(button);
panel.add(coinsText);
panel.add(autoCoinsUpgradeButton);
panel.add(autoCoinsCostText);
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Clicker Clicker - " + versionRing + " " + versionNumber);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new GUI();
}
@Override
public void actionPerformed(ActionEvent e) {
// increase coins script
}
}
我不知道为什么应用程序在我尝试的大多数方法中都停止响应,而且根本没有任何减慢速度的方法也会使应用程序挂起...
我是非常 Java 新手,所以解释一下 this 或 that 的作用会帮助我更好地理解。 :)
【问题讨论】:
-
你永远不想减慢摆动主线程。这就是控制你的gui的东西。您想使用计时器线程进行计时,同时让 swing 线程处理 gui 的其余部分。
-
该应用程序由单线程支持,如果它忙于循环,则无法处理其他事情......以延迟您不必阻止的操作线程,但是推迟操作,看类
java.util.Timer。 -
@rascio "..看看
java.util.Timer" 类因为所有的 Swing/AWT 应用程序都应该在 Event Dispatch Thread 上创建和更新,所以使用javax.swing.Timer确保在 EDT 上执行其中的操作。 -
啊,对不起,我从未使用过 swing :D 我不知道它的具体课程。那么是的,它是正确的,没有并发问题。
-
您的 autoCoinsLevel 正在 EDT 中更新,但在主线程中可能看不到该更新(可能是由于托管了 while 循环)。该变量应声明为
volatile。我在答案部分提供了此行为的演示。