这都什么年代了,我还在用Java Swing做界面。
做八数码实验作业的时候,需要把搜索过程展示出来,我采用网格布局GridLayout, 3 ∗ 3 3*3 3∗3的九宫格,每个格子放了一个JTextField,搜索过程中要能实时改变并显示文本框的数字变化。
但是经历过的就知道,点击按钮后,开始搜索过程,这时候按钮会一直呈现出被点击的样式状态,主线程被阻塞了,所以Swing不能实时的更新,直到搜索完毕后(主线程返回后刷新),组件才刷新,就只展示了最后的状态。
如果想让这个更新立刻显示在界面上而不是等swing的主线程返回后刷新,也就是为了看到中间的搜索过程,可以另开一个线程,此时不管处理数据需要多长时间,只要组件内容更新后,文本框里就能实时呈现出来。
// 组件内容更新函数
private void drawRoute(){
// 开启多线程,更新显示进程,实现实时刷新
new Thread(new Runnable() {
public void run() {
// 组件更新
// ...
}
}).start();
}
比如,下面的两个框框里面是我的组件更新部分。
为了中间结果能更容易看清楚,每次改变之间休眠了1s,第335行。
然后在按钮btn的监听事件中调用该函数drawRoute:
JButton confirm = new JButton("开始");
confirm.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
if(originField.getText().isEmpty() || goalField.getText().isEmpty() ){
JOptionPane.showMessageDialog(null, "请输入初始序列和目标序列", "输入为空!", JOptionPane.ERROR_MESSAGE);
}
else{
IO();
if(!isSovable()){
JOptionPane.showMessageDialog(null, "这两个状态之间不可达。", "不可达状态!", JOptionPane.INFORMATION_MESSAGE);
}
else{
Solution start = new Solution(startId, n);
solutions.add(start);
heuristicSearch();
drawRoute();
}
}
}
});
启发式搜索求解八数码问题,源代码在其中贴出来了,能看到中间结果的感觉真好啊。
2021.10.20更新
之前理解有误,之前是把组件内容更新代码开了个线程,其实应该把耗时的计算操作开新线程,而简单的组件更新放在按钮的事件响应中。任何很耗时的任务(阻塞UI,让界面看上去像卡死)的操作都不应该放在addActionListener中。
private void drawRoute(){
// 开启多线程,更新显示进程,实现实时刷新
new Thread(new Runnable() {
public void run() {
// 耗时的计算操作
// ...
}
}).start();
}