现在我的界面因为调用了后台数据库,所以显示很慢。
因为我是在界面构造的时候就开始时从后台取值来初始化控件的显示值,知道初始化完毕,才开始显示
伪代码如下public class ClientFrame extends JFrame
{
    public ClientFrame ()
    {
       addEveryJComponent();
       //因为后台数据库调用,非常耗费时间,所以最终的显示很慢 
       getValueFromBackGroud();
       initEveryJComponentValues();
       this.pack();
       this.setVisible(true);
    }
    
    //初始化那些与数据库相关联的控件的显示值 
    public void initEveryJComponentValues()
    {
    }
    //在frame上添加各种组件
    private void addEveryJComponent
    {
       Container con = this.getContentPane();
       con.setLayout(...);
       con.add(..);
       .....
    }    private void getValueFromBackGroud()
    {
            //后台数据库调用,非常耗费时间
    }    public static void main(String[]  args)
    {
      ClientFrame  cf = new ClientFrame ();    }
}我最初的解决方案是就是增加一个内部类,该类继承Thread
然后在该内的run方法中,去调用后台数据库的操作public class ClientFrame extends JFrame
{
    public ClientFrame ()
    {
       addEveryJComponent();
       //将后台数据库调用的工作交给另外一个线程去做
       new InitThread().start();
       this.pack();
       this.setVisible(true);
    }
    
    //调用后台数据库操作的内部类
    class InitThread extends Thread()
    {
       public void run()
       {
       getValueFromBackGroud();
       initEveryJComponentValues();
       } 
    }
    //初始化那些与数据库相关联的控件的显示值 
    public void initEveryJComponentValues()
    {
    }
    //在frame上添加各种组件
    private void addEveryJComponent
    {
       Container con = this.getContentPane();
       con.setLayout(...);
       con.add(..);
       .....
    }    private void getValueFromBackGroud()
    {
            //后台数据库调用,非常耗费时间
    }    public static void main(String[]  args)
    {
      ClientFrame  cf = new ClientFrame ();    }
}我试了一下,好像是可以了,但是看了有关文档,说这样用是不符合官方规范的
最好是用SwingUtilities.invokeLater(new Runnable())
那是否意味着我把那个内部类作为参数传给SwingUtilities.invokeLater()即可呢?
那么就有下面的伪代码public class ClientFrame extends JFrame
{
    public ClientFrame ()
    {
       addEveryJComponent();
       //将后台数据库调用的工作交给另外一个线程去做
      SwingUtilities.invokeLater(new InitThread());
       this.pack();
       this.setVisible(true);
    }
    
    //调用后台数据库操作的内部类
    class InitThread extends Thread()
    {
       public void run()
       {
       getValueFromBackGroud();
       initEveryJComponentValues();
       } 
    }
    //初始化那些与数据库相关联的控件的显示值 
    public void initEveryJComponentValues()
    {
    }
    //在frame上添加各种组件
    private void addEveryJComponent
    {
       Container con = this.getContentPane();
       con.setLayout(...);
       con.add(..);
       .....
    }    private void getValueFromBackGroud()
    {
            //后台数据库调用,非常耗费时间
    }    public static void main(String[]  args)
    {
      ClientFrame  cf = new ClientFrame ();    }
}
可是文档上这个SwingUtilities.invokeLater()其实是用来处理组件paint事件的,而我这是一个
后台获取数据的操作,不涉及到组件paintYou can't directly meddle with Swing components, 
or their backing data models from a second thread. 
The contract is, if you want to do anything to a Swing component that 
could have any effect on it's display from an application thread
 you should add it to the event dispatch thread's queue via 
SwingUtilities.invokeLater( Runnable ) or SwingUtilities.invokeAndWait( Runnable ) 
so that it will be done on the same thread that Swing itself uses.
 Obviously you can call Swing methods directly from the EventDispatchThread. 这是源话,我还是不大理解,最好是有大虾也能阐释一把所以我想知道,实现这么一个功能最好的方法(即先再前台快速显示界面,再在后台慢慢,也许也是快快的加载数据)是什么呢?请大虾指教

解决方案 »

  1.   

    swing要求,一旦组件被显示出来,那么所有影响到该组件的代码都应该在event-dispatching thread里面执行。
    在这里你可以通过这种方式来实现,启动一个线程来进行初始化加载数据更新界面,但是涉及更新界面的部分你应该放到SwingUtilities.invokeLater()或者SwingUtilities.invokeAndWait()里执行。
    例如
    SwingUtilities.invokeAndWait(new Runnable(){
    public void run(){
    void initEveryJComponentValues;
    }
    });
      

  2.   

    首先我先说明:我确实不大理解SwingUtilities.invokeAndWait()这个方法
    但是如果
    SwingUtilities.invokeAndWait(new Runnable(){
    public void run(){
      initEveryJComponentValues;
    }
    });
    看看java tutorial中描述
    The invokeAndWait method is just like invokeLater, except that invokeAndWait doesn't return 
    until the event-dispatching thread has executed the specified code.
    这样用的话,是否达不到我要的效果呢?这同样是要等
    initEveryJComponentValues这句代码是否是要等所有的界面绘制事件已经完成才往下走拉那么实际上就达不到并行的效果,所以界面出来后initEveryJComponentValues这句代码才会执行
    而如果用SwingUtilities.invokeLater(new Runnable(){
    public void run(){
      initEveryJComponentValues;
    }
    });就基本并行啊,因为在初始化界面的时候
    initEveryJComponentValues;就开始执行拉把
    请大虾指教啊
      

  3.   

    搂主可以学习一下这篇文章
    http://www.javaresearch.org/article/showarticle.jsp?column=287&thread=10141
    http://www.javaresearch.org/article/showarticle.jsp?column=287&thread=10165