我对我的java GUI管理有一个问题。我正在制作更新程序,但当我试图从ExecutorService线程编辑一些JText或JProgressbar时,什么也没有…
为什么它坏了?这是我的ControllerManager:
public class UpdateManager extends AppManager {
private final List<Controller> controllers;
@Getter private final ExecutorService worker;
@Getter private final UserInterface form;
private boolean isEnd;
public UpdateManager() {
this.controllers = new ArrayList<>();
this.form = new Form(this);
this.worker = Executors.newCachedThreadPool();
}
@Override
public void start(Controller... controllers) {
form.initialize();
this.controllers.addAll(Arrays.asList(controllers));
for(Controller controller: controllers)
controller.start();
}
@Override
public void end(boolean dispose) {
if(isEnd) return;
for(Controller controller: controllers)
controller.end();
if(dispose) form.dispose();
isEnd = true;
}
}
这里有一个例子,当我试图改变一些标签:
/**
* Created by romain on 17/05/2015.
*/
public class ReleaseController implements Controller {
private final AppManager manager;
@Getter private final LinkedBlockingDeque<URL> files;
private Future<?> future;
private final SerializedObject<SerializedReleases> serializedReleases;
private final SerializedObject<Integer> serializedRelease, serializedTimestamp;
public ReleaseController(AppManager manager) {
this.manager = manager;
this.files = new LinkedBlockingDeque<>();
this.serializedReleases = SerializedObjectImpl.create(FileUtils.path("releases", "releases.dat"), true, null);
this.serializedRelease = SerializedObjectImpl.create(FileUtils.path("swtour", "release.int"), false, 0);
this.serializedTimestamp = SerializedObjectImpl.create(FileUtils.path("swtour", "timestamp.int"), false, 0);
}
/**
* TODO: checking local files
*/
@Override
public void start() {
this.future = manager.getWorker().submit(new Runnable() {
@Override
public void run() {
int release = serializedRelease.get();
int serverRelease = serializedReleases.get().lastRelease(AppUtils.OS);
int result = serverRelease - release;
if(result == 0 || result < 0) {
manager.getForm().alreadyUpdated(); //HERE
return;
}
for(int i=release+1;i<serverRelease;i++) {
try {
files.addLast(new URL(
FileUtils.path(Main.SERVER, "releases", AppUtils.OS.toString(), i + ".zip")));
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
serializedRelease.setObject(serverRelease).write();
serializedTimestamp.setObject((int)System.currentTimeMillis()).write();
}
});
}
@Override
public void end() {
if(future != null && !future.isCancelled())
future.cancel(true);
}
}
如果你没看错的话,它是:
manager.getForm().alreadyUpdated();
修改我的GUI:
public void alreadyUpdated() {
content.getFirstLine().setText("");
content.getSecondLine().setText("Your client is already up-to-date!");
content.getPlayButton().setEnabled(true);
}
但没有. .我的gui没有改变!谢谢你
尝试从另一个线程更新Swing数据结构有两个问题:
- Swing不是设计成多线程安全的。你可以破坏它的数据结构。没有什么强迫它看到在另一个线程中所做的更改。它可以在不受内存更改影响的寄存器或缓存中运行。
正如在评论中已经指出的那样,您需要使用invokeAndWait
或invokeLater
在Swing事件处理线程中进行更改。