在Java中等待打开com端口的按钮事件,而不是在控制台输入端口选择。

问题描述 投票:0回答:1

下面是我用来打开com端口的代码--它等待用户从控制台扫描器输入数字来打开端口,这个端口列在一个JComboBox中。我有一个带有按钮的事件监听器,我想用它来代替打开com端口。但我不确定是否有一个最好的做法来 "停止 "进一步的执行,直到用户按下按钮来打开端口。控制台扫描器目前很方便地允许程序等待选择)。我只是想让程序只在按下按钮后打开端口时才继续执行。一个jcombo框显示了端口,我可以使用getSelectedIndex()获得端口号。

package testPackage;

import java.awt.BorderLayout;
import java.awt.ItemSelectable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.PrintWriter;
import java.util.Scanner;
import com.fazecast.jSerialComm.*;
import javax.swing.*;


//To test - Select option 5, from select a port dialogue (Com0Com port 6)
//open terminal program - select port Com0Com 7 
//send numbers as Ascii
public class Main {
static SerialPort serialPort; 

    public static void main(String[] args) {

        Window1 window1 = new Window1();
        JComboBox<String> commList = new JComboBox<>();
        window1.add(commList);  
        JButton bigButton = new JButton("Select Comm port");
        window1.add(bigButton);

        window1.pack();
        window1.setVisible(true);
        JLabel label = new JLabel("My label");
        window1.add(label, BorderLayout.CENTER);

        SerialPort[] ports = SerialPort.getCommPorts();

        System.out.println("Select a port:");
        int i = 1;
        for(SerialPort port : ports) {
            System.out.println(i++ +  ": " + port.getSystemPortName());
            commList.addItem(port.getSystemPortName());
        }

        bigButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Clicked");
                label.setText("Selected");
                   System.out.println("Selected: " + commList.getSelectedItem());
                   System.out.println("Position: " + commList.getSelectedIndex());  
                  // SerialPort serialPort = ports[commList.getSelectedIndex()];
                   open_serial();
            }

            private void open_serial() {
                 serialPort = ports[commList.getSelectedIndex()];


            }

        });     

        Scanner s = new Scanner(System.in);
        int chosenPort = s.nextInt();
        SerialPort serialPort = ports[chosenPort - 1];
//      System.out.println("Chosen port : " + chosenPort);
//        System.out.println("Selected: " + commList.getSelectedItem());
//        System.out.println("Position: " + commList.getSelectedIndex());
        if(serialPort.openPort())
            System.out.println("Port opened successfully.");
        else {
            System.out.println("Unable to open the port.");
            s.close();
            return;
        }   
        serialPort.setBaudRate(9600);
        serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 0, 0);
        Scanner data = new Scanner(serialPort.getInputStream());
        int value = 0;
        //Thread thread = new Thread();
        PrintWriter output = new PrintWriter(serialPort.getOutputStream());

            output.print("Hiya"); 
            output.flush();
            System.out.println("printing1");



        while(data.hasNextLine()){
            System.out.println(value);
            try{value = Integer.parseInt(data.nextLine());}catch(Exception e){}
            output.print("Received"); 
            output.flush();
        }
        System.out.println("Done.");
        data.close();
        s.close();

    }

};

//-here is the window1 class
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;

public class Window1 extends JFrame{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    JButton BigButton;


public Window1() {
    super("Programmer");
    setLookAndFeel();
    this.setPreferredSize(new Dimension(400, 300));
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    FlowLayout flo = new FlowLayout();
    setLayout(flo);

    setVisible(true);  
}


private void setLookAndFeel() {
    try {
        UIManager.setLookAndFeel(
            "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
        );
    } catch (Exception exc) {
        // ignore error
    }
}


}  
java swing serial-port event-listener
1个回答
0
投票

但我不确定是否有一个最好的做法来 "停止 "进一步的执行,直到用户按下打开端口的按钮。

我可以想到两种主要的方法来 "暂停 "一个Swing GUI,同时等待用户输入。

  1. 如果程序应该完全停止, 那就把 port 的选择放到一个模型对话框中, 比如 JOptionPane 或更通用的模态 JDialog。这可以防止调用代码,即主 GUI,与用户进行交互,直到对话框不再可见(已被处理),或
  2. 使用状态设计模式类型的程序,在端口被选择之前,您只是不对用户的输入做出反应,例如在用户可能进行交互的地方设置if块,检查端口选择的状态,并且只处理用户的交互,直到端口选择有效。例如, 您可以使用一个变量。SerialPort selectedPort = null; 和其他监听器中的其他地方, 那些不涉及端口选择的监听器, 都在顶部。if (selectedPort == null) { return; }

如果您想了解更多的细节,那么可以考虑创建并发布一个有效的 最小的、可复制的例子 带着您的问题,我可以根据您的需求进行调整。请查看这个宝贵工具的链接。


