【问题标题】:JTextField not updating from Serial PortJTextField 未从串行端口更新
【发布时间】:2017-11-30 16:12:51
【问题描述】:

我正在尝试编写软件来从三个 RS232 串行端口读取数据,并且我已经编写了一些代码来提供有关程序实际正在侦听的端口的视觉反馈。我知道程序正在侦听 COM1,因为我已经将它打印到控制台以告诉我它正在侦听哪个端口。问题是它没有更新 JTextFields 以在实际的 GUI 中通知用户。我写的代码如下:

if (Serial.currPortId == (null)) {
    listenState.setText("NONE");
    listenState.revalidate();
}
while (Serial.currPortId != (null)) {
    listenState.setText(Serial.currPortId.getName());
    listenState.revalidate();
    if (Serial.currPortId.getName().equals("COM1")) {
        tab1sheet.setText(ImportMenu.serialImport.datafeed);
        tab1sheet.revalidate();
    }
    else if (Serial.currPortId.getName().equals("COM2")) {
        tab2sheet.setText(ImportMenu.serialImport.datafeed);
        tab2sheet.revalidate();
    }
    else if (Serial.currPortId.getName().equals("COM3")) {
        tab3sheet.setText(ImportMenu.serialImport.datafeed);
        tab3sheet.revalidate();
    }
    else {tab1sheet.setText("N/A");
          tab1sheet.revalidate();
          tab2sheet.setText("N/A");
          tab2sheet.revalidate();
          tab3sheet.setText("N/A");
          tab3sheet.revalidate();
    }
}

由于某种原因,它只是将“listenState”字段设置为 NONE,然后不更新,尽管声称在控制台中监听 COM1。

【问题讨论】:

    标签: java swing serial-port


    【解决方案1】:

    您的代码违反了 Swing 线程规则。它可能正在尝试在 Swing 事件线程上运行监听代码(我们无法根据您发布的 sn-p 判断),但它肯定会尝试以错误的方式更新文本字段。相反,我建议您使用 SwingWorker 在后台线程中侦听端口,特别是使用发布/处理方法对的 SwingWorker<Void, String> 将文本发送到 JTextArea。或者,如果您需要在 GUI 的多个位置使用更复杂的信息更新 GUI,则可以通过将 PropertyChangeListener 附加到 SwingWorker 来执行此操作,这将通知任何侦听器(GUI)有关工作人员状态的更改。

    更多信息,请查看Lesson: Concurrency in Swing

    您的代码可能看起来像这样

    class MyWorker extends SwingWorker<Void, Void> {
        // properties to listen for changes to:
        public static final String LISTEN_STATE = "listen state";
        public static final String CURRENT_PORT_ID = "current port id";
        public static final String DATA_FEED = "data feed";
        private String listenState = "None";
        private String dataFeed = "";
        private String currentPortId = "";
    
        @Override
        protected Void doInBackground() throws Exception {
            while (true) {
                if (Serial.currPortId != (null)) {
                    // change properties when data comes in
                    String currPortId = Serial.currPortId.getName();
                    setListenState(currPortId);
                    setCurrentPortId(currPortId);
                    setDataFeed(ImportMenu.serialImport.datafeed);
                } else {
                    setListenState("None");
                    break; // ??
                }
            }
            return null;
        }
    
        public String getListenState() {
            return listenState;
        }
    
        public void setListenState(String listenState) {
            // set the prop change parameters
            String oldValue = this.listenState;
            String newValue = listenState;
    
            // update the propertie's state
            this.listenState = listenState;
    
            // notify listeners of the change
            firePropertyChange(LISTEN_STATE, oldValue, newValue);
        }
    
        public String getDataFeed() {
            return dataFeed;
        }
    
        public void setDataFeed(String dataFeed) {
            // same rationale as for the other setter method
            String oldValue = this.dataFeed;
            String newValue = dataFeed;
            this.dataFeed = dataFeed;
            firePropertyChange(DATA_FEED, oldValue, newValue);
        }
    
        public String getCurrentPortId() {
            return currentPortId;
        }
    
        public void setCurrentPortId(String currentPortId) {
            // same rationale as for the other setter method
            String oldValue = this.currentPortId;
            String newValue = currentPortId;
            this.currentPortId = currentPortId;
            firePropertyChange(CURRENT_PORT_ID, oldValue, newValue);
        }
    }
    

    然后您可以附加一个响应更改的侦听器,然后更新 GUI 中的显示

    private class MyWorkerListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            switch (evt.getPropertyName()) {
            case MyWorker.LISTEN_STATE:
                String listenState = evt.getNewValue().toString();
                // show in text field
                break;
            case MyWorker.CURRENT_PORT_ID:
                String currentPortId = evt.getNewValue().toString();
                // use this to decide which tab to change to
                break;
            case MyWorker.DATA_FEED:
                String dataFeed = evt.getNewValue().toString();
                // show where needed
                break;
    
            default:
                break;
            }
        }
    }
    

    你会在 gui 中像这样连接它:

    MyWorker worker = new MyWorker();
    worker.addPropertyChangeListener(new MyWorkerListener());
    worker.execute();
    

    您还想向 SwingWorker 添加另一个 PropertyChangeListener 以侦听 SwingWorker.StateValue.DONE newValue,当它发生时,在 worker 上调用 get() 以捕获和处理任何异常

    【讨论】:

    • 我会调查一下,谢谢!监听代码在不同的类中运行,这里通过“Serial”调用。这只是让它更新的一个例子。我对串口没有太多经验,所以都是学习。
    • @JosephOliver:但是您是在后台线程中运行监听代码吗?如果没有,我希望代码完全冻结您的 GUI,使其完全无响应。
    • @JosephOliver:请参阅答案中的编辑以获取不完整的示例。
    猜你喜欢
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 2014-12-04
    • 2013-03-29
    • 2018-12-15
    相关资源
    最近更新 更多