在我的Java GUI应用程序中,我有JButton
,点击后会调用function
来连接到database
,然后调用function
到clear
} table
中的DB
,然后调用function
从一个文件中读取文本并加载variables
,该function
调用从另一个文件读取文本的data
文件,比较两者中的function
,然后将update
调用到数据库中的insert
或JButton
数据,所有这些都可以正常工作。
但是我的问题与Indeterminate progress bar
有关,点击后我想运行一个action listener setIndeterminate to false
,以便用户知道正在完成的工作,然后就在它离开{{1}之前并将progress bar
的值设置为100(complete)
,但在我的情况下,当您点击button
时,它会保持点击状态并且progress bar
冻结。
我应该采取什么措施来防止这种情况发生?可能穿线?但我对java中的线程很新。这是我的动作听众:
private class buttonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if( e.getSource() == genButton )
{
progressBar.setIndeterminate(true);
progressBar.setString(null);
try
{
dbConnect(); //connects to DB
clearSchedules(); // deletes data in tables
readFile(); // reads first file and calls the other functions
dbClose();// closes the DB
progressBar.setIndeterminate(false);
progressBar.setValue(100);
}
catch (Exception e1){
System.err.println("Error: " + e1.getMessage());
}
}
}
}
另一方面,我希望操作栏实际上随着程序的进展而移动,但我不确定如何监控其进度。
谢谢,牛肉。
UPDATE 这是我的SwingWorker示例以及我如何使用它:
全球宣布
private functionWorker task;
private abstract class functionWorker extends SwingWorker {
public void execute() {
try {
dbConnect();
} catch (SQLException e) {
e.printStackTrace();
}
clearSchedules();
try {
readFile();
} catch (IOException e) {
e.printStackTrace();
}
dbClose();
}
}
在我的actionPerformed方法
中if( e.getSource() == genButton )
{
progressBar.setIndeterminate(true);
progressBar.setString(null);
try
{
task.execute();
progressBar.setIndeterminate(false);
progressBar.setValue(100);
}
catch (Exception e1){
System.err.println("Error: " + e1.getMessage());
}
}
答案 0 :(得分:7)
问题可能与连接到UI线程中的昂贵操作(连接到数据库,从文件读取,调用其他函数)有关。在任何情况下都不应该从UI线程调用占用过多CPU时间的代码,因为整个界面在执行代码时无法继续,并且会导致“死”的应用程序,其中组件保持其状态为在昂贵的操作直到完成之前的时间。您应该执行另一个线程,执行其中的昂贵工作,然后使用带有传递的runnable的SwingUtilities.invokeLater(Runnable doRun)
来更新进度。
可能存在与组件状态相关的同步问题,但您可以稍后解决这些问题。
答案 1 :(得分:6)
我可以在执行操作时创建新线程并在线程中调用新函数,还是应该在实际函数本身内执行线程?
您可以从按钮的处理程序中启动SwingWorker
,如图here所示。实现Runnable
的相关示例见here。
答案 2 :(得分:5)
处理进度条的一种方法是在类中扩展SwingWorker
。
SwingWorker
负责为您运行后台任务,因此您不必实现自己的线程,最终可能导致未知问题。
首先,负责处理进度条UI的班级应该实现PropertyChangeListener
并实现public void propertyChange(PropertyChangeEvent evt) {
- 根据全局变量更新进度条状态。
后台任务类应如下所示(这可能是内部类):
class ProgressTask extends SwingWorker<Void, Void> {
@Override
public Void doInBackground() {
//handle your tasks here
//update global variable to indicate task status.
}
@Override
public void done() {
//re-enabled your button
}
}
按钮的事件监听器:
public void actionPerformed(ActionEvent evt) {
//disable your button
//Create new instance of "ProgressTask"
//make the task listen to progress changes by task.addPropertyChangeListener(this);
//calll task.execute();
}
我试图淡化代码示例,您必须阅读一些教程以了解所有这些部分是如何组合在一起的。但是,重点是不要编写你的线程代码,而是使用SwingWorker
答案 3 :(得分:0)
progressBar.setIndeterminate(true);
progressBar.setValue(0);
dbConnect(); //connects to DB
progressBar.setIndeterminate(true);
progressBar.setValue(10);
clearSchedules(); // deletes data in tables
progressBar.setIndeterminate(true);
progressBar.setValue(50);
readFile(); // reads first file and calls the other functions
progressBar.setIndeterminate(true);
progressBar.setValue(75);
dbClose();// closes the DB
progressBar.setIndeterminate(false);
progressBar.setValue(100);
您需要告诉进度条已取得多少进展,因为它不知道完成的百分比。更好的是,编写一个更新和重新绘制进度条的方法,而不是在这里重复方法调用。
updateProgressBar(int progress, boolean isDeterminate, String msg){};
您还需要确保您的特定按钮触发了所执行的操作。
class IvjEventHandler implements java.awt.event.ActionListener {
public void actionPerformed(java.awt.event.ActionEvent e) {
if (e.getSource() == JMyPanel.this.getJButtonUpdate())
connEtoC1(e);
};
};
connEtoC1(e);应该执行控制器类或SwingWorker,而不是从GUI
触发