我投降。现在尝试了几个星期,以找出阻止接收到的串行数据被我的代码的图形部分更新的原因。第一次用Java编程。拥有大约 15 年的微型编程经验,我习惯于解决我自己的问题,但这超出了该策略有效的范围。我的应用程序包含两个文件。
一个文件来自 RXTX 项目,每秒捕获两次以多个数据包发送的串行数据。这就像一个魅力(花了一些时间),我可以看到捕获的数据是正确且稳定的。
另一个文件是图形文件,包含大约 80 个菜单,最终用户可以在其中读取和有时写入值。到目前为止,导航是通过按钮和滚动条上的鼠标事件完成的。这部分也可以正常工作。可以读取、更改和保存值等。
我被卡住的部分是串行文件中的更新值永远不会更新图形屏幕。尝试了数百个示例和教程(许多来自此站点),但没有成功。
对象相关语言的概念对我来说是新的并且仍然很混乱。很确定我的问题涉及继承和类。线程是另一个候选者...已将代码缩减到仍然可以运行并提出我的问题的最小大小,并希望有人能看到什么是错的。
package components;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.swing.SwingUtilities;
public class SerialComm extends ScreenBuilder implements java.util.EventListener {
InputStream in;
public SerialComm() {
    super();
}
public interface SerialPortEventListener
        extends java.util.EventListener {
}
void connect(String portName) throws Exception {
    CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier("COM1");
    if (portIdentifier.isCurrentlyOwned()) {
        System.out.println("Error: Port is currently in use");
    } else {
        CommPortIdentifier.getPortIdentifier("COM1");
        System.out.println("" + portName);
        CommPort commPort = portIdentifier.open("COM1", 2000);
        if (commPort instanceof SerialPort) {
            SerialPort serialPort = (SerialPort) commPort;
            serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_2, SerialPort.PARITY_NONE);
            InputStream in = serialPort.getInputStream();
            OutputStream out = serialPort.getOutputStream();
            serialPort.addEventListener(new SerialComm.SerialReader(in));
            serialPort.notifyOnDataAvailable(true);
            (new Thread(new SerialComm.SerialReader(in))).start();
            // TX functionality commented for now
            //               (new Thread(new SerialWriter(out))).start();
        } else {
            System.out.println("Error: Only serial ports are handled by this     example.");
        }
    }
}
public class SerialReader extends SerialComm implements Runnable,
        gnu.io.SerialPortEventListener {
    public SerialReader(InputStream in) {
        this.in = in;
    }
    @Override
    public void run() {
    count=11; // just for test. run is normally empty
    count2=count; // and real code runs within serialEvent()
    System.out.println("SerialReader " + count);
    dspUpdate(); // do some desperate stuff in graphics file
    System.out.println("Post Update " + count);
    }
    @Override
    public void serialEvent(SerialPortEvent event) {
    System.out.println("SerialEvent");
        switch (event.getEventType()) {
            case SerialPortEvent.DATA_AVAILABLE:
                try {
                    synchronized (in) {
                        while (in.available() < 0) {
                            in.wait(1, 800000);
                        } //in real code RX data is captured here twice a sec
                    } //and stored into buffers defined in ScreenBuilder
    //dspUpdate() is called from here to make ScreenBuilder update its screen
    //That never happens despite all my attempts               
                } catch (IOException e) {
                    System.out.println("IO Exception");
                } catch (InterruptedException e) {
                    System.out.println("InterruptedException caught");
                }
        }
    }
}
/* "main" connect PC serial port and start graphic part of application
 * To demonstrate problem with no serial data stream present
 * order of init between serial port and graphics are switched
 */
public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            ScreenBuilder screen = new ScreenBuilder();
            screen.createAndShowGUI();
            System.out.println("Created GUI");
        }
    });
    try {
        (new SerialComm()).connect("COM1");
    } catch (Exception e) {
        System.out.println("Error");
        e.printStackTrace();
    }
  }
}
和图形文件
package components;
import java.awt.*;
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.*;
public class ScreenBuilder extends JPanel implements ActionListener {
public Font smallFont = new Font("Dialog", Font.PLAIN, 12);
Color screenColor;
Color lineColor;
short btn=0;
short count;
short count2;
Button helpButton;
public static void createAndShowGUI() {
    System.out.println("Created GUI on EDT? "
            + SwingUtilities.isEventDispatchThread());
    JFrame f = new JFrame("JUST A TEST");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.add(new ScreenBuilder());
    f.pack();
    f.setVisible(true);
}
public void dspButton() {
    setLayout(null);// 
    helpButton = new Button("?");
    helpButton.setLocation(217, 8); // set X, Y
    helpButton.setSize(16, 14); //Set Size X, Y //
    helpButton.addActionListener(this);
    add(helpButton);
    setBackground(Color.black);
    helpButton.setBackground(Color.black);
    screenColor = Color.black;
    helpButton.setForeground(Color.white);
    lineColor = Color.white;
}
@Override
public void actionPerformed(ActionEvent e) {
    if (e.getSource() == helpButton) {
        count2++;
        System.out.println("Pressed Button ");
        repaint();
    }
}
public ScreenBuilder() {
    setBorder(BorderFactory.createLineBorder(Color.black));
}
@Override
public Dimension getPreferredSize() {
    return new Dimension(240, 180);
}
public void dspUpdate() {
    /*
     * This function is called from SerialComm
     * Should be called when serial packets have arrived (twice a second)
     * and update screen with values from serial stream
     * For now just a test var to validate that values from SerialComm
     * get to here (they do)
     */
count++;
System.out.println("Update Count " + count);
System.out.println("Update Count2 " + count2);
//    revalidate(); // another futile attempt to update screen
//    repaint();
}
@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(lineColor);
    g.setFont(smallFont);
    count++;
    g.drawString("" + count, 130, 20);
    g.drawString("" + count2, 150, 20);
    if (btn == 0) {
      dspButton();
      btn = 1;
    }
  }
}