Java Swing線程

2018-01-09 19:23 更新

Java Swing教程 - Java Swing線程


Swing的線程安全規(guī)則規(guī)定,一旦實現(xiàn)了Swing組件,就必須在事件分派線程上修改或訪問該組件的狀態(tài)。

如果組件已經(jīng)被涂漆或者準(zhǔn)備涂漆,則認(rèn)為該組件被實現(xiàn)。

Swing中的頂級容器是在我們調(diào)用它的pack()時實現(xiàn)的,第一次使用setVisible(true)或show()方法。

當(dāng)實現(xiàn)頂層容器時,它的所有子代也被實現(xiàn)。

事件分派線程是JVM在檢測到它正在使用Swing應(yīng)用程序時由JVM自動創(chuàng)建的線程。JVM使用此線程來執(zhí)行Swing組件的事件處理程序。

例如,當(dāng)我們單擊JButton時,actionPerformed()方法中的代碼由事件分派線程執(zhí)行。

以下兩個類是Swing應(yīng)用程序中用于處理其線程模型的輔助類。 類是

  • SwingUtilities
  • SwingWorker

要知道代碼是否在事件分派線程中執(zhí)行,使用SwingUtilities類的靜態(tài)方法isEventDispatchThread()。

如果代碼在事件分派線程中執(zhí)行,則返回true。 否則,它返回false。

System.out.println(SwingUtilities.isEventDispatchThread());

使用Swing操作處理程序代碼時,應(yīng)遵循以下列出的規(guī)則。

  • add all event handlers to a component at the end of the GUI-building code.
  • run all GUI code on the event dispatch thread by using the invokeLater(Runnable r) method from the SwingUtilities class.

以下代碼顯示了啟動Swing應(yīng)用程序的正確方法。

SwingUtilities.invokeLater(() ->  {
    MySwingApp  app = new MySwingApp("A Swing App");
    app.pack();
    app.setVisible(true);
});

如果事件分派線程尚未啟動,SwingUtilities.invokeLater(Runnable r)方法將啟動它。

SwingUtilities.invokeLater()方法調(diào)用立即返回,并且Runnable參數(shù)的run()方法是異步執(zhí)行的。

在SwingUtilities類中有另一個重要的靜態(tài)方法invokeAndWait(Runnable r)。

此方法是同步執(zhí)行的,它不會返回,直到run()方法在事件分派線程上完成執(zhí)行。 此方法可能會拋出InterruptedException或InvocationTargetException。

不應(yīng)該從事件調(diào)度中調(diào)用SwingUtilities.invokeAndWait(Runnable r)方法線程,因為它會阻塞事件分派線程。

我們可以使用SwingUtilities類的invokeAndWait()方法來啟動Swing應(yīng)用程序,而不是invokeLater()方法。

try  {
    SwingUtilities.invokeAndWait(() ->  { 
       JFrame  frame  = new JFrame(); 
       frame.pack(); 
       frame.setVisible(true);
    });
    System.out.println("Swing application  is running...");
}catch (Exception e)  {
    e.printStackTrace();
}


Java Swing教程 - Java Swing線程...

要在Swing應(yīng)用程序中執(zhí)行耗時的任務(wù),在除了事件分派線程之外的單獨線程中執(zhí)行長任務(wù)。

Swing提供了一個SwingWorker類,這使得在Swing應(yīng)用程序中很容易使用多個線程。

SwingWorker< T,V> 類被聲明為abstract。 類型參數(shù)T是結(jié)果類型,類型參數(shù)V是中間結(jié)果類型。

