[英]How do I set a JTextPane out of another Thread?
我現在正在學習多線程。
我有一個“主”類,我在其中構建了一個帶有文本字段、開始和停止按鈕的 JFrame。
我還有另一個類/線程,當我單擊框架的開始按鈕時,我想從中將當前時間打印到我的文本字段中。 一切正常,但當我啟動線程時,文本字段中的文本不會改變,即使 Eclipse 說我的代碼沒問題。
我究竟做錯了什么?
第一類:
public class Uhr extends JFrame {
private JPanel contentPane;
public JTextPane tpZeit;
Thread t;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Uhr frame = new Uhr();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Uhr() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
tpZeit = new JTextPane();
tpZeit.setText("test");
tpZeit.setBounds(43, 50, 212, 43);
contentPane.add(tpZeit);
JButton btnstart = new JButton("GO");
btnstart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tpZeit.setText("started");
if (t == null) {
t = new Thread(new Uhrsteuerung());
}
if(!t.isAlive()) {
t = new Thread(new Uhrsteuerung());
t.start();
}
}
});
btnstart.setBounds(10, 227, 89, 23);
contentPane.add(btnstart);
JButton btnstop = new JButton("Stop");
btnstop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
t.interrupt();
}
});
btnstop.setBounds(248, 227, 89, 23);
contentPane.add(btnstop);
}
}
帶有附加線程的類:
public class Uhrsteuerung extends Uhr implements Runnable {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String time;
boolean x ;
@Override
public synchronized void run() {
// TODO Auto-generated method stub
x = true;
while (x) {
try {
time = sdf.format(System.currentTimeMillis());
System.out.println(time);
tpZeit.setText(time);
repaint();
Thread.sleep(1000);
} catch (InterruptedException ex) {
x = false;
}
}
}
}
Java 的 Swing 類的所有代碼都必須在事件調度線程 (EDT) 上執行。 Swing 提供了一些特殊的類來幫助您做到這一點。
要在 EDT 之外執行代碼,請使用 SwingWorker 類。 SwingWorker 將在后台執行任務(不使用 EDT),然后返回在 EDT 上執行的正確同步的結果。 https://docs.oracle.com/en/java/javase/16/docs/api/java.desktop/javax/swing/SwingWorker.html
它的應用非常簡單。 定義您自己的擴展 SwingWorker 的類。
class PrimeNumbersTask extends SwingWorker<List<Integer>, Integer> {
// ...
如果需要更新一個組件,最好把組件傳入,方便以后參考。
class PrimeNumbersTask extends SwingWorker<List<Integer>, Integer> {
private JTextArea textArea;
public PrimeNumbersTask( JTextArea textArea ) {
this.textArea = textArea;
}
// ...
通過覆蓋方法doInBackground()
來完成您的工作。 不要觸及此方法中的 Swing 類。 如果您想提供漸進式結果而不是等待整個任務完成,請使用publish()
方法將較小的數據塊發送到 EDT。
@Override
public List<Integer> doInBackground() {
while (!done && ! isCancelled()) {
// do stuff
publish(number);
setProgress(100 * numbers.size() / numbersToFind);
}
}
return numbers;
}
最后覆蓋方法process()
以更新您的 Swing 類。
@Override
protected void process(List<Integer> chunks) {
for (int number : chunks) {
textArea.append(number + "\n");
}
}
在 EDT 中,您可以調用execute()
來啟動您的后台任務。
JTextArea textArea = new JTextArea();
// manipulate and set up GUI...
PrimeNumbersTask task = new PrimeNumbersTask(textArea);
task.execute();
如果您在 Google 上搜索 SwingWorker,還有更多文檔,這就是如何使用它的基礎知識。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.