关于JPanel的刷新问题..

「已注销」 2012-08-30 12:49:52
代码如下,右键点按钮运行后想实现没隔一秒出现一个按钮,但总是在时间结束后所有按钮都一块出来..
求帮忙解决...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class forLP extends JDialog implements ActionListener{

JPanel panel_total ;
JPanel panel_center ;
JPanel panel_north;

public static void main(String[] args) throws InterruptedException{
new forLP().doIt();
}

public forLP(){
super();
}

public void doIt() throws InterruptedException {
panel_total = new JPanel(new BorderLayout());

panel_north = getNorthPanel();
panel_total.add(panel_north,BorderLayout.NORTH);

panel_center = new JPanel();
panel_total.add(panel_center,BorderLayout.CENTER);

this.add(panel_total);
this.setSize(500, 500);
this.setVisible(true);
}

private void setCenterPanel() throws InterruptedException {

int x = 250 ;
int y = 250 ;
int flag = 1 ;

panel_center.setLayout(null);
JButton jb = getButton(x,y);
jb.setBackground(getRandomColor());
panel_center.add(jb);
panel_center.updateUI();

/**
* 新建两个线程,每割1秒刷新出一个按钮
* 但是为什么总是到第二秒的时候两个按钮一起出来呢。。
*/

SwingUtilities.invokeLater(new Runnable(){
public void run() {
try {
Thread.sleep(1000);
JButton jb = getButton(250, 300);
panel_center.add(jb);
panel_center.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

SwingUtilities.invokeLater(new Runnable(){
public void run() {
try {
Thread.sleep(2000);
JButton jb = getButton(350, 300);
panel_center.add(jb);
panel_center.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

// for( int i = 1 ; i < 2 ; i ++){
// if( i%2 == 1){
// for(int j = 0 ; j < i ; j ++){
// y = y + 20;
// addButton(x,y,flag);
// flag ++ ;
// }
// for(int k = 0 ; k < i ; k ++){
// x = x + 20 ;
// addButton(x,y,flag);
// flag ++ ;
// }
// }else {
// for(int j = 0 ; j < i ; j ++){
// y = y - 20;
// addButton(x,y,flag);
// flag ++ ;
// }
// for(int k = 0 ; k < i ; k ++){
// x = x - 20 ;
// addButton(x,y,flag);
// flag ++ ;
// }
// }
// }
}

public Color getRandomColor(){
Color color = new Color(
(new Double(Math.random() * 128)).intValue() + 128,
(new Double(Math.random() * 128)).intValue() + 128,
(new Double(Math.random() * 128)).intValue() + 128);
return color ;
}



private void addButton(final int x, final int y, final int flag) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
try {
Thread.sleep(1000*flag);
System.out.println("执行第"+flag+" 坐标:"+x+" " +y);
JButton jb = getButton(x, y);
panel_center.add(jb);
panel_center.repaint();
panel_center.updateUI();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}

private JButton getButton(int x,int y) {
JButton jb = new JButton();
jb.setPreferredSize(new Dimension(10,10));
jb.setBounds(x, y, 10, 10);
jb.setBackground(getRandomColor());
jb.setVisible(true);
return jb;
}

private JPanel getNorthPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JButton btn_1 = new JButton("点我");
btn_1.addActionListener(this);
panel.add(btn_1);
return panel;
}

@Override
public void actionPerformed(ActionEvent e) {
try {
setCenterPanel();
} catch (InterruptedException e1) {
e1.printStackTrace();
}

}

}
...全文
416 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2012-09-04
  • 打赏
  • 举报
回复
谢谢 ldh911 耐心解答。。。
MiceRice 2012-08-30
  • 打赏
  • 举报
回复
我要汗死啊,强调多次了,别把Sleep写在 里面,你写在里面就是GUI主线程在Sleep,它去Sleep了那还有时间去刷新你的界面。。。

repaint() 并不是立即刷新,而是把任务加入到 GUI 主线程的“待办事项列表”中去而已。。。

而这个“待办事项列表”中,你之前连续执行的好几次“SwingUtilities.invokeLater”,都还排在前面呢。。。


     try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JButton jb = getButton(250, 300);
panel_center.add(jb);
panel_center.repaint();
}
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable(){
public void run() {
Thread.sleep(2000);
JButton jb = getButton(350, 300);
panel_center.add(jb);
panel_center.repaint();
}
});
「已注销」 2012-08-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

引用 4 楼 的回复:
我原来那个主线程sleep1秒完后,为什么不刷新呢


要主线程要一直把整个函数执行完毕结束后,主线程才能继续干别的事情。

仅就一条线程本身,可不支持并发,只能顺序执行,一件事情一件事情(函数调用)的顺序做完。
[/Quote]


SwingUtilities.invokeLater(new Runnable(){
public void run() {
try {
Thread.sleep(1000);
JButton jb = getButton(250, 300);
panel_center.add(jb);
panel_center.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

SwingUtilities.invokeLater(new Runnable(){
public void run() {
try {
Thread.sleep(2000);
JButton jb = getButton(350, 300);
panel_center.add(jb);
panel_center.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

这段代码的执行顺序:
先进第一个SwingUtilities,sleep1秒,刷新
再进第二个SwingUtilities,sleep2秒,刷新
顺序是这样吗?
在第二次sleep之前的刷新操作为什么不执行呢。。。。
谢谢。。。
MiceRice 2012-08-30
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
我原来那个主线程sleep1秒完后,为什么不刷新呢
[/Quote]

要主线程要一直把整个函数执行完毕结束后,主线程才能继续干别的事情。

仅就一条线程本身,可不支持并发,只能顺序执行,一件事情一件事情(函数调用)的顺序做完。
scbb 2012-08-30
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

引用 2 楼 的回复:

主GUI线程只有1条哦,亲。。。

你在主GUI线程里面 Thread.sleep(1000); 整个GUI 就 1秒钟啥都不干哦,亲。。。


所以你只能是在另外一个线程中进行 Sleep 之类的行为,调用 SwingUtilities.invokeLater() 时就做一件事情,显示按钮。

比如:
Java code
new Thread(……
[/Quote]

主线程就是UI线程,所以UI刷新的也在等你那1秒呢。





swing是非线程安全的,也就是说,如果多个线程同时对一个swing组件进行操作,很可能会引发异常等问题,以至程序崩溃。毕竟,repaint是一个比较花费时间的操作,如果一个swing组件在repaint的过程中,其内容被更改,就会导致repaint的内容与修改后的内容不符,可能导致访问错误(比如多线程环境下修改一个List的item项)。

使用Swing的时候,有几个需要注意的地方。首先,当一个swing窗体被创建并现实的时候,会有一个叫做“事件分派线程”的线程被创建,所有的事件处理方法(repaint、actionPerformed等等)都是由这个线程负责执行的,也就是说,整个swing窗体(包含其中的组件)都是这个线程支撑的。

使用swing的几个规则:

1)如果遇到耗时的或者可能阻塞的事情要去做,就创建一个线程去处理它。比如,文件io、网络连接、大规模数据处理。不要放在事件分派线程中处理,以免导致swing界面不响应。

2)如果一个处理需要从swing ui中读取数据,则应该在此方法处理任何具体事情前,将所有数据从UI中读取完毕,然后再处理。

3)如果你需要等待一个固定的时间,使用Timer而不要让事件分派线程sleep();,因为这里一sleep,别的事件就没法处理了。

4)不要在别的线程中操作ui,应该设置相应参数,让事件分派线程操作ui,保证只有一个线程操作swing这个线程非安全的东西。(swing程序的单一线程规则)
「已注销」 2012-08-30
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

主GUI线程只有1条哦,亲。。。

你在主GUI线程里面 Thread.sleep(1000); 整个GUI 就 1秒钟啥都不干哦,亲。。。


所以你只能是在另外一个线程中进行 Sleep 之类的行为,调用 SwingUtilities.invokeLater() 时就做一件事情,显示按钮。

比如:
Java code
new Thread(){
public void……
[/Quote]

我原来那个主线程sleep1秒完后,为什么不刷新呢
「已注销」 2012-08-30
  • 打赏
  • 举报
回复
解决了,非常感谢。
MiceRice 2012-08-30
  • 打赏
  • 举报
回复
主GUI线程只有1条哦,亲。。。

你在主GUI线程里面 Thread.sleep(1000); 整个GUI 就 1秒钟啥都不干哦,亲。。。


所以你只能是在另外一个线程中进行 Sleep 之类的行为,调用 SwingUtilities.invokeLater() 时就做一件事情,显示按钮。

比如:
new Thread(){
public void run() {
Thread.sleep(1000);
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JButton jb = getButton(250, 300);
panel_center.add(jb);
panel_center.repaint();
}
}
Thread.sleep(1000);
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JButton jb = getButton(250, 300);
panel_center.add(jb);
panel_center.repaint();
}
}
}
}.start();

51,411

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