当界面上的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()
进行操作时,请确保您没有违反此单线程规则。