Component state change must be done on Event Dispatch Thread,程序运行出现了这个问题,现在用swing做的是文件传输,C/S模式下的,在一条监听线程中一直监听客户端的回应,有请求就读写文件并写入socket流中去,过程中有一个进度条,进度条的改变也是在监听线程中进行的,监听线程再起了一条线程去改变进度条的状态,下面是改变进度条的一段代码:try {
final FileInputStream fin = new FileInputStream(selectFile);
final byte[] buff = new byte[1024];
final int s;
final long size = selectFile.length();
final int count = 0;
SwingUtilities.invokeLater(new Runnable() { public void run() {
bar.setMaximum((int) size);
while ((s = fin.read(buff)) > 0) {
count += s; //这里出问题了count 显示 The final local variable count cannot be assigned, since it is defined in an enclosing type
oos.write(buff, 0, s);
String str = "" + 100 * (count / size);
bar.setString(str + " %");
bar.setValue(count);
}
}
});
oos.flush();
fin.close();
oos.close();
client.close();
server.close();
} catch (Exception e2) {
e2.printStackTrace();
}上面的代码会抛Component state change must be done on Event Dispatch Thread这个异常,只有当完全传送完后才显示100%,过程中没有变化,即没有动起来,假如我用 try {
final FileInputStream fin = new FileInputStream(selectFile);
final byte[] buff = new byte[1024];
int s;
final long size = selectFile.length();
int count = 0;
while ((s = fin.read(buff)) > 0) {
count += s;
final int count_value = count;
oos.write(buff, 0, s);
final String str = "" + 100 * (count / size);
SwingUtilities.invokeLater(new Runnable() { public void run() {
bar.setMaximum((int) size);
bar.setString(str + " %");
bar.setValue(count_value );
}
});
} oos.flush();
fin.close();
oos.close();
client.close();
server.close();
} catch (Exception e) {
e.printStackTrace();
} }这里用了 SwingUtilities.invokeLater后进度条是能动了,但是上面的那些变量都得改为final类型,bar.setString()方法在这里没用了,bar是JProgressBar~,这里面的count_value 在这里只能为final,而且也想不明白count_value 既然是final了,应该只能只能被赋值一次,赋值后值不再改变,但是bar.setValue()还是动了~如果直接bar.setValue(count)的话,count要改为final,里面就运行不来了在count+=s那里~以上是问题,有表达不到位的说下~恳请大侠们给点指点,蛋疼了2天的问题了~又是双休日~~~有空耐心的看下~
final FileInputStream fin = new FileInputStream(selectFile);
final byte[] buff = new byte[1024];
final int s;
final long size = selectFile.length();
final int count = 0;
SwingUtilities.invokeLater(new Runnable() { public void run() {
bar.setMaximum((int) size);
while ((s = fin.read(buff)) > 0) {
count += s; //这里出问题了count 显示 The final local variable count cannot be assigned, since it is defined in an enclosing type
oos.write(buff, 0, s);
String str = "" + 100 * (count / size);
bar.setString(str + " %");
bar.setValue(count);
}
}
});
oos.flush();
fin.close();
oos.close();
client.close();
server.close();
} catch (Exception e2) {
e2.printStackTrace();
}上面的代码会抛Component state change must be done on Event Dispatch Thread这个异常,只有当完全传送完后才显示100%,过程中没有变化,即没有动起来,假如我用 try {
final FileInputStream fin = new FileInputStream(selectFile);
final byte[] buff = new byte[1024];
int s;
final long size = selectFile.length();
int count = 0;
while ((s = fin.read(buff)) > 0) {
count += s;
final int count_value = count;
oos.write(buff, 0, s);
final String str = "" + 100 * (count / size);
SwingUtilities.invokeLater(new Runnable() { public void run() {
bar.setMaximum((int) size);
bar.setString(str + " %");
bar.setValue(count_value );
}
});
} oos.flush();
fin.close();
oos.close();
client.close();
server.close();
} catch (Exception e) {
e.printStackTrace();
} }这里用了 SwingUtilities.invokeLater后进度条是能动了,但是上面的那些变量都得改为final类型,bar.setString()方法在这里没用了,bar是JProgressBar~,这里面的count_value 在这里只能为final,而且也想不明白count_value 既然是final了,应该只能只能被赋值一次,赋值后值不再改变,但是bar.setValue()还是动了~如果直接bar.setValue(count)的话,count要改为final,里面就运行不来了在count+=s那里~以上是问题,有表达不到位的说下~恳请大侠们给点指点,蛋疼了2天的问题了~又是双休日~~~有空耐心的看下~
SwingUtilities.invokeLater(new Runnable(){//...});这个方法造成的,其官方API解释为:导致 doRun.run() 在 AWT 事件指派线程上异步执行。在所有挂起的 AWT 事件被处理后才发生。此方法应该在应用程序线程需要更新该 GUI 时使用。在下面的示例中,invokeLater 调用将事件指派线程上的 Runnable 对象 doHelloWorld 加入队列,然后输出一条信息。
Runnable doHelloWorld = new Runnable() {
public void run() {
System.out.println("Hello World on " + Thread.currentThread());
}
}; SwingUtilities.invokeLater(doHelloWorld);
System.out.println("This might well be displayed before the other message.");
这样就导致了你的第一段代码的结果,就是进度条没有动。2.你的意图很明显,就是用多线程读写文件、发送socket,然后用一个进度条去监听进度。这是多线程的应用个,你可以直接继承Thread类或者实现Runnable接口来进行多线程处理,同时注意一下线程同步。对进度条的控制,可以通过估算进度的方式来显示。其实进度条的作用无非就是告诉用户:"我的程序正在帮你积极处理一些事情,马上就好了"。3.使用SwingUtilities.invokeLater方法后,在run方法中的count必须要定义为final类型的。这是因为你在SwingUtilities.invokeLater方法中传递了一个匿名内部类new Runnable(){//...},因此count属于外部类的属性,在内部类中使用就必须是final标示的。4.通常来说被赋予为final类型的变量,我们都说它是最终变量。从某种角度来说,它是不可更改的。但如果你清楚private final int iCount = 10;这条语句的执行过程后,你就会改变看法。另外,在你的这段代码中while ((s = fin.read(buff)) > 0) {
count += s;
final int count_value = count;
oos.write(buff, 0, s);
final String str = "" + 100 * (count / size);
SwingUtilities.invokeLater(new Runnable() { public void run() {
bar.setMaximum((int) size);
bar.setString(str + " %");
bar.setValue(count_value );
}
});
}
每循环一次,你就定义了一个变量count_value,并赋值为count,由于count在变化,count_value每次都是新定义的,所有你的进度条当然就会改变。5.建议:将thinking in java多看几遍!!6.期望:结贴吧。如有问题可继续发帖问~~ 兄弟回复打字手都打软了~~
Runnable doHelloWorld = new Runnable() {
public void run() {
System.out.println("Hello World on " + Thread.currentThread());
}
}; SwingUtilities.invokeLater(doHelloWorld);
System.out.println("This might well be displayed before the other message.");
2.楼主是想用多线程实现文件读写、socket传送,并使用进度条显示进度。其实可以直接使用Thread类或者Runnable接口。只要注意线程状态和同步控制就可以了。其实进度条的目的是告诉客户:“我的程序正在努力为你工作,请你等候一下”。另外,注意swing组件不具有线程安全,有些地方你需要自己去控制。3.第一段代码中:final int count = 0;
SwingUtilities.invokeLater(new Runnable() { public void run() {
bar.setMaximum((int) size);
while ((s = fin.read(buff)) > 0) {
count += s; //这里出问题了count 显示 The final local variable count cannot be assigned, since it is defined in an enclosing type
oos.write(buff, 0, s);
String str = "" + 100 * (count / size);
bar.setString(str + " %");
bar.setValue(count);
}
}
});你的count是在外部定义的,且为final标示,因此你在while循环中试图改变其值,就必然会出现错误。
而第二段代码中:
while ((s = fin.read(buff)) > 0) {
count += s;
final int count_value = count;
oos.write(buff, 0, s);
final String str = "" + 100 * (count / size);
SwingUtilities.invokeLater(new Runnable() { public void run() {
bar.setMaximum((int) size);
bar.setString(str + " %");
bar.setValue(count_value );
}
});
}你是在每次循环中都定义了一个final标示的count_value变量,也就是说循环多少次就有多少个count_value变量产生,且将之赋值为count,由于count是变化的,因此会常出现进度条有反应的状况。4.SwingUtilities.invokeLater(new Runnable() { public void run() {
bar.setMaximum((int) size);
bar.setString(str + " %");
bar.setValue(count_value );
}
});这样的代码使用了匿名内部类,且count_value不是在该匿名内部类中进行定义的,也就属于外部类,因此java要求必须标示为final。5.通常我们都说final标示的变量不可更改,从某种意义上说这没错。但如果你彻底理解了private final int count = 29;的执行步骤和顺序,你会改变自己的看法。建议楼主多看看《thinking in java》。6.打字手都打软了,第一次没发送成功,打了两遍。楼主结贴吧...
不知道该说csdn太贰,还是我自己~~~