尝试连接到串行端口时使用javax.swing.SwingWorker时出现问题

时间:2013-04-04 22:43:44

标签: java swing user-interface serial-port xbee

我正在开发一个Java应用程序,它将从Xbee设备接收的数据上传到在线数据库。功能就在那里,一切正常,但在开发GUI(使用WindowsPro Builder)时,一切都很糟糕。问题是,应用程序需要能够检测到Xbee设备,如果没有连接,请等待它连接 - 无限期(或直到关闭)。我已经有一种方法可以检测串口是否是Xbee设备;就像我说的,一切正常,除非我将它与GUI集成。

我遇到的问题是创建一个首先检测Xbee设备是否已连接的GUI,如果没有,则显示一条消息,通知用户连接设备以便继续。同时(显示消息时),我需要调用扫描串口的方法。我在考虑线程,但我有一段时间没有使用它们。请注意,该方法已在应用程序启动时运行一次,以便尝试连接。我没有代码可以显示,因为我所做的只是提出了基本的框架,按钮等(还没有事件)。我是Java的GUI编程新手,有什么建议吗?

更新:所以我试图实现MadProgrammer建议的内容,我确信它在SwingWorker教程中有用,但没有任何反应。唯一运行的是设置GUI。接下来是代码:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;

import javax.swing.SwingWorker;


public class ConnectionWorker extends SwingWorker<Boolean, String> {

private ConnectionListener callBack;
private Xbee xbee = new Xbee();
private QboComm comm;

public ConnectionWorker(ConnectionListener listener, QboComm comm) {
    this.callBack = listener;
    this.comm = comm;
}


protected void process(List<String> chunks) {
    String msg = chunks.get(chunks.size() - 1);
    if (msg.equals("WAITING")) {
        comm.publishError();
    }
}

protected Boolean doInBackground() throws Exception {
    boolean isConnected = false;
    this.xbee = QboComm.xbee;
    ArrayList<String> list = new ArrayList<String>();
    if(!isConnected){
        publish("WAITING");
        while(!isConnected){
            list = xbee.getSerialPorts();
            for(String s : list){
                isConnected = xbee.connect(s);
                if(isConnected){
                    publish("DONE");
                    break;
                }
            }
        }
    }
    return isConnected;
}


protected void done() {
    boolean check;
    try {
        check = get();
        if (check) {
            comm.removeError();
            callBack.connectionEstablished();
        } else {
            callBack.connectionFailed();
        }
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}  
}

import java.awt.EventQueue;


public class QboComm {

private JFrame frmQboCommunicator;
public static Xbee xbee = new Xbee();
private JInternalFrame internalFrame;
private JLabel lblConnected;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            QboComm window = new QboComm();
            window.frmQboCommunicator.setVisible(true);
            ConnectionListener callback = new ConnectionListener() {
                public void connectionEstablished() {
                    try {
                        ArrayList<String> list = new ArrayList<String>();
                        list = xbee.fetch();
                        DBConnector db = DBConnector.getConnector();
                        if(db.connect()){
                            for(String s : list){
                                db.upload(s.substring(0, 5), s.substring(5));
                            }
                        }
                        db.disconnect();
                        xbee.printDBList();
                    } catch (Exception e) {
                        e.printStackTrace();
                    } 
                }
                public void connectionFailed() {
                    //IMPLEMENT
                }
            };
            new ConnectionWorker(callback, window).execute();
        }
    });
}

/**
 * Create the application.
 */
