Java 为什么我的Swing应用程序冻结了?
基本上,每次我点击我的一个按钮,它就会锁定。我环顾四周,发现这可能是因为一个无限循环,但我在任何地方都看不到 一双新鲜的眼睛会很有用的 无论如何,下面是要声明的JButtons:Java 为什么我的Swing应用程序冻结了?,java,swing,user-interface,jbutton,infinite-loop,Java,Swing,User Interface,Jbutton,Infinite Loop,基本上,每次我点击我的一个按钮,它就会锁定。我环顾四周,发现这可能是因为一个无限循环,但我在任何地方都看不到 一双新鲜的眼睛会很有用的 无论如何,下面是要声明的JButtons: public static JButton textYes = new JButton("Yes"); public static JButton textNo = new JButton("No"); 下面是我的main()方法: 下面是Start()方法: 下面是带有JButton侦听器的actionPerfor
public static JButton textYes = new JButton("Yes");
public static JButton textNo = new JButton("No");
下面是我的main()方法:
下面是Start()方法:
下面是带有JButton侦听器的actionPerformed()方法:
public void actionPerformed(ActionEvent e) {
//jTextArea1.setText(null);
if (box1.isSelected()) {
System.out.println("1 is selected");
willRerollDiceOne = true;
}
else {
//System.out.println("1 not selected");
willRerollDiceOne = false;
}
if (box2.isSelected()) {
System.out.println("2 is selected");
willRerollDiceTwo = true;
}
else {
//System.out.println("2 not selected");
willRerollDiceTwo = false;
}
if (box3.isSelected()) {
System.out.println("3 is selected");
willRerollDiceThree = true;
}
else {
//System.out.println("3 not selected");
willRerollDiceThree = false;
}
if (box4.isSelected()) {
System.out.println("4 is selected");
willRerollDiceFour = true;
}
else {
//System.out.println("4 not selected");
willRerollDiceFour = false;
}
if (box5.isSelected()) {
System.out.println("5 is selected");
willRerollDiceFive = true;
}
else {
//System.out.println("5 not selected");
willRerollDiceFive = false;
}
if ("menu".equals(area)) {
if(e.getSource() == textYes){
start("yes");
}
if(e.getSource() == textNo){
start("no");
}
}
if ("choiceReroll".equals(area)) {
if(e.getSource() == textYes){
choiceReroll = "yes";
}
if(e.getSource() == textNo){
choiceReroll = "no";
}
}
}
我在想它和JButtons有某种联系
如果需要显示更多代码,请告诉我
无论如何,任何和所有的帮助都是感激的
谢谢你的帮助和时间
编辑:很抱歉,我忘记显示附加到JBUttons的侦听器:
textYes.addActionListener(this);
textNo.addActionListener(this);
编辑:还有,这里是Game()方法:
以及rollDice方法:
看起来您从未将任何侦听器附加到按钮,而是尝试从System.in读取。如果这是真的,那么程序将挂起,等待System.in的输入 而不是
Scanner is = new Scanner(System.in);
...
area = "menu";
menu = is.next();
在按钮上使用actionListeners,使用
textYes.addActionListener(/*Your Action Listener*/);
...
编辑-即使附加了ActionListeners,它也会挂在扫描行上,试图读取输入流。删除这些行应该可以解决此问题。看起来您从未将任何侦听器附加到按钮,而是尝试从System.in读取。如果这是真的,那么程序将挂起,等待System.in的输入 而不是
Scanner is = new Scanner(System.in);
...
area = "menu";
menu = is.next();
在按钮上使用actionListeners,使用
textYes.addActionListener(/*Your Action Listener*/);
...
编辑-即使附加了ActionListeners,它也会挂在扫描行上,试图读取输入流。删除这些行应该可以解决问题。问题是您的
ActionListener
在不使用新线程的情况下执行所有操作。这意味着您正在冻结UI线程,这基本上会阻止UI刷新
您可以在actionPerformed
方法中使用线程
public void actionPerformed(final ActionEvent e) {
Thread t = new Thread() {
public void run() {
//jTextArea1.setText(null);
if (box1.isSelected()) {
System.out.println("1 is selected");
willRerollDiceOne = true;
}
else {
//System.out.println("1 not selected");
willRerollDiceOne = false;
}
if (box2.isSelected()) {
System.out.println("2 is selected");
willRerollDiceTwo = true;
}
else {
//System.out.println("2 not selected");
willRerollDiceTwo = false;
}
if (box3.isSelected()) {
System.out.println("3 is selected");
willRerollDiceThree = true;
}
else {
//System.out.println("3 not selected");
willRerollDiceThree = false;
}
if (box4.isSelected()) {
System.out.println("4 is selected");
willRerollDiceFour = true;
}
else {
//System.out.println("4 not selected");
willRerollDiceFour = false;
}
if (box5.isSelected()) {
System.out.println("5 is selected");
willRerollDiceFive = true;
}
else {
//System.out.println("5 not selected");
willRerollDiceFive = false;
}
if ("menu".equals(area)) {
if(e.getSource() == textYes){
start("yes");
}
if(e.getSource() == textNo){
start("no");
}
}
if ("choiceReroll".equals(area)) {
if(e.getSource() == textYes){
choiceReroll = "yes";
}
if(e.getSource() == textNo){
choiceReroll = "no";
}
}
}
};
t.start();
}
使用线程将防止UI冻结
更新
正如MadProgrammer所说,在这种情况下,最好使用一个线程而不是一个线程。问题是您的
ActionListener
在不使用新线程的情况下执行所有操作。这意味着您正在冻结UI线程,这基本上会阻止UI刷新
您可以在actionPerformed
方法中使用线程
public void actionPerformed(final ActionEvent e) {
Thread t = new Thread() {
public void run() {
//jTextArea1.setText(null);
if (box1.isSelected()) {
System.out.println("1 is selected");
willRerollDiceOne = true;
}
else {
//System.out.println("1 not selected");
willRerollDiceOne = false;
}
if (box2.isSelected()) {
System.out.println("2 is selected");
willRerollDiceTwo = true;
}
else {
//System.out.println("2 not selected");
willRerollDiceTwo = false;
}
if (box3.isSelected()) {
System.out.println("3 is selected");
willRerollDiceThree = true;
}
else {
//System.out.println("3 not selected");
willRerollDiceThree = false;
}
if (box4.isSelected()) {
System.out.println("4 is selected");
willRerollDiceFour = true;
}
else {
//System.out.println("4 not selected");
willRerollDiceFour = false;
}
if (box5.isSelected()) {
System.out.println("5 is selected");
willRerollDiceFive = true;
}
else {
//System.out.println("5 not selected");
willRerollDiceFive = false;
}
if ("menu".equals(area)) {
if(e.getSource() == textYes){
start("yes");
}
if(e.getSource() == textNo){
start("no");
}
}
if ("choiceReroll".equals(area)) {
if(e.getSource() == textYes){
choiceReroll = "yes";
}
if(e.getSource() == textNo){
choiceReroll = "no";
}
}
}
};
t.start();
}
使用线程将防止UI冻结
更新
正如MadProgrammer所说,在这种情况下,最好使用一个而不是一个线程我怀疑
ChoiceRollDice
正在使用一个扫描器从用户那里读取输入,这会阻塞事件调度线程,阻止它被重新绘制
您将CLI范例与GUI范例混合在一起,这再次提出了一个问题:为什么
使用图形界面时,不应使用CLI样式的输入(即
扫描仪
),而应使用可用的图形控件,例如按钮或文本字段我怀疑ChoiceRollDice
正在使用扫描仪从用户读取输入,这将阻止事件调度线程,阻止其重新绘制
您将CLI范例与GUI范例混合在一起,这再次提出了一个问题:为什么
使用图形界面时,不应使用CLI样式的输入(即
扫描仪
),而应使用可用的图形控件,例如按钮或文本字段游戏()的功能是什么?它看起来像是在UI线程中进行处理,这使得UI无法更新。游戏运行几种不同的方法。我可以很快地发布Game()方法。我们还需要所有的rollDice方法。当然,我也会把它们放上去。即使它们所做的只是掷骰子,Game()
做什么?它看起来像是在UI线程中进行处理,这使得UI无法更新。游戏运行几种不同的方法。我可以很快发布Game()方法。我们还需要所有的rollDice方法。当然,我也会把它们放上去。尽管它们所做的只是掷骰子。很抱歉,我确实有一些听众,我只是没提到。删除哪一行<代码>菜单=is.next()代码>?扫描器is=新扫描器(System.in);“和“菜单=is.next;”行。除非你想让用户输入他们的回复,否则这些都是不需要的。即使去掉那些线,它仍然有同样的问题。此外,每当我尝试使用textYes.addActionListener()时代码>它告诉我它不是抽象的。对此很抱歉,但我确实附加了一些侦听器,我只是没有提到。删除哪些行<代码>菜单=is.next()代码>?扫描器is=新扫描器(System.in);“和“菜单=is.next;”行。除非你想让用户输入他们的回复,否则这些都是不需要的。即使去掉那些线,它仍然有同样的问题。此外,每当我尝试使用textYes.addActionListener()时代码>它告诉我它不是抽象的。这不起作用,它只是说“线程不能应用于给定的类型”和“局部变量e是从内部类中访问的;需要声明为final”。还有其他想法吗?非常感谢。@user2506658是的,Thread
不能使用局部变量,除非它们是final
。因此,您需要使用final
变量或。对于无法应用于给定类型的线程,抛出的异常的完整消息是什么?@user2506658请参见我的编辑,将public void actionPerformed(ActionEvent e)
更改为public void actionPerformed(final ActionEvent e)
从内部类访问局部变量e;需要声明最终错误应消失“方法”
public void actionPerformed(final ActionEvent e) {
Thread t = new Thread() {
public void run() {
//jTextArea1.setText(null);
if (box1.isSelected()) {
System.out.println("1 is selected");
willRerollDiceOne = true;
}
else {
//System.out.println("1 not selected");
willRerollDiceOne = false;
}
if (box2.isSelected()) {
System.out.println("2 is selected");
willRerollDiceTwo = true;
}
else {
//System.out.println("2 not selected");
willRerollDiceTwo = false;
}
if (box3.isSelected()) {
System.out.println("3 is selected");
willRerollDiceThree = true;
}
else {
//System.out.println("3 not selected");
willRerollDiceThree = false;
}
if (box4.isSelected()) {
System.out.println("4 is selected");
willRerollDiceFour = true;
}
else {
//System.out.println("4 not selected");
willRerollDiceFour = false;
}
if (box5.isSelected()) {
System.out.println("5 is selected");
willRerollDiceFive = true;
}
else {
//System.out.println("5 not selected");
willRerollDiceFive = false;
}
if ("menu".equals(area)) {
if(e.getSource() == textYes){
start("yes");
}
if(e.getSource() == textNo){
start("no");
}
}
if ("choiceReroll".equals(area)) {
if(e.getSource() == textYes){
choiceReroll = "yes";
}
if(e.getSource() == textNo){
choiceReroll = "no";
}
}
}
};
t.start();
}