4

我有一个 Main JPanel,它的布局设置为 CardLayout。

主 JPanel 有 4 张卡片:Card1JPanel、Card2JPanel、Card3JPanel、Card4JPanel。

我还有一个名为“MySwingy”的 SwingWorker 类,当它的循环标志设置为 true 时,它​​会永远执行某些操作。

当 Card1JPanel 可见/显示时,我想执行 MySwingy 工作者。

当 Card1JPanel 不可见/隐藏时,我想停止 MySwingy 工作人员;

以下是我目前拥有的代码,我想知道是否有更好/更清洁的方法来解决上述问题。在下面的代码示例中,您将看到我使用 Card1JPanel 的 ComponentListener 来检测它是显示还是隐藏,但是如果我有很多很多卡片,每个卡片都有自己的 ComponentListener 事件,这些事件侦听器会减慢我的应用程序吗?

非常感谢你

public class Card1JPanel extends JPanel{

    private MySwingy mySwingy;
    private JTable tableDatabase;

    public Card1JPanel(){
        initComponents();//tableDatabase is drawn here among other things
        this.addComponentListener(new myListener());
    }

    class myListener implements ComponentListener {

        @Override
        public void componentHidden(ComponentEvent e) {
            try{
                mySwingy.stopExecuting();//A flag inside of the worker gets set to false that terminates the while(true) loop.
            }catch(NullPointerException ex){
            }
        }

        @Override
        public void componentMoved(ComponentEvent e) {
        }

        @Override
        public void componentResized(ComponentEvent e) {
        }

        @Override
        public void componentShown(ComponentEvent e) {
            mySwingy = new MySwingy(tableDatabase);
            mySwingy.execute();
        }
    }
}

编辑:显示 mySwingy 的作用:

MySwingy 用于解析来自 SQL 数据库的数据,并在数据库中的数据发生更改时更新 tableDatabase。tableDatabase 位于 Card1JPanel 上,并使用 SwingUtilities.InvokeLater 在 MySwingy 的 EDT 上更新。在我的应用程序中,我有许多带有 JTables 和 SwingWorkers 的卡片 (JPanels),它们在 EDT 上更新他们的 JTables。现在,我确信如果所有这些 JTable 都从他们的 SwingWorkers 在 EDT 上不断更新,那么 GUI 将会冻结。因此,当 JPanel 不可见时,如何阻止 SwingWorker 更新 JTable?那是我的问题。

public class MySwingy extends SwingWorker<Void,Void>{

    private JTable tableDatabase;
    private boolean isStopExecuting;
    private boolean isDatabaseDataChanged;

    public MySwingy(JTable tableDatabase){
        this.tableDatabase = tableDatabase
        isStopExecuting = false;
        isDatabaseDataChanged = false;
    }

    public void stopExecuting(){
        isStopExecuting = true;
    }

    @Override
    public Void doInBackground(){

        while(isStopExecuting == false){

            //Here is the code that parses some data from an SQL database and if the data in the SQL database
            //has changed the isDatabaseDataChanged boolean flag is set to true,
            //else isDatabaseDataChanged boolean flag is set to false;

            if(isDatabaseDataChanged == true){

                isDatabaseDataChanged = false;

                SwingUtilities.InvokeLater(new Runnable(){

                    @Override
                    public void run(){

                    //Update tableDatabase rows with new data

                    }
                });
            }
        }

    return null;

    }
}
4

1 回答 1

4

不要切换工人;让它运行。相反,仅当它isVisible()直接通过process()或间接通过属性更改时才有条件地更新视图。

附录:一些有用的评论值得仔细研究。

  • 正如@Andrew 所说,很大程度上取决于工人的任务。可以在后台线程上演化模拟模型,但任何渲染都必须事件调度线程上进行。

  • 我的困惑不亚于@mKorbel;你要求对解决方案进行批判性评估,但没有说明它要解决什么问题。

  • @kleopatra 指出 SwingWorker 被设计为只执行一次。任何从另一个线程控制循环的尝试doInBackground()都将难以同步。还要检查您的任务的预期延迟,此处提到。的实例javax.swing.Timer,它暴露start()stop()方法,可能是一个替代方案。

  • 更新的问题:如果您的工作人员需要轮询具有可变延迟的数据源,java.util.Timer请在后台线程中使用以可持续的速度执行触发器查询。

于 2012-09-08T01:46:07.823 回答