这里是我的意思的一个例子。运行它来试试。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import javax.swing.*;

@SuppressWarnings("serial")
public class MyPortExample extends JPanel {
    private JTextArea fromPortArea = new JTextArea(20, 40);
    private Action sendAction = new SendAction("Send");
    private Action setUpPortAction = new SetUpPortAction("Set Up Port", this);
    private JTextField toPortField = new JTextField(35);
    private JTextField portNameField = new JTextField(15);
    private JButton sendTextBtn = new JButton(sendAction);
    private PrintStream outFromPort = null;
    private MockSerialPort serialPort = null;

    public MyPortExample() {
        portNameField.setFocusable(false);
        JPanel topPanel = new JPanel();
        topPanel.add(new JButton(setUpPortAction));
        topPanel.add(portNameField);

        JScrollPane scrollPane = new JScrollPane(fromPortArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        sendAction.setEnabled(false);
        toPortField.setAction(sendAction);
        fromPortArea.setFocusable(false);

        JPanel sendPanel = new JPanel();
        sendPanel.add(toPortField);
        sendPanel.add(sendTextBtn);

        setLayout(new BorderLayout());
        add(topPanel, BorderLayout.PAGE_START);
        add(scrollPane);
        add(sendPanel, BorderLayout.PAGE_END);
    }

    public void setSerialPort(MockSerialPort port) {
        this.serialPort = port;
        outFromPort = (PrintStream) port.getOutputStream();
        InputStream in = port.getInputStream();
        new PortWorker(in, fromPortArea).execute();
        portNameField.setText(port.getSystemPortName());
        sendAction.setEnabled(true);
    }

    public MockSerialPort getSerialPort() {
        return serialPort;
    }

    private class PortWorker extends SwingWorker<Void, String> {
        private Scanner portScanner;
        private JTextArea textArea;

        public PortWorker(InputStream in, JTextArea fromPortArea) {
            this.textArea = fromPortArea;
            portScanner = new Scanner(in);
        }

        @Override
        protected Void doInBackground() throws Exception {
            while (portScanner.hasNextLine()) {
                publish(portScanner.nextLine());
            }
            return null;
        }

        @Override
        protected void process(List<String> chunks) {
            for (String text : chunks) {
                textArea.append(text + "\n");
            }
        }
    }

    private class SendAction extends AbstractAction {
        public SendAction(String name) {
            super(name);
            putValue(MNEMONIC_KEY, KeyEvent.VK_S);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (outFromPort != null) {
                String text = toPortField.getText();
                outFromPort.println(text);
                toPortField.selectAll();
                toPortField.requestFocusInWindow();
            } else {
                System.err.println("No output stream available");
            }
        }

    }

    private static class SetUpPortAction extends AbstractAction {
        private MyPortExample myPortExample;

        public SetUpPortAction(String name, MyPortExample myPortExample) {
            super(name);
            putValue(MNEMONIC_KEY, KeyEvent.VK_P);
            this.myPortExample = myPortExample;
        }

        @Override
        public void actionPerformed(ActionEvent e) {

            int messageType = JOptionPane.PLAIN_MESSAGE;
            MockSerialPort port = (MockSerialPort) JOptionPane.showInputDialog(myPortExample, "Please select a port",
                    "Port Selection", messageType, null, MockSerialPort.getCommPorts(), null);
            if (port != null) {
                myPortExample.setSerialPort(port);
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        MyPortExample mainPanel = new MyPortExample();
        JFrame frame = new JFrame("MyPortExample");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private static class MockSerialPort {

        public static final String TIMEOUT_READ_SEMI_BLOCKING = "timeout read semi blocking";
        private String portName;
        private int baudRate;

        public MockSerialPort(String name) {
            this.portName = name;
        }

        public String getSystemPortName() {
            return portName;
        }

        public OutputStream getOutputStream() {
            return System.out;
        }

        public InputStream getInputStream() {
            return System.in;
        }

        public void setComPortTimeouts(String timeoutReadSemiBlocking, int i, int j) {
            // TODO ??? not sure what goes here
        }

        public void setBaudRate(int baudRate) {
            this.baudRate = baudRate;
        }

        public boolean openPort() {
            return true;
        }

        @Override
        public String toString() {
            return portName;
        }

        public static MockSerialPort[] getCommPorts() {
            List<MockSerialPort> ports = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                ports.add(new MockSerialPort("Port " + (i + 1)));
            }
            return ports.toArray(new MockSerialPort[] {});
        }
    }
}

在通过顶部的按钮选择了一个端口之前,GUI是被禁用的,然后底部的JTextField和按钮被启用,以通过以下方式向端口发送数据 .setEnabled(true).

这也包含了一个我没有的串口类的 "模拟 "类。

© www.soinside.com 2019 - 2024. All rights reserved.