在Java Swing编程中,往往会遇到需要动态刷新界面的时候,例如动态刷新JLabel的文本,JTextField里的文本等等。但是往往却没有达到我们预期的效果,我相信很多朋友都遇到过本文将要说的这个问题。

如下图的Swing界面中,我们期望在点击按钮时,Jlabel和JTextField里的文本能不断的变化,并实时地显示出来。

这个例子中,我们期望点击按钮后,JLabel和JTextField中每隔一秒钟刷新一下文本,顺序的显示以下的几句文本:

Button clicked

Start to change text...

接着显示数字1到10

action end

很多人都会像下面的代码这样实现这个功能:

MainFrame.java

package com.longyg.test;

public class MainFrame extends javax.swing.JFrame {

    public MainFrame() {
initComponents();
} @SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() { jLabel = new javax.swing.JLabel();
labelText = new javax.swing.JLabel();
jTextField = new javax.swing.JLabel();
fieldText = new javax.swing.JTextField();
button = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); jLabel.setText("JLabel:"); labelText.setBorder(javax.swing.BorderFactory.createEtchedBorder()); jTextField.setText("JTextField: "); button.setText("click");
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonActionPerformed(evt);
}
}); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(button)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(labelText, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(jTextField)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fieldText, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(17, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(20, 20, 20)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel)
.addComponent(labelText, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jTextField)
.addComponent(fieldText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(button)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); pack();
}// </editor-fold> private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
changeText("Button clicked");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
changeText("Start to change text...");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
for (int i = 0; i < 10; i++) {
changeText((i+1)+"");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
changeText("action end");
} private void changeText(String text) {
labelText.setText(text);
fieldText.setText(text);
} /**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
new MainFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton button;
private javax.swing.JTextField fieldText;
private javax.swing.JLabel jLabel;
private javax.swing.JLabel jTextField;
private javax.swing.JLabel labelText;
// End of variables declaration
}

可以看到,在buttonActionPerformed方法中,我们多次调用了setText来期望改变JLabel和JTextField中的文本。

当我们运行这段代码,你会很遗憾的发现,点击click后,JLabel和JTextField中并没有如我们所期望的不断的更新并显示不同的文本。而是点击按钮后,界面仿佛被卡住一样,等过了一段时间后,显示出最后一句文本“action end”。

为什么会发生这样奇怪的现象呢?

Java Swing中,界面刷新是线程同步的,也就是说同一时间,只有一个线程能执行刷新界面的代码。如果要多次不断地刷新界面,必须在多线程中调用刷新的方法。

本例中,在buttonActionPerformed方法中多次调用了setText方法来试图刷新JLabel和JTextField的文本。buttonActionPerformed方法运行在主线程中,所以每次调用setText都是运行在主线程中,而且是顺序的执行的。在前面几次调用setText后,线程并没有退出,所以界面刷新线程不能获得执行刷新的机会。而当最后一次setText后,线程退出,界面才能执行刷新。所以我们只能看到最后一次setText的值。

因此,要解决这个问题,我们必须把buttonActionPerformed方法中的代码段放到一个单独的线程中执行。这样它就不会使线程阻塞,当每次setText后,界面刷新线程也能得到执行的机会,从而刷新界面。

下面是修改后的代码,只有buttonActionPerformed方法的代码被修改,其他部分的代码与上面的完全一致。

private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
new Thread(new Runnable() {
@Override
public void run() {
changeText("Button clicked");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
changeText("Start to change text...");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
for (int i = 0; i < 10; i++) {
changeText((i+1)+"");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
changeText("action end");
}
}).start();
}

我们可以看到,新的buttonActionPerformed方法中,仅仅是把整个代码段放在了一个线程中,并启动了线程。

我们在每次setText后,都睡眠了1秒钟,是为了看到界面真的实时的变化了,如果不睡眠,界面刷新会一闪而过,不利于观察。

再次运行代码,会发现,终于得到了我们期望的效果:JLabel和JTextField中的文本动态的变化了!

http://www.cnblogs.com/longyg/archive/2012/07/03/2575482.html

Swing界面刷新问题(转)的更多相关文章

  1. Android界面刷新之invalidate与postInvalidate的区别

    Android的invalidate与postInvalidate都是用来刷新界面的. 在UI主线程中,用invalidate():本质是调用View的onDraw()绘制. 主线程之外,用postI ...

  2. Android之界面刷新(invalidate和postInvalidate使用)

    Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用. Android提供了Inva ...

  3. 可视化swing界面编辑--转载

    原文地址:http://279234058.iteye.com/blog/2200122 今天发现了一个WindowBuilder插件,功能好强大,啊哈哈,从此告别手动编辑swing界面代码,直接像V ...

  4. Android界面刷新

    Android的invalidate与postInvalidate都是用来刷新界面的,用法区别在于: 1)invalidate():实例化一个Handler对象,并重写handleMessage方法调 ...

  5. Android界面刷新方法

    Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中 ...

  6. androidTv界面刷新跳动的问题

    今天刚完成老大要求的新模块,在界面刷新的时候遇到了一些问题:一个scrollview动态的添加控件且控件中的数据进行更换的时候,出现的界面跳动的问题 刚开始以为是界面没有展示完全配合scrollvie ...

  7. Swing界面组件的通用属性

    ----------------siwuxie095                             Swing 界面组件(控件)的通用属性:         (1)enabled:启用/禁用 ...

  8. Java AWT组件开发和Swing界面编程

    一.AWT组件开发 1.AWT AWT是抽象窗口工具箱的缩写,它为编写图形用户界面提供了用户接口,通过这个接口就可以继承很多方法,省去了很多工作.AWT还能使应用程序更好地同用户进行交互. AWT中的 ...

  9. WPF 数据绑定,界面刷新的两种方法-----INotifyPropertyChanged

    .Netformwork4.0及以下版本 -------INotifyPropertyChanged 命名空间: System.ComponentModel 后台代码 public partial c ...

随机推荐

  1. Trufun云端建模平台之云端UML工具发布

    Trufun云端建模平台包括云端UML工具,云端BPMN工具,云端思维导图工具. 云端UML工具是目前最先进的基于HTML5的UML2.x建模工具,所有代码基于JAVA开发,支持类图.用例图.活动图. ...

  2. camel-name-utils 在驼峰风格跟下划线风格之间切换

    用处 用来将字符串在驼峰风格跟下划线风格之间切换. 对于一般人可能没用.对于写orm框架的人有点作用. 样例: company_name -> companyName 安装方式 加入下面依赖到p ...

  3. rsyslog+LogAnalyzer 日志收集

    Linux 之rsyslog+LogAnalyzer 日志收集系统 一.LogAnalyzer介绍 LogAnalyzer工具提供了一个易于使用,功能强大的前端,用于搜索,查看和分析网络活动数据,包括 ...

  4. 在VC++中启用内存泄露检测

    检测内存泄漏的主要工具是调试器和 CRT 调试堆函数.若要启用调试堆函数,请在程序中包括以下语句: #define CRTDBG_MAP_ALLOC#include <stdlib.h># ...

  5. 查看进程所用的内存(使用GetWindowThreadProcessId取得进程ID,OpenProcess打开进程和GetProcessMemoryInfo取得内存信息)

    // function GetProcessMemorySize(_sProcessName: string; var _nMemSize: Cardinal): Boolean; var l_nWn ...

  6. Hibernate(六)——多对多关联映射

    前面几篇文章已经较讲解了三大种关联映射,多对多映射就非常简单了,不过出于对关联映射完整性的考虑,本文还是会简要介绍下多对多关联映射. 1.单向多对多关联映射 情景:一个用户可以有多个角色,比如数据录入 ...

  7. 14.3.3 Locks Set by Different SQL Statements in InnoDB 不同的SQL语句在InnoDB里的锁设置

    14.3.3 Locks Set by Different SQL Statements in InnoDB 不同的SQL语句在InnoDB里的锁设置 locking read, 一个UPDATE,或 ...

  8. oschina图形和图像工具开源软件

    图形和图像工具开源软件 http://www.oschina.net/project/tag/181/imagetools?sort=view&lang=21&os=0

  9. 【编程之美】java二进制实现重建

    package com.cn.binarytree.utils; /** * @author 刘利娟 liulijuan132@gmail.com * @version 创建时间:2014年7月20日 ...

  10. 浅谈 Python 程序和 C 程序的整合

    源地址:http://www.ibm.com/developerworks/cn/linux/l-cn-pythonandc/ 概览 Python 是一种用于快速开发软件的编程语言,它的语法比较简单, ...