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

时间:2012-01-12 05:42:28

标签: java swing icons cursor

我的应用程序中有JTable可调整大小的标题列。通常,当我将光标移动到表头以进行调整大小时,光标图标会更改为调整大小箭头,例如< - >。

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

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

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

这可以被视为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);
}
}

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

2 个答案:

答案 0 :(得分:8)

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

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

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

  • 使glassPane(框架的rootpane)可见并在其上设置waitCursor
  • 在较小的区域使用JLayer(jdk7)或JXLayer(jdk6)并在其上设置waitCursor
  • 使用较少侵入性的可视化,f.i。 JProgressBar或JXBusyLabel(in the SwingX project)某处

附录(适用于@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 :(得分:1)

1)您有重定向代码

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

到BackGround任务,您可以实现javax.swing.TimerSwingWorke r,或将这些代码行包​​装在Runnable#Thread中,例如here

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