SwingWorker< T,V> 類被聲明為abstract。 類型參數(shù)T是結(jié)果類型,類型參數(shù)V是中間結(jié)果類型。...

  • doInBackground(): perform a time-consuming task. It is executed in a separate worker thread.
  • process(): called as a result of a publish() method call. This method executes on the event dispatch thread, and we can access Swing component in this method.
  • The publish() method accepts a varargs argument. The process() method passes all arguments to the publish() method packed in a List.
  • done(): When the doInBackground() method finishes, normally or abnormally, the done() method is called on the event dispatch thread. we can access Swing components in this method.
  • execute(): call this method to start executing the task in a separate thread.
  • get(): This method returns the result of the task as returned from the doInBackground() method. It is not suggested to call this method on the event dispatch thread, as it will block all events until it returns.
  • cancel(boolean mayInterruptIfRunning): This method cancels the task if it is still running.
  • isCancelled(): returns true if the process has been cancelled. Otherwise, it returns false.
  • isDone(): It returns true if the task has completed. A task may complete normally or by throwing an exception or by cancellation. Otherwise, it returns false.
import java.awt.BorderLayout;
import java.awt.Container;
import java.util.List;
//from   ww w  .  ja  v  a2s  .co m
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

class SwingWorkerProcessor extends SwingWorker<Integer, Integer> {
  private final SwingWorkerFrame frame;
  private int iteration;
  private int intervalInMillis;

  public SwingWorkerProcessor(SwingWorkerFrame frame, int iteration,
      int intervalInMillis) {
    this.frame = frame;
    this.iteration = iteration;

    if (this.iteration <= 0) {
      this.iteration = 10;
    }
    this.intervalInMillis = intervalInMillis;
    if (this.intervalInMillis <= 0) {
      this.intervalInMillis = 1000;
    }
  }

  @Override
  protected Integer doInBackground() throws Exception {
    int sum = 0;
    for (int counter = 1; counter <= iteration; counter++) {
      sum = sum + counter;
      this.publish(counter);
      if (Thread.interrupted()) {
        throw new InterruptedException();
      }
      if (this.isCancelled()) {
        break;
      }
      Thread.sleep(intervalInMillis);
    }

    return sum;
  }

  @Override
  protected void process(List<Integer> data) {
    for (int counter : data) {
      frame.updateStatus(counter, iteration);
    }
  }
  @Override
  public void done() {
    try {
      frame.doneProcessing();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
class SwingWorkerFrame extends JFrame {
  String startMessage = "Please click the   start button...";
  JLabel statusLabel = new JLabel(startMessage);
  JButton startButton = new JButton("Start");
  JButton cancelButton = new JButton("Cancel");
  SwingWorkerProcessor processor;

  public SwingWorkerFrame() {
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container contentPane = this.getContentPane();
    cancelButton.setEnabled(false);

    contentPane.add(statusLabel, BorderLayout.NORTH);
    contentPane.add(startButton, BorderLayout.WEST);
    contentPane.add(cancelButton, BorderLayout.EAST);

    startButton.addActionListener(e -> startProcessing());
    cancelButton.addActionListener(e -> cancelProcessing());
  }
  public void setButtonStatus(boolean canStart) {
    if (canStart) {
      startButton.setEnabled(true);
      cancelButton.setEnabled(false);
    } else {
      startButton.setEnabled(false);
      cancelButton.setEnabled(true);
    }
  }
  public void startProcessing() {
    setButtonStatus(false);
    processor = new SwingWorkerProcessor(this, 10, 1000);
    processor.execute();
  }
  public void cancelProcessing() {
    processor.cancel(true);
    setButtonStatus(true);
  }
  public void updateStatus(int counter, int total) {
    String msg = "Processing " + counter + "  of  " + total;
    statusLabel.setText(msg);
  }
  public void doneProcessing()throws Exception {
    if (processor.isCancelled()) {
      statusLabel.setText("Process  cancelled ...");
    } else {
      int sum = processor.get();
      statusLabel.setText("Sum  is " + sum);
      setButtonStatus(true);
    }
  }
}
public class Main{
  public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
      SwingWorkerFrame frame = new SwingWorkerFrame();
      frame.pack();
      frame.setVisible(true);
    });
  }
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號