触发setCursor方法后,光标图标不会更改

我的应用程序中有一个带可resize的标题列的JTable 。 通常,当我将光标移动到表头以进行resize时,光标图标会更改为resize箭头,如。

但是在以下场景中情况有所不同。

在同一Frame有一个按钮动作,并且在执行动作期间,我将光标设置为忙图标,并在动作完成后使用Container.setCurosr(Cursor cursor)方法将其更改回默认光标。

有时如果我将光标移到resize的表头上,在按钮操作后,光标图标不会更改为resize箭头,光标根本不会改变。

这可以被视为Java Swing中的错误还是有针对此问题的解决方案?

更新:附加示例代码

 import java.util.*; import java.awt.*; import javax.swing.*; import java.awt.event.*; public class ColumnResizeIconTest extends JFrame { JScrollPane scrollPane; JTable table; JButton button; public ColumnResizeIconTest() { setLayout(new BorderLayout()); addComponents(); setSize(300,300); } private void addComponents() { addButton(); addTable(); } private void addButton() { button = new JButton("Click Me"); button.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent ae) { setWaitCursor(); for(int i=0; i<2000; i++) { System.out.print(i); } setDefaultCursor(); } }); add(button, BorderLayout.NORTH); } private void addTable() { scrollPane = new JScrollPane(createTable()); add(scrollPane, BorderLayout.CENTER); } private JTable createTable() { Object[][] cellData = { { "1-1", "1-2","1-3" }, { "2-1", "2-2", "2-3" }, { "3-1", "3-2", "3-3" } }; String[] columnNames = { "column1", "column2", "column3" }; table = new JTable(cellData, columnNames); return table; } private void setWaitCursor() { Container container = getContentPane(); setWaitCursor(container); } private void setWaitCursor(Container container) { for(int iCount = 0; iCount < container.getComponentCount(); iCount++) { Component child = (Component) container.getComponent(iCount); if(child instanceof Container) { setWaitCursor((Container) child); } else { child.setCursor(new Cursor(Cursor.WAIT_CURSOR)); } } container.setCursor(new Cursor(Cursor.WAIT_CURSOR)); } private void setDefaultCursor() { Container container = getContentPane(); setDefaultCursor(container); } private void setDefaultCursor(Container container) { for(int iCount = 0; iCount < container.getComponentCount(); iCount++) { Component child = (Component) container.getComponent(iCount); if(child instanceof Container) { setDefaultCursor((Container) child); } else { child.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } container.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } public static void main(String[] argv) throws Exception { ColumnResizeIconTest test = new ColumnResizeIconTest(); test.setVisible(true); } } 

单击按钮几次,然后尝试调整表格列的大小。 光标停留在默认光标上。

正如我在评论中已经提到的那样:重新设置游标并不是完全无关紧要,甚至不是单个组件:-)基本问题(在等待的递归游标设置中)假设所有组件都有默认值光标。

正如您在表头上看到的那样,该假设不正确:在该组件上,“default”是defaultCursor或resizeCursor,具体取决于鼠标位置。 此外,内部光标切换不是很聪明:它不检查状态(从我的头顶,不久前被这个事实击中:-)

不完全确定你想达到什么,所以没有具体的解决方案,除了完全放弃递归设置,它太难以正确。 选项可能是

  • 使glassPane(框架的rootpane)可见并在其上设置waitCursor
  • 在较小的区域上使用JLayer(jdk7)或JXLayer (jdk6)并在其上设置waitCursor
  • 使用较少侵入性的可视化,fi JProgressBar或JXBusyLabel( 在SwingX项目中 )某处

附录 (适用于@mKorbel 🙂

这个问题很容易重现,只需对OPs SSCCE稍作修改(多亏了!):如下所示更改addButton方法,然后单击按钮,在显示等待光标时,将鼠标移动到标题中,然后转到另一列(跨列边框)。 多次这样做会导致标题上出现不可预测的游标……

 private void addButton() { button = new JButton("Click Me"); final ActionListener off = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setDefaultCursor(); button.setEnabled(true); } }; button.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent ae) { setWaitCursor(); button.setEnabled(false); Timer timer = new Timer(2000, off); timer.setRepeats(false); timer.start(); } }); add(button, BorderLayout.NORTH); } 

1)您有重定向代码

 for(int i=0; i<2000; i++) { System.out.print(i); } 

到BackGround Task,你可以实现javax.swing.Timer , SwingWorke r,或者在Runnable#Thread中包装这些代码行,例如这里

2)你必须在Error/Exception上恢复Cursor ,这可能是为什么没有更改Cursor的原因