尝试连接到串行端口时使用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-这是一个概念证明,你需要填写功能
你正在跟踪线程。
您可能会感兴趣的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();
}
我收到错误“名称冲突:ConnectionWorker类型的方法进程(列表)与类型为SwingWorker的进程(List)具有相同的擦除但不覆盖它”用于此方法。我该怎么办? –
yoaquim
2013-04-06 00:33:11
Scratch:没有设置SwingWorker参数类型。我认为现在所有的代码都可以,但我仍然遇到一些麻烦。检查更新。 – yoaquim 2013-04-06 01:03:57