public QboComm() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frmQboCommunicator = new JFrame();
    frmQboCommunicator.setTitle("Qbo Communicator");
    frmQboCommunicator.getContentPane().setBackground(new Color(165, 42, 42));
    frmQboCommunicator.getContentPane().setForeground(new Color(211, 211, 211));
    frmQboCommunicator.setBounds(100, 100, 450, 300);
    frmQboCommunicator.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frmQboCommunicator.getContentPane().setLayout(null);

    /**
     * Connection Error Pop-up
     */
    this.internalFrame = new JInternalFrame("Connection Error");
    internalFrame.setBorder(new LineBorder(new Color(153, 180, 209), 3));
    internalFrame.setBounds(103, 46, 227, 157);
    frmQboCommunicator.getContentPane().add(internalFrame);
    internalFrame.getContentPane().setLayout(null);
    JTextPane txtpnAQboCommunicator = new JTextPane();
    txtpnAQboCommunicator.setText("A Qbo Communicator is not connected. Please connect a Qbo Communicator to continue.");
    txtpnAQboCommunicator.setEditable(false);
    txtpnAQboCommunicator.setBounds(0, 0, 211, 128);
    internalFrame.getContentPane().add(txtpnAQboCommunicator);
    internalFrame.setVisible(false);

    /**
     * Application Name
     */
    JLabel lblQboCommunicator = DefaultComponentFactory.getInstance().createTitle("QBO COMMUNICATOR");
    lblQboCommunicator.setForeground(new Color(255, 255, 255));
    lblQboCommunicator.setBackground(new Color(255, 255, 240));
    lblQboCommunicator.setHorizontalAlignment(SwingConstants.CENTER);
    lblQboCommunicator.setBounds(144, 0, 146, 14);
    frmQboCommunicator.getContentPane().add(lblQboCommunicator);

    /**
     * Connected label, displayed when connected to Xbee device
     */
    this.lblConnected = DefaultComponentFactory.getInstance().createLabel("CONNECTED");
    lblConnected.setForeground(new Color(255, 255, 255));
    lblConnected.setFont(new Font("Tahoma", Font.BOLD, 14));
    lblConnected.setHorizontalAlignment(SwingConstants.CENTER);
    lblConnected.setBounds(144, 25, 146, 14);
    frmQboCommunicator.getContentPane().add(lblConnected);

    /**
     * Scroll Panel that displays uploaded data
     */

    JScrollPane scrollPane = new JScrollPane();
    scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setBounds(53, 65, 344, 131);
    frmQboCommunicator.getContentPane().add(scrollPane);

    JPanel panel = new JPanel();
    panel.setBorder(new LineBorder(new Color(255, 255, 255)));
    panel.setBackground(new Color(165, 42, 42));
    scrollPane.setViewportView(panel);

    /**
     * Progress Bar
     */
    JProgressBar progressBar = new JProgressBar();
    progressBar.setStringPainted(true);
    progressBar.setFont(new Font("Tahoma", Font.BOLD, 12));
    progressBar.setBackground(new Color(255, 255, 255));
    progressBar.setForeground(new Color(255, 140, 0));
    progressBar.setBounds(53, 214, 344, 25);
    frmQboCommunicator.getContentPane().add(progressBar);
}

public void publishError(){
    this.internalFrame.setVisible(true);
    this.lblConnected.setText("DISCONNECTED");
}

public void removeError(){
    this.internalFrame.setVisible(false);
    this.lblConnected.setText("CONNECTED");
}
}

第二个代码块是启动应用程序的主类。有什么建议吗?

2 个答案:

答案 0 :(得分:2)

你正在使用线程。

您可能对Java trail中的Concurrency Tutorial感兴趣。我会想到notify and wait的内容。例如:

public synchronized guardedJoy() {
    // This guard only loops once for each special event, which may not
    // be the event we're waiting for.
    while(!joy) {
        try {
            wait();
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}

上面的代码将等到另一个线程从notify块或方法调用对象上的synchronized方法;例如,通过调用此方法:

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}

答案 1 :(得分:2)

我强烈建议使用类似SwingWorker的内容。

你不想做的是在阻止UI的事件调度线程上做任何事情,这将阻止你更新UI(包括显示消息)和UI自我更新,使它看起来像它挂了。

查看Concurrency in Swing了解详情。

Swing是一个事件驱动的环境(我敢肯定),基本上,你希望你的应用程序只是运行直到建立连接,可能会显示某种消息窗口,表明它正在等待连接。

设置一个可以为另一个类提供回调的SwingWorker,我将是一个相对简单的过程。

import java.awt.EventQueue;
import java.util.List;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class WaitForSwingWorker {

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

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

                ConnectionListener callback = new ConnectionListener() {

                    @Override
                    public void connectionEstablished() {
                        // Continue running the app
                    }

                    @Override
                    public void connectionFailed() {
                        // Show error message :(
                    }
                };

                new ConnectionWorker(callback).execute();

                // Execution will continue here...

            }
        });
    }

    public interface ConnectionListener {
        public void connectionEstablished();
        // If possible, you should provide a message as to why...
        public void connectionFailed();
    }

    public class ConnectionWorker extends SwingWorker<Void, String> {

        private ConnectionListener callBack;

        public ConnectionWorker(ConnectionListener listener) {
            callBack = listener;
        }

        @Override
        protected void process(List<String> chunks) {
            // Back in the EDT...
            String msg = chunks.get(chunks.size() - 1);
            if (msg.equals("WAITING")) {
                // Show waiting for connection message...
            }
        }

        @Override
        protected Void doInBackground() throws Exception {
            // Within our own thread
            // Establish connection...
            if (!isConnected) {
                publish("WAITING");
                // Wait for incoming connection, this can block...
            }
            return null;
        }

        @Override
        protected void done() {
            // Back in the EDT
            if (isConnected) {
                // Show failed to connect message?
                callBack.connectionEstablished();
            } else {
                callBack.connectionFailed();
            }
        }

    }

}

nb-这是概念验证,您需要填写功能