问题
After many attempts trying to make a JProgressBar work as expected, I finally became successful at achieving my goal. I had used @MadProgrammer's advice and used a SwingWorker to finally get the program work as I want.
Now, I want the cursor to change into
when my JProgressBar goes from 0% to 100%. I've googled and found out that
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
is the code to do it. I've tried it but it does not work as expected.
Relevant piece of code:
JProgressBar progress;
JButton button;
JDialog dialog; //Fields of my GUI class
progress=new JProgressBar(JProgressBar.HORIZONTAL,0,100);
button=new JButton("Done");
dialog=new JDialog(); //Done from methods
progress.setValue(0);
progress.setStringPainted(true);
progress.setBorderPainted(true); //Also done from methods
button.addActionListener(this); //Also done from methods
dialog.setLayout(new FlowLayout(FlowLayout.CENTER));
dialog.setTitle("Please wait...");
dialog.setBounds(475,150,250,100);
dialog.setModal(true); //Also done from methods
dialog.add(new JLabel("Loading..."));
dialog.add(progress); //Also done from methods
And here is the actionPerformed method:
public void actionPerformed(ActionEvent e)
{
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Task task=new Task();
task.addPropertyChangeListener(this);
task.execute();
dialog.setVisible(true);
}
The propertyChange method:
public void propertyChange(PropertyChangeEvent evt) {
if("progress" == evt.getPropertyName()){
int progressnum = (Integer) evt.getNewValue();
progress.setValue(progressnum);
}
}
and the nested class Task:
class Task extends SwingWorker<Void, Void> {
/*
* Main task. Executed in background thread.
*/
@Override
public Void doInBackground() {
int progressnum = 0;
setProgress(0);
while (progressnum < 100) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
System.err.println("An error occured:"+ex);
ex.printStackTrace();
}
progressnum ++;
setProgress(Math.min(progressnum, 100));
}
return null;
}
/*
* Executed in event dispatching thread
*/
@Override
public void done() {
//setCursor(null); //turn off the wait cursor
setCursor(Cursor.getDefaultCursor()); //Is this one or the one above it right?
dialog.dispose();
progress.setValue(progress.getMinimum());
}
}
When I press button, the JDialog with the JProgressBar appears and the JProgressBar goes from 0% to 100%. During this time, the cursor needs to be changed into (busy cursor) and when the JProgressBar reaches 100%, the normal cursor(
) needs to be restored.
The problem is, when I press button, the cursor changes to the busy cursor for a split second and then, changes back into the original cursor. I want the cursor to be busy until the JProgressBar reaches 100%.
I've added the code to convert the cursor into a busy cursor in the actionPerformed method and the restore the normal cursor in the done method of the nested class Task. Note that I've also included the necessary packages.
- What is causing the problem?
- How do I fix it?
Should I use
setCursor(null);or
setCursor(Cursor.getDefaultCursor());to restore the cursor?
回答1:
When you call setCursor() on the JFrame, it only has effect for the frame, not the dialog. Similarly, when you call setCursor() on the JDialog, it only has effect for the dialog, not the frame. There the problem: you did not set the cursor for the dialog, right?
I'm not sure whether setCursor(null) is safer than setCursor(Cursor.getDefaultCursor()). :p
回答2:
Kudos for creating a modeless dialog and using a worker thread, which will improve the user's experience with decreased perceived latency. Consider adding a MouseListener to the dialog when the worker starts. Display the WAIT_CURSOR in your implementation of mouseEntered(), and restore the default in your implementation of mouseExited(). Remove the listener in done(). This will make the progress and cursor visual cues coincide when the user's attention shifts to the dialog while the worker is running.
来源:https://stackoverflow.com/questions/29817219/changing-the-default-cursor-to-busy-cursor-does-not-work-as-expected