作者sbrhsieh (十年~)
看板java
标题Re: [问题] GUI的动作写在递回里面
时间Thu Jan 3 03:16:18 2013
※ 引述《gp123 (George Peng)》之铭言:
: 这个问题很明显是thread的问题,
: 由於Swing元件的更新在另一个thread中进行,
: 而这个thread的优先权很低。
: : 我发现函式只会自己跑自己的
: : 但JLabel完全没有反应
: : 等到递回函式跑完了
: : Label才终於显示最後的状态
: : 可是中途完全没有任何反应
: 在你的状况中,
: 几乎要等到递回的method执行完後,
: 才有机会轮到Swing一次更新到最新状况,
: 才会造成你看到的结果。
: 通常不建议在一般的worker thread中直接操作Swing,
: 长时间的操作中更不合适,
: 可试着参考
: http://slientfreaky.blogspot.tw/2011/09/java-swing.html
: 的方式,
: 将你的函式移到GUI的执行绪中进行。
通常 GUI 回应不够及时(常见於提问中的说法是:中间变化略过直接显示最後的
状态),是由於在 UI Thread 做了耗时间的事,若这些事里头包含了操作 UI 组件
或变更组件资料/状态,就会出现『常见说法』中的情况。
这不是由於 UI Thread 的 priority 太低所致。
原帖主希望在一个递回函式的执行过程中由 UI 组件显示执行的状态(也许是每一个
call stack 的参数或某些状态),要这样子做来帮助了解递回函式执行的流程(教学
用的程式?)势必要在递回函式中加入 delay,否则程式执行的速度很快,肉眼是
无法观察到过程中 UI 组件显示的即时资讯(人的反应太慢)。
下面是一个以递回函式来做倒数的 demo(对,很矫情的 demo),它显示出一般
要做一件耗时的事情又需要在过程中更新 UI 组件来显示其 progress 的常见做法。
这只是一个用来点出某些观念(我在上一篇的推文)的demo,所以暂时请不要讲究
这倒数精不精确或其他小细节。
CountDownDemo.java(网页版:
http://ideone.com/VEY1io )
CountDown.java(网页版:
http://ideone.com/edwtgI )
*减少看官翻页动作,注解(讨论)写在前头,程式码殿後
如果把 start 按钮按下後的动作改成
counter.syncStart(10);
取代了原本的
counter.asyncStart(10);
这就是在 UI Thread(event-dispatching thread) 里做耗时的工作(倒数需要
好几秒),会导致倒数的期间(约 10 秒) GUI 像是死了一般(不会更新);直到
倒数完毕才直接显示 0 秒。
===========================================================================
CountDown.java
package cc.ptt;
public class CountDown {
public interface OnTickListener {
public void onTick(int seconds);
}
private static class NullTickListener implements OnTickListener {
@Override
public void onTick(int seconds) {
}
}
private static final OnTickListener nullListener
= new NullTickListener();
private OnTickListener tickListener = nullListener;
public void asyncStart(final int seconds) {
// run in some worker thread
new Thread(new Runnable() {
public void run() {
try {
count(tickListener, seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public void syncStart(int seconds) {
// run in the caller thread
try {
count(tickListener, seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void count(OnTickListener listener, int timeInSecs)
throws InterruptedException {
if (timeInSecs <= 0) {
listener.onTick(0);
return;
}
listener.onTick(timeInSecs);
Thread.sleep(1000);
count(listener, timeInSecs - 1);
}
public OnTickListener getTickListener() {
return tickListener == nullListener ? null : tickListener;
}
public void setTickListener(OnTickListener tickListener) {
if (tickListener == null)
this.tickListener = nullListener;
else
this.tickListener = tickListener;
}
}
===========================================================================
CountDownDemo.java
package cc.ptt;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class CountDownDemo {
public static void main(String[] args) {
JFrame frm = new JFrame("Demo for Java@ptt");
frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final JLabel messageBar = new JLabel("", JLabel.CENTER);
messageBar.setBorder(BorderFactory.createLoweredBevelBorder());
messageBar.setFont(messageBar.getFont().deriveFont(48f));
frm.getContentPane().add(messageBar);
final JButton start = new JButton("开始倒数 10 秒");
frm.getContentPane().add(start, BorderLayout.SOUTH);
final CountDown counter = new CountDown();
counter.setTickListener(new CountDown.OnTickListener() {
@Override
public void onTick(int seconds) {
// setText method is thread-safe
messageBar.setText(String.format("%d 秒", seconds));
if (seconds <= 0) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
start.setEnabled(true);
}
});
}
}
});
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
start.setEnabled(false);
counter.asyncStart(10);
// counter.syncStart(10);
}
});
frm.setSize(400, 400);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
}
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 1.172.190.207
※ 编辑: sbrhsieh 来自: 1.172.187.77 (01/04 01:31)