簡體   English   中英

Java-將信號從線程發送到Swing組件

[英]Java - send signal from Thread to Swing component

我想問一下,如果我可以運行Thread,並且是否發生了某些事件,則發送信號,並且某些swing組件將捕獲信號。 像這樣:

public class MyThread extends Thread {
  String today = "???";

  @Override
  public void run() {
    if (today.equals("monday")) {
        // send signal
    }
  }
}

public class MyPanel extends JPanel {
  // catching signals and if signal is catched change background color
}

編輯:我嘗試了此,但它不起作用。

public class MyThread extends Thread {
@Override
public void run() {
    SwingWorker worker = new SwingWorker<String, String>() {
        @Override
        protected String doInBackground() throws Exception {
            System.out.println("doInBackground");
            publish("doInBackgroundPublish");
            firePropertyChange("firePropertyChange1", "oldValue1", "newValue1");
            return "doInBackground return";
        }
        @Override
        protected void process(List<String> chunks) {
            super.process(chunks);
            firePropertyChange("firePropertyChange2", "oldValue2", "newValue2");
        }
    };
    worker.execute();
}

}

public class MyPanel extends JPanel {
public class SWListen implements PropertyChangeListener, Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("SWListen update");
    }
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println("SWListen propertyChange");
    }
}
public MyPanel {
    addPropertyChangeListener(new SWListen());
}

}

SwingWorker是一個自包含的“線程”(出於參數考慮),這意味着它將創建並啟動它自己的Thread從該doInBackground將調用doInBackground

然后, doInBackground應該“做某事”並使用中間值調用publish (假設您想在最后生成一個總值,否則,它只會生成一個值)

在未來的某個時刻process被調用。 在EDT的上下文中調用此方法,從而可以安全地從內部更新UI。

然后,您可以通過多種方式“將”更改“通知”用戶界面,大多數方法都屬於“觀察者模式”類別。

例如...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            JLabel label = new JLabel("...");
            add(label);

            TickerWorker worker = new TickerWorker();
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    System.out.println(evt.getPropertyName());
                    if ("counter".equals(evt.getPropertyName())) {
                        long value = (long) evt.getNewValue();
                        label.setText(Long.toString(value));
                    }
                }
            });
            worker.execute();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class TickerWorker extends SwingWorker<Void, Long> {

        @Override
        protected Void doInBackground() throws Exception {
            long counter = 0;
            while (true) {
                Thread.sleep(1000);
                publish(++counter);
            }
        }

        @Override
        protected void process(List<Long> chunks) {
            // Since we're in the EDT, it's probably pointless do announce ALL the
            // values, we're probably only interested in the last one
            for (long value : chunks) {
                firePropertyChange("counter", value - 1, value);
            }
        }
    }

}

現在,這將通知單個組件,如果您需要通知多個組件,則難度將增加一個數量級。

您可以讓每個組件創建自己的SwingWorker ,該SwingWorker監視一些全局監視器鎖定,從而允許“主要”工作人員觸發notifyAll ,然后將允許“組件工作人員”發布一些結果...但是如何獲得值!?

在這一點上,我可能只會考慮使用某種事件總線

暫無
暫無

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

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