我的应用程序基本上使用apache的httpclient连接到服务器并为用户做些事情。
我是一名java初学者(虽然不是开发初学者),但许多特定于Java的方法可能会被冷静地忽略。
描述
这是我在Java中的第一个应用程序,因此可能存在许多晦涩难懂...... :(
问题
所需的行为是,每当用户尝试运行此应用程序的第二个实例时,它会尝试在端口X上绑定套接字侦听器,并且失败时会向该端口发送字符串消息。主要' app接受消息并对显示的确认对话框做出反应,要求用户输入一些信息。
当我添加客户端服务器时,一切正常工作;第二个实例成功触发观察者的update()方法,观察者正确区分正在进行的操作并触发相应的方法;然后在第一个新的GUI组件(确认对话框)应该出现时,没有发生:
..只是对话后的所有说明都没有执行,对话框也没有出现。
WEIRDNESS#1
当用户使用托盘图标菜单触发显示对话框的其他命令时,GUI以某种方式咳嗽并以正确的顺序显示两个(或更多适当的时候)对话框(首先显示卡住的隐藏对话框然后第二个新鲜的)并且一切似乎都是正确的状态并且所有命令都被正确执行(尽管其中一些命令稍后有点)。
WEIRDNESS#2
我猜这是因为挥杆与线程不兼容;但是,当update()方法从httpclient(也是一个单独的线程)中启动时,GUI工作正常。观察者获得通知的方式的唯一区别是 WebClient 在一些用户操作之后调用notifyObservers()(虽然在一个单独的线程中以及在(最差的)30s超时和 AttServer之后在catch()块中调用notifyObservers(),因为当指定的端口已被绑定时抛出IOException。
WEIRDNESS#3
这个问题至少可以说是不规则的。它通常发生在开发环境(netbeans)中,虽然有时候它并没有 - 起初我得到的印象是它通过调用另一个(虚拟)JDialog来解决,它仍然是故意隐藏的,实际上有问题的对话 - 看起来摇摆需要一点点“推开门”#;;虽然在将项目构建到jar或exe(通过launch4j)后,问题又回来了。然后我尝试在所有的swing对话框中使用单个JFrame组件,它有所帮助 - 有时当输出jar运行时它会正常工作,第二天它会再次隐藏对话框。
我完全迷失了,在地球上搜寻解决方案,没有发现任何真的。我希望其他人可能碰到一些类似的问题,并且作为一个更有经验的Javaman,找到了解决方案。我还在主JFrame实例上尝试了一些doLayout(),validate(),revalidate(),repaint(),update()调用,但没有去。
有希望:)感谢阅读,并感谢任何想法。
代码示例
这是来自 AttServer 的run()函数 - 非工作更新()的来源...(它有点硬编码,因为主要功能在那里,我被困在其他地方..)
public void run() {
this.addObserver( Controller.getInstance() );
setChanged();
// this.command == INIT set and new thread with AttServer called in the beginning of the main()
if( null != this.command ) {
switch( this.command ) {
case INIT:
try {
init();
} catch( IOException ex ) {
notifyObservers( new ErrorEvent( 100 , "Could not bind the specified port." ) );
}
break;
default:
} //switch
// no command, looks like an incoming connection
} else {
try {
DataInputStream in = new DataInputStream( socket.getInputStream() );
String inputLine;
while( ( inputLine = in.readLine() ) != null ) {
if( inputLine.trim().equals( EventType.CLOCKIN.toString() ) ) {
notifyObservers( EventType.CLOCKIN );
return;
}
}
} catch( IOException ex ) {
//todo
}
}
}
..这是围栏的另一面,即update()方法:
public void update( Observable obj, Object arg) {
// received a remote request *******************************************
if( obj instanceof AttServer
&& arg instanceof EventType ) {
EventType command = (EventType) arg;
Attendance.debugMsg( "Received " + command.toString() + " request from AttServer" );
if( false == isOnClock ) {
doClock( true , true );
}
} // ..........
..这是从update()调用的doClock()方法的本质 - 实际上并没有什么,即使在调用之后立即显示对话框,或者在事件发生时也是如此。如果在update()方法中显示,它不起作用。
(overloaded with default data)
public static void doClock( Boolean clockIn , Boolean confirm , String message , String title ) {
Event lastEvent = Log.getLastClock();
if( confirm ) {
if( JOptionPane.NO_OPTION == JOptionPane.showConfirmDialog( mainFrame , message , title , JOptionPane.YES_NO_OPTION ) ) {
return;
}
}
答案 0 :(得分:5)
如果没有阅读整个文档(!!!),我猜你不会通过Event Dispatch Thread (EDT)更新GUI。
GUI应仅由单个线程,EDT 更新。
您可以在应用程序中使用后台线程,但必须将更新GUI传递给EDT 。
请勿触摸您自己的线程中的任何Swing控件,即EDT以外的其他线程
否则你会遇到很多问题
不通过EDT显然是错误的