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

问题描述:

我正在开发一个应用程序(Java),用于将从Xbee设备接收的数据上载到联机数据库。功能在那里,一切正常,但是在开发GUI(使用WindowsPro Builder)时,一切都变得很糟糕。事情是,应用程序需要能够检测Xbee设备,如果没有连接,请等待它连接 - 无限期地(或直到关闭)。我已经有了一个方法来检测串口是否是Xbee设备;就像我说的那样,除了我将它与GUI集成在一起时,一切都有效。尝试连接到串行端口时使用javax.swing.SwingWorker的问题

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

更新:所以我还挺想实现什么MadProgrammer建议,这我有点相信它的工作原理给出的SwingWorker的教程,但没有happens.The只运行的是建立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"); 
} 
} 

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

我强烈建议使用类似于SwingWorker的东西。

你不想做的事情是在事件分派线程上做任何事情来阻止用户界面,这将阻止你更新用户界面(包括显示消息)和用户界面从自己更新它,使它看起来就像挂了。

查看更多详情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-这是一个概念证明,你需要填写功能

+0

我收到错误“名称冲突:ConnectionWorker类型的方法进程(列表)与类型为SwingWorker的进程(List)具有相同的擦除但不覆盖它”用于此方法。我该怎么办? – yoaquim 2013-04-06 00:33:11

+0

Scratch:没有设置SwingWorker参数类型。我认为现在所有的代码都可以,但我仍然遇到一些麻烦。检查更新。 – yoaquim 2013-04-06 01:03:57

你正在跟踪线程。

您可能会感兴趣的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;例如通过调用此方法:

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

我不认为这是明智的,赶上而忽视'InterruptedException'。被中断通常意味着,线程应该实际上停止它正在做的事情,做可能的清理,并终止或返回到某个基本状态,等待新事物的执行。 – hyde 2013-04-04 23:01:26

+0

@hyde这是我链接的教程中的一个例子。这只是为了演示如何使用'wait';因为'wait'会抛出'InterruptedException',所以这是必须的。如果这是一个真正的应用程序,那么是的,我同意,这将是一个坏主意。 – wchargin 2013-04-04 23:23:10