簡體   English   中英

Java Swing-多線程和重繪

[英]Java Swing - MultiThread and Repaint

我通過在JComboBox中選擇應該從中讀取要繪制信息的項目來繪制4個JPanels中的圖表。 選擇將啟動一個線程,該線程每秒讀取一次Informations()和repaint()。 關於信息讀取,它工作正常,但是當我選擇一個已經開始的項目時,它不會重新繪制整個圖表,而是從當前信息開始,因此丟失了一部分圖表。

public class MainClass extends JFrame
{
       private ArrayList<Item> items;
       public MainClass()
       {
            items = new ArrayList();
       }

       private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) 
       { 
            if(!items.get((jComboBox1.getSelectedIndex())).isRunning())
            {
                items.get(jComboBox1.getSelectedIndex()).start();
            }

            for(int i=0; i<forni.size(); i++)
            {
               if(forni.get(i).isRunning() && 
               forni.get(i) != forni.get(jComboBox1.getSelectedIndex()))
               {
                  jPanel1.remove(items.get(i).getChart1());
                  jPanel2.remove(items.get(i).getChart2());
                  jPanel3.remove(items.get(i).getChart3());
                  jPanel4.remove(items.get(i).getChart4());
               }
            }

             jPanel1.add(forni.get(jComboBox1.getSelectedIndex()).getChart1());
             jPanel2.add(forni.get(jComboBox1.getSelectedIndex()).getChart2());
             jPanel3.add(forni.get(jComboBox1.getSelectedIndex()).getChart3());
             jPanel4.add(forni.get(jComboBox1.getSelectedIndex()).getChart4());

             jPanel1.revalidate();
             jPanel2.revalidate();
             jPanel3.revalidate();
             jPanel4.revalidate();

        }  
 }

物品類別

 import java.util.Timer;
 public class Item
 {
     private Chart chart1;
     private Chart chart2;
     private Chart chart3;
     private Chart chart4;

     private Timer timer;

     private boolean running = false;

     public Item()
     {
         timer = new Timer();
         chart1 = new Chart();
         //...
     }

     public void start()
     {
        running = true;
        timer.scheduleAtFixedRate(new TimerTask() 
        {
           @Override
           public void run() 
           {
                read();
                repaint();
           }
         }, 1000,1000);
     }

      private void read()
      {
         chart1.read();
         //....
      }
      private void repaint()
      {
         chart1.repaint();
         //...
      }

      public Boolean isRunning()
      {
          return running; 
      }


// And the getting methods that return a JComponent

}

Chart類擴展了JComponent,他的paintComponent()方法只是重繪了更新的整個點數組。

要從線程刷新UI,請使用javadoc中的SwingUtilities.invokeAndWait()

 Causes <code>doRun.run()</code> to be executed synchronously on the
 AWT event dispatching thread.  This call blocks until
 all pending AWT events have been processed and (then)
 <code>doRun.run()</code> returns. This method should
 be used when an application thread needs to update the GUI

或來自Javadoc的SwingUtilities.invokeLater()

Causes <i>doRun.run()</i> to be executed asynchronously on the
AWT event dispatching thread.  This will happen after all
pending AWT events have been processed.  This method should
be used when an application thread needs to update the GUI.

您還寫了您使用java.util.Timer 看一下javax.swing.Timer ,在EDT中調用了ActionListener ,可以安全地進行GUI更改和繪畫。

但是請記住,您不應在EDT中進行冗長的工作,因為這會使GUI無法響應。 如果是這種情況,請簽出SwingWorker以在冗長的作業和短代碼之間取得平衡,以更新UI。

如果您想堅持使用自己的單獨線程,則SwingUtilities.invokeLater()SwingUtilities.invokeAndWait()是您的朋友。

如果您想進一步了解它,請閱讀Oracle官方教程: Swing中的並發性

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM