2017-05-15 5 views
1
  1. Swing JComponentとのすべてのやりとりは、イベントディスパッチスレッドで行う必要があります。ペインティングも。
  2. 長いタスクはEvent Dispatch Threadの外側で実行する必要があります。そうでない場合、GUIをブロックします。

しかし、長いタスクがGraphics2Dのアプリケーションを1000回ペイントしている場合はどうなりますか?この相反する要件はありますか? JComponentを長いタスクとして描画する

public class MyObject extends JPanel { 
    ... 
    public void paintComponent(Graphics g) {...} 
    ... 
} 

私はそれは長いタスクとして考えることができることを、そんなに回、このメソッドを呼び出す必要がある場合

、私は、GUIをブロックを回避するために、何をすべき?私が理解する限り、それはSwingWorkerで委譲するだけでは許されません。そのような「長い作業」の回避策はありますか?

+1

あなたはなぜそれは多くの時間がかかるのですか?それはデータベースにアクセスしますか?それは長期実行トランザクションを呼び出すか? 別の質問:なぜ1000回実行するのですか? 1000ペイントでどれくらい時間がありますか? –

+1

paintComponentメソッドの外側にあるすべての数値と図形を計算します。paintComponentメソッドが行う必要があるのは、ペイントだけです。 1000個のオブジェクトを描画するだけでは、特に現代のビデオカードを搭載したマシンでは、パフォーマンスに影響を与える可能性は低いです。 – VGR

+0

@Tamas Revはい、実際には私のアプリケーションを10.000回以上塗りつぶしてpdfsを生成します(pdf-g2でpaintComponentを呼び出します)。そして、私はそれを実行中に進行状況バーを表示したい。 – AvrDragon

答えて

1

私はこれが例外だと思います。スクリーンにペイントしていない限り、バックグラウンドスレッドで呼び出すことができます。重要なのは、イベントディスパッチスレッド上で実際のUIが実行されるため、すべての変更がユーザーに表示されるということです。スイングオブジェクトは、この印刷中に変更しないでください。

public class MyObject extends JPanel { 

    private static final int NUMBER_OF_PDFS = 10_000; 

    private JProgressBar progressBar = new JProgressBar(0, NUMBER_OF_PDFS); 

    public void paintPdfs() { 
     ExecutorService threadPool = Executors.newFixedThreadPool(5); // this can come somewhere else too 
     for (int i = 0; i < NUMBER_OF_PDFS; i++) { 
      final int newProgressBarValue = i; // you might need some mapping, depends on the setup of the taskbar 
      threadPool.execute(() -> { 
       try { 
        Graphics pdfG2 = getPdfGraphics(); 
        MyObject.this.paintComponent(pdfG2); 
       } finally { 
        SwingUtilities.invokeLater(() -> { 
         int progressBarValue = progressBar.getValue(); 
         if (progressBarValue < newProgressBarValue) { 
          progressBar.setValue(newProgressBarValue); 
         } 
        }); 
       } 
      }); 
     } 
    } 

    private Graphics getPdfGraphics() { 
     // I don't know how to do this. On the other hand, you do :) 
     return null; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     // ... 
    } 
} 

を私は一つだけ注意点を確認することができます。

これは、これが起こるべきかのスケルトンです。もしそうなら、別のトリックが必要です。この他のトリックは、イベントディスパッチスレッド1対1でPDFファイルを印刷することになります。

public void paintPdfs() { 
    for (int i = 0; i < NUMBER_OF_PDFS; i++) { 
     final int newProgressBarValue = i; // you might need some mapping, depends on the setup of the taskbar 
     SwingUtilities.invokeLater(() -> { 
      try { 
       Graphics pdfG2 = getPdfGraphics(); 
       MyObject.this.paintComponent(pdfG2); 
      } finally { 
       int progressBarValue = progressBar.getValue(); 
       if (progressBarValue < newProgressBarValue) { 
        progressBar.setValue(newProgressBarValue); 
       } 
      } 
     }); 
    } 
} 

この第二のアプローチは、一度に1つのpaintComponent()を実行し、それはあなたのUIがフリーズしません。このため、エグゼキュータまたはワーカースレッドは必要ありません。それはそれが追加することを確認するだけです

+1

最初の 'paintComponent'は決して' public'であってはいけません。理由のために 'protected'です。直接呼び出す必要はありません。代わりに、この種のために設計された' print'または 'printAll'を使うべきです操作のダブルバッファリングを無効にする – MadProgrammer

関連する問題