-2

私のアプリケーションは、シリアル ポートの読み取りと書き込みを行うことになっています。データは、PortReader クラスの EventListener で読み取られます。今後使用するために、このデータをグローバル String 変数 (プライベート String sPortReaderString) に割り当てたいと考えています。グローバル文字列変数は、単に文字列 sPortReaderString を返す getPortReader() と呼ばれるメソッドを使用して、その値を返す必要があります。アプリケーションの JFrame で、シリアル ポート接続を開き、シリアル デバイスから自動的に応答を受信するコマンドを送信し、その応答出力をラベルに表示します。問題は、getPortReader() から返された sPortReaderString に何も割り当てられていないため、ラベルが常に空白になることです。sPortReaderString には、EvenListener で値が割り当てられると確信しています。問題は、値が sPortReaderString に割り当てられるのに十分な時間が経過する前に、JFrame のメソッド getPortReader() が呼び出されることです。私のotuputと以下のコードを見てください:

以下は私が得る出力です:

sPortReaderString:
PortReader

JFrame の portsMethod の短い例:

public class MyJFrame extends javax.swing.JFrame {

    public MySerialPort msp = new MySerialPort();   

    public MainJFrame() {
        portsMethod();
    }

    private void portsMethod() {

        msp.getPortNames();//Gets the name of the port (COM1 in my case)
        msp.openPort();//Opens COM1 port
        msp.getFirmwareVersion();//Prompts for device firmware version by sending a string command
        msp.getPortReader();//Reads the reply from device

    }

}

以下は、私のシリアル ポート クラスの例です。

public class MySerialPort {

    private SerialPort serialPort;
    private int iBaudRate = SerialPort.BAUDRATE_57600;
    private int iDataBits = SerialPort.DATABITS_8;
    private int iStopBits = SerialPort.STOPBITS_1;
    private int iParity = SerialPort.PARITY_NONE;
    private String sPortName;
    private String sPortReaderString = "";
    private StringBuilder sbPortReaderString = new StringBuilder();

    public void getFirmwareVersion() {
        sendPortCommand("<FirmVer>\r\n");
    }

    public void clearPortReader() {
        sbPortReaderString.setLength(0);
    }

    public String getPortReader() {
        System.out.print("sPortReaderString: " + sPortReaderString);
        return sPortReaderString;
    }

    public void getPortNames() {
        String[] sPorts = SerialPortList.getPortNames();
        sPortName = sPorts[0];
    }

    public void openPort() {

        serialPort = new SerialPort(sPortName);

        try {

            if (serialPort.openPort()) {

                if (serialPort.setParams(iBaudRate, iDataBits, iStopBits, iParity)) {

                    serialPort.addEventListener(new PortReader(), SerialPort.MASK_RXCHAR
                            | SerialPort.MASK_RXFLAG
                            | SerialPort.MASK_CTS
                            | SerialPort.MASK_DSR
                            | SerialPort.MASK_RLSD);

                } else {
                    serialPort.closePort();
                }

            } else {}
        } catch (SerialPortException | HeadlessException ex) {}
    }

    private void sendPortCommand(String sSendPortCommand) {

        if (sSendPortCommand.length() > 0) {
            try {
                serialPort.writeBytes(sSendPortCommand.getBytes());
            } catch (Exception ex) {}
        }
    }

    private class PortReader implements SerialPortEventListener {

        private String sBuffer = "";

        @Override
        public void serialEvent(SerialPortEvent spe) {

            if (spe.isRXCHAR() || spe.isRXFLAG()) {

                if (spe.getEventValue() > 0) {

                    try {

                        //Read chars from buffer
                        byte[] bBuffer = serialPort.readBytes(spe.getEventValue());
                        sBuffer = new String(bBuffer);

                        SwingUtilities.invokeAndWait(
                                new Runnable() {

                                    @Override
                                    public void run() {
                                        sbPortReaderString.append(sBuffer);
                                    }
                                });

                        sPortReaderString = new String(sbPortReaderString);
               //if I print sPortReaderString in here it is not blank and has the correct value

                        System.out.print("PortReader");

                    } catch (SerialPortException | InterruptedException | InvocationTargetException ex) {
                    }
                }
            }
        }
    }
}
4

1 に答える 1

2

私にはかなり論理的に思えます:

ファームウェア バージョンを取得してからポート リーダーを取得する EDT で、最初のイベント処理メソッドを実行します。ファームウェア バージョンを取得すると、別のスレッドでportsMethod()(したがって、EDT での実行と並行して) イベントが受信されます。

イベント処理コードは を呼び出しますSwingUtilities.invokeAndWait()。したがって、この呼び出しは、最初のイベント処理メソッドが完了するのを待ってから、受信した文字列を に追加しsbPortReaderStringます。したがって、この追加はportsMethodが完了した後に行われます。

シリアル ポートは、イベント ベースのメカニズムを提供します。これを使用して、EDT 内の 1 つまたは複数のリスナーにイベントを伝播します。

// accessed only from the EDT
private List<MyPortListener> portListeners = new ArrayList<MyPortListener>();

public void addMyPortListener(MyPortListener listener) {
    portListeners.add(listener);
}

public void removeMyPortListener(MyPortListener listener) {
    portListeners.remove(listener);
}

... 

    @Override
    public void serialEvent(SerialPortEvent spe) {
        ...
        final String receivedString = ...;
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                for (MyPortListener listener : portListeners) {
                    listener.stringReveivedFromSerialPort(receivedString);
                }
            }
        });
    }

補足:主に変数とメソッドの名前が不適切であるため、コードを理解するのは困難です。

于 2012-02-29T20:29:50.890 に答える