我是一个初学者,在路上遇到了坎坷。
我遇到的问题是我的 JTextArea
在程序运行时没有更新。我运行命令行来查看 JTextArea 的值是否正在更改。事实证明确实如此,但在用户界面上它直到最后都保持不变,然后它显示了我所做的最终更改。您能帮我找到解决这个问题的方法吗?
下面是出现问题的代码。 (在我的 ActionListener
中。)
private class ButtonHandler implements ActionListener //Start of inner class for event handling of buttons
{
public void actionPerformed( ActionEvent event )
{//start method that prosesses the events for the buttons
if(event.getSource() == call)
{
do {
delay.myDelay(2000); //simply a Thread.sleep(I intend to repeat this a lot so I made a class for it.
elevatorFloor = eCall.calling();
eCall.setFloor(elevatorFloor);
System.out.println("getfloor in call= " +eCall.getFloor()); //Test yields correct value
eFloor = ind.level(eCall.getFloor()); //String that gives floor number
floorIndicator.setText(eFloor); //DOES NOT CHANGE IN GUI
String value = floorIndicator.getText();
System.out.println("Floorindicator is= " +value);//Test yields that the value is changing dynamically in command line
floorIndicator.updateUI(); //Stuff I found on the internet that didnt work
floorIndicator.revalidate();
floorIndicator.validate();
} while(eCall.getFloor() != eCall.getUserFloor());
delay.myDelay(2000);
doorImage.setIcon(door1);
}
}
}
最佳答案
在 Java 中,UI(组件、事件等的绘制)由一个名为 Event Dispatching Thread 的特殊线程处理。 。由于该线程决定了 UI 响应事件的速度,因此仅对其执行与 UI 相关的操作非常重要。
不建议在此线程中执行可能阻塞的操作,例如 Thread.sleep ,因为它会阻塞线程的执行,从而使您的应用程序无法响应线程中的事件。及时的方式。这就是为什么在一些评论中,您被告知您正在阻止 EDT。
在您的情况下,也可以避免循环,因为每次迭代时,您都会等待两秒钟(我假设给出自动扶梯在楼层之间移动的印象)。
解决这个问题的方法(至少是其中之一)是将 do...while 循环的整个主体放在一个单独的线程中。然后该线程将由事件处理程序启动。此解决方案不会阻塞事件调度线程,但现在还有另一个问题:只有 EDT 可以上传 UI,因此,上述方法本身不会更改文本。
为此,Java 提供了 SwingWorker
允许代码在 EDT 上对项目进行排队的类。
因此,简而言之,您的代码会像这样:
private class ButtonHandler implements ActionListener //Start of inner class for event handling of buttons
{
public void actionPerformed( ActionEvent event )
{//start method that prosesses the events for the buttons
if(event.getSource() == call)
{
//final int elFloor = eCall.calling(); i ran it without this and it worked
new Thread(new Runnable() {
@Override
public void run() {
do{
/*There is nothing wrong with calling Thread.sleep directly
*wrapping a one liner with your own implementation might cause
*more confusion
*/
delay.myDelay(2000);
//Not sure what is elevatorFloor
elevatorFloor = eCall.calling();
eCall.setFloor(elevatorFloor);
System.out.println("getfloor in call= " +eCall.getFloor()); //Test yields correct value
eFloor = ind.level(eCall.getFloor()); //String that gives floor number
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
floorIndicator.setText(eFloor); //DOES NOT CHANGE IN GUI
}
});
String value = floorIndicator.getText();
System.out.println("Floorindicator is= " +value);//Test yields that the value is changing dynamically in command line
}while(eCall.getFloor() != eCall.getUserFloor());
//delay.myDelay(2000);
doorImage.setIcon(door1);
}
}).start();
}
}
}
注意:上面的代码尚未经过测试,您可能需要进行其他更改,特别是关于如何从线程范围内访问变量,但它应该提供您需要执行的操作的概述。
关于java - 在 Java 中更新 JTextArea 的 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30214507/