I have a program that is going to do some work (in a background thread) at startup, so I'd like to display a busy cursor for a few moments while a table is being populated. Unfortunately, no matter what I did, I could not get a wait cursor to appear if my window (JFrame
) appeared under the pointer. I did some experimentation, and I tracked it down to a simple test case (below). Basically, if there exists a JScrollPanel
(e.g. as a parent for a JTable
) as a child of the JFrame
, then only the default cursor will appear unless I move the pointer out of the window and back in.
Here's the compilable code:
package curso开发者_JS百科rtest;
import java.awt.Cursor;
import java.awt.Dimension;
import javax.swing.*;
public class CursorTest extends JFrame {
void initPanel() {
JScrollPane panel = new JScrollPane();
panel.setMinimumSize(new Dimension(500, 500));
panel.setMaximumSize(new Dimension(500, 500));
panel.setPreferredSize(new Dimension(500, 500));
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(panel)
);
layout.setVerticalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(panel)
);
}
public CursorTest() {
initPanel();
setMinimumSize(new Dimension(500, 500));
setMaximumSize(new Dimension(500, 500));
setPreferredSize(new Dimension(500, 500));
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
pack();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new CursorTest().setVisible(true);
}
});
}
}
Launch the program so that when the window appears, the mouse pointer is within the bounds of the window. You may have to fiddle with the sizes to get that to happen (that I know I have forced in an artificial way for this example).
If initPanel
is NOT called, then the mouse cursor will immediately appear as a wait cursor.
If initPanel
IS called, then the mouse cursor will appear as default until you move the pointer out of the window and then back in.
Also, if the JScrollPane
is replaced with some other kind of widget, say a JLabel
, then this cursor problem does not manifest.
Can anyone help me to figure to how to fix this problem? I've thought about also setting the busy cursor for the widgets (my JScrollPanel
and/or JTable
), but this doesn't work. You could try it by adding the line panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
.
Oh, and I should probably mention that I'm doing this on a Mac.
for example
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class CursorTest extends JFrame {
private static final long serialVersionUID = 1L;
private javax.swing.Timer timer = null;
private JScrollPane scroll;
public CursorTest() {
scroll = new JScrollPane();
scroll.setPreferredSize(new Dimension(400,300));
setTitle("CursorTest");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
add(scroll);
setLocation(100, 100);
pack();
setVisible(true);
start();
}
private void start() {
scroll.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
timer = new javax.swing.Timer(5000, stop());
timer.start();
}
public Action stop() {
return new AbstractAction("Change Cursor Action") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
timer.stop();
scroll.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
};
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new CursorTest().setVisible(true);
}
});
}
}
精彩评论