正在为 Java 中的 JTextArea 更新 UI
Updating UI for JTextArea in Java
我是初学者,在路上遇到了一个坎。
我的问题是我的 JTextArea
没有更新,因为我的程序是 运行。我用运行命令行查看JTextArea
的值是否在变化。事实证明是的,但是在 UI 上它一直保持到最后,然后它显示了我所做的最终更改。你能帮我找到解决这个问题的方法吗?
下面是出现问题的代码。 (在我的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
class 允许代码在 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();
}
}
}
注意:上面的代码尚未经过测试,您可能需要进行其他更改,尤其是在如何从线程范围内访问变量方面,但它应该提供您需要执行的操作的概述。
我是初学者,在路上遇到了一个坎。
我的问题是我的 JTextArea
没有更新,因为我的程序是 运行。我用运行命令行查看JTextArea
的值是否在变化。事实证明是的,但是在 UI 上它一直保持到最后,然后它显示了我所做的最终更改。你能帮我找到解决这个问题的方法吗?
下面是出现问题的代码。 (在我的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
class 允许代码在 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();
}
}
}
注意:上面的代码尚未经过测试,您可能需要进行其他更改,尤其是在如何从线程范围内访问变量方面,但它应该提供您需要执行的操作的概述。