为什么java swing不允许从ExecutorService线程进行更改



我对我的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不是设计成多线程安全的。你可以破坏它的数据结构。没有什么强迫它看到在另一个线程中所做的更改。它可以在不受内存更改影响的寄存器或缓存中运行。

正如在评论中已经指出的那样,您需要使用invokeAndWaitinvokeLater在Swing事件处理线程中进行更改。

相关内容

  • 没有找到相关文章

最新更新