我有一个主JPanel,其布局设置为CardLayout。

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

我还有一个名为“MySwingy”的SwingWorker类,当其循环标志设置为true时,该类将永久执行某些操作。

当Card1JPanel是可见/显示时,我要执行MySwingy worker。

当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将冻结。因此,当JTable的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;

    }
}

最佳答案

不要切换工人;让它运行。取而代之的是,仅在通过isVisible()或通过属性更改间接地添加process()时,才有条件地更新视图。

附录:一些有用的评论值得仔细检查。

  • 正如@Andrew所指出的,很大程度上取决于工作人员的任务。可能会在后台线程上演化模拟的模型,但是任何渲染都必须在event dispatch thread上进行。
  • 我和@mKorbel一样困惑。您已经要求对解决方案进行严格的评估,而没有说明解决方案将要解决的问题。
  • @kleopatra指出SwingWorker设计为executed only once。从另一个线程控制doInBackground()循环的任何尝试都将难以同步。还要检查您的任务的预期延迟,提到了here。可以公开一个javax.swing.Timerstart()方法的stop()实例,可以替代。
  • Updated question:如果您的工作人员需要轮询具有可变延迟的数据源,请在后台线程中使用java.util.Timer以可持续的速度执行触发器查询。
  • 10-04 14:36