手动按JButton会产生不同的结果doClick()?

J_m*_*ie6 1 java swing event-listener jbutton

JButton在界面上遇到问题,当按下按钮时触发此事件监听器:

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

它运行以下代码:

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();
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是:

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

打印出几个东西(JTextArea接收到的接口System.out.println()),控制台上方会弹出一个进度条,大约10秒内从0%变为100%,消失,打印更多东西等等.

但是,当我将按钮添加到界面时,我点击它并且行为完全不同:

什么都没打印.进度条出现,并且在10秒内保持0%,然后消失,几秒钟之后doProgram完成执行,并且在运行期间应该打印的所有信息都会突然全部打印出来.

任何人都可以告诉我是什么原因造成这种奇怪的行为以及如何解决这个问题?

我会发布一个SSCCE,但由于有很多任务和子进程,这个程序有点难.请注意,我使用它的进度条在GUI线程上运行,主代码在它自己的线程中完成(如您所见)

编辑:我setEnabled(false);在调用周围的侦听器中添加并且为true doProgram,当按钮以编程方式按下时,按钮显示为灰色并且按照我的预期进行重新设置,但是如果我手动单击按钮它不会禁用,我可以再按一次

Mar*_*o13 5

代码看起来有点令人困惑.

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

这可能解释了您所描述的大多数差异.但是,请记住,始终必须在Event Dispatch Thread上对Swing组件进行修改.因此,无论您正在做什么,例如,使用gui.doCommands(),请确保您不违反此单线程规则.