2013-04-04 78 views
2

我正在開發一個應用程序(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"); 
} 
} 

的第二個代碼塊是啓動該應用程序的主類。有什麼建議麼?

回答

2

我強烈建議使用類似於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

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;例如通過調用此方法:

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