0

I am implementing a "Load File" functionality in my Java application - sometimes the file might be on a network share which can take a little while to read. Once the user has selected a file to load, I am changing the mouse cursor to Cursor.WAIT_CURSOR. This works fine on Windows, but I am getting strange results on both Java 7u75 and 8u45 on Mac OS 10.9.5. I have tried changing the cursor on both the JFrame component as well as the GlassPane, but I am seeing the same results.

Basically, on Mac OS, if the mouse interacts with the JFileChooser in any way then the cursor isn't changed, but if I use the keyboard to select a file then it works as expected and the cursor is changed.

This looks a bit bug like, but lookig for some wisdom from someone who might have come across this before and conquered it? I have put together an SSCCE below to demonstrate the problem.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class SSCCE extends JFrame implements ActionListener {
  private final SSCCE T = this;
  private Component gP = getRootPane().getGlassPane();
  private JMenuBar mBar;
  private JMenu mFile;
  private JMenuItem miLoad;

  public SSCCE() {
    setTitle("SSCCE");
    setSize(960, 640);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    mBar = new JMenuBar();
    mFile = new JMenu("File");
    miLoad = new JMenuItem("Load");
    miLoad.addActionListener(this);
    mFile.add(miLoad);
    mBar.add(mFile);
    setJMenuBar(mBar);

    setLocationRelativeTo(null);
    setVisible(true);
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    if (e.getSource() == miLoad) {
      JFileChooser fc = new JFileChooser();
      fc.showDialog(this, "Test");

      updateCursor(Cursor.WAIT_CURSOR);

      new SwingWorker<Void, Void>() {
        @Override
        protected Void doInBackground() {
          try {
            Thread.sleep(5000);
          }
          catch (Exception e) {
            e.printStackTrace();
          }
          return null;
        }

        @Override
        protected void done() {
          updateCursor(Cursor.DEFAULT_CURSOR);
          JOptionPane.showMessageDialog(T, "OK", "Status", JOptionPane.PLAIN_MESSAGE);
        }
      }.execute();
    }
  }

  private void updateCursor(final int c) {
    gP.setCursor(Cursor.getPredefinedCursor(c));
    gP.setVisible(c != Cursor.DEFAULT_CURSOR);
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        new SSCCE();
      }
    });
  }
}
chrixm
  • 942
  • 6
  • 26
  • 2
    `Thread.sleep(5000);` is your first problem... – MadProgrammer Apr 26 '15 at 09:06
  • Is this `Thread.sleep(5000)` your way of mocking the actual long file loading operation? If so, then indeed, you shouldn't be running it in the event dispatch thread. Use a swing worker. Different OSs do things different ways, and MacOS X may well update the cursor in the event dispatch loop. – RealSkeptic Apr 26 '15 at 09:13
  • Yes, I forgot to mention that I was using `Thread.sleep(5000)` to mimic the long loading times to demonstrate the problem. I don't really mind if the GUI locks up during a load file operation as the user shouldn't be able to do anything while this is happening - I just wanted to change the cursor so they knew something was happening. Doesn't my use of `invokeLater` schedule it after the cursor update? – chrixm Apr 26 '15 at 09:35
  • BUT, if the UI locks up, how is suppose to provide information about the state of the cursor? – MadProgrammer Apr 26 '15 at 09:37
  • Isn't `invokeLater` telling it to perform the tasks after it has processed all the other tasks on the EDT? If not, then I would need to place my load functionality into a Thread or SwingWorker after I have disabled the GUI from the EDT so the user can't fiddle with it, and then use `invokeLater` from the Thread to update the GUI? – chrixm Apr 26 '15 at 09:54
  • Read the file in the background as suggested [here](http://stackoverflow.com/q/25526833/230513); condition the cursor as suggested [here](http://stackoverflow.com/a/29819176/230513). – trashgod Apr 26 '15 at 10:30
  • Updated SSCCE to use a SwingWorker, but I am still seeing the same problem on Mac OS? – chrixm Apr 26 '15 at 10:53

0 Answers0