4

メイン JPanel があり、そのレイアウトは CardLayout に設定されています。

メイン JPanel には、Card1JPanel、Card2JPanel、Card3JPanel、Card4JPanel の 4 つのカードがあります。

また、ループ フラグが true に設定されている間、永久に何かを実行する「MySwingy」という SwingWorker クラスもあります。

Card1JPanel が VISIBLE/SHOWN の場合、MySwingy ワーカーを実行したい。

Card1JPanel が NOT VISIBLE/HIDDEN の場合、MySwingy ワーカーを停止したいと考えています。

以下は私が現在持っているコードであり、上記の問題に取り組むためのより良い/よりクリーンな方法があるかどうか疑問に思っています. 次のコード例では、Card1JPanel の ComponentListener を使用して表示または非表示を検出していますが、それぞれ独自の ComponentListener イベントを持つ非常に多くの Card がある場合、これらのイベント リスナーによってアプリケーションの速度が低下しますか?

どうもありがとうございました

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();
        }
    }
}

EDIT:mySwingyが何をするかを示します:

MySwingy は、SQL データベースからのデータを解析し、データベース内のデータが変更されたときに tableDatabase を更新するために使用されます。tableDatabase は Card1JPanel にあり、SwingUtilities.InvokeLater を使用して MySwingy から EDT で更新されます。私のアプリケーションには、EDT で JTables を更新する JTables と SwingWorker を含む多くのカード (JPanels) があります。ここで、これらの JTable のすべてが SwingWorker から 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 が1 回だけ実行されるように設計されていることに注目しています。doInBackground()別のスレッドからループを制御しようとすると、同期が困難になります。こちら で説明されている、タスクの予想される待機時間も調べてください。およびメソッドjavax.swing.Timerを公開する のインスタンスは、代わりになる場合があります。start()stop()

  • 更新された質問: ワーカーが可変レイテンシーを持つデータ ソースをポーリングする必要がある場合java.util.Timerは、バックグラウンド スレッドで を使用して、トリガー クエリを持続可能なペースで実行します。

于 2012-09-08T01:46:07.823 に答える