当界面上的JButton按下按钮触发此事件侦听器时,我遇到了一个问题:

if (event.getSource() == goButton)
{
    MainLauncher.doProgram(assetsField.getText(), FileFinder.completePath(String.format("%s\\%s", modDirectoryPath, modList.getSelectedValue())), databaseField.getText());
}


运行以下代码:

public static void doProgram(final String baseGamePath, final String modPath, final String databasePath)
{
    new Thread()
    {
        public void run()
        {
            System.out.println("Running: " + modPath + "\n");

            reader = new MetaDataReader(databasePath);
            reader.formConnection();

            long start = System.currentTimeMillis();
            long temp;

            File cache = new File("RegisterCache.SC");
            if (!cache.exists())
            {
                temp = System.currentTimeMillis();

                start += System.currentTimeMillis() - temp;
                System.out.println("Calculating number of files");
                FileFinder baseGame = new FileFinder();
                baseGame.calculateNumFiles(baseGamePath);
                System.out.println(String.format("Loading %s base game files", baseGame.getNumFiles()));
                gui.doProgressBar();
                baseGame.findFiles(baseGamePath, true);
                gui.killProgressBar();
                System.out.println();

                 //load the base game assets, we want to move this to metadata later
                System.out.println("Checking for base game reference errors");
                new ReferenceDetector(Table.getRegister()).findReferences(true);
                Table.serializeTable(cache); //write the database to cache, we can use it next time
            }
            else
            {
                System.out.println("Loading cache");
                Table.unserializeTable(cache);
            }

            gui.doCommands(); //calls reset()!!! be careful with the temporary excludes!

            System.out.println("Eliminating base game requires errors");
            RequiresWhere.executeRequires(true);

            temp = System.currentTimeMillis();

            start += System.currentTimeMillis() - temp;
            System.out.println("Calculating number of files");
            FileFinder mod = new FileFinder();
            mod.calculateNumFiles(modPath);
            System.out.println(String.format("Loading %s mod files", mod.getNumFiles()));
            gui.doProgressBar();
            mod.findFiles(modPath, false);
            gui.killProgressBar();

            System.out.println();
            System.out.println("Finding reference errors");
            new ReferenceDetector(Table.getRegister()).findReferences(false);

            System.out.println("Finding requires errors");
            RequiresWhere.executeRequires(false);

            System.out.println("Checks complete");
            reader.killConnection();

            System.out.println(String.format("Execution Time: %dms", System.currentTimeMillis() - start));
            Table.reset();
        }
    }.run();
}


奇怪的是:

测试时,我没有将按钮添加到界面上,依此类推,在main()上我调用了goButton.doClick();,该触发了doProgram(),并给出了我期望的结果:

打印了几件事(在从JTextArea接收的界面上的System.out.println()上),控制台上方弹出进度条,大约10秒钟内从0%变为100%,消失了一些打印更多东西等等

但是,当我将按钮添加到界面时,我单击了按钮,其行为完全不同:

什么都没有打印。进度条出现,并在0%处停留10秒钟,然后消失,几秒钟后doProgram完成执行,并且所有在运行时应打印的信息突然全部一次打印出来。

谁能告诉我是什么导致这种奇怪的行为以及如何解决?

我会发布一个SSCCE,但是对于这个程序来说,这有点困难,因为任务和子流程太多了。请注意,我使用它的进度条在GUI线程上运行,主要代码在其自己的线程中完成(如您所见)

编辑:我在setEnabled(false);调用周围的监听器中添加了doProgram和true,并且以编程方式按下该按钮时,该按钮呈灰色显示,并且正如我所期望的那样启用,但是,如果我手动单击该按钮,不禁用,我可以再按一次

最佳答案

该代码看起来有些混乱。

但是,首先:您正在调用在那里创建的新线程的run()方法。这将导致run()方法中的代码由调用doProgram的线程执行,而不是由在那里创建的新线程执行。为了真正在此新线程中执行代码,您必须调用start()而不是run()

这可能解释了您描述的大多数差异。但是,请记住,必须始终在事件调度线程上对Swing组件进行修改。因此,例如,使用gui.doCommands()进行操作时,请确保您没有违反此单线程规则。

09-04 05:53