Changing the default cursor to busy cursor does not work as expected

房东的猫 提交于 2019-12-04 04:58:16

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!