Значок курсора не меняется после запуска метода setCursor - PullRequest
5 голосов
/ 12 января 2012

В моем приложении есть 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 ]

8 голосов
/ 12 января 2012

Как уже упоминалось в моем комментарии: переустановить / установить курсоры не совсем тривиально, даже для отдельного компонента :-) Основная проблема (при установке рекурсивного курсора на ожидание) состоит в предположении, что все компоненты do имеет курсор по умолчанию.

Как видно из заголовка таблицы, это предположение неверно: для этого компонента значением «default» является либо defaultCursor, либо resizeCursor, в зависимости от расположения мыши. Кроме того, переключение внутреннего курсора не очень разумно: оно не проверяет состояние (из-за того, что я недавно столкнулся с этим фактом: -)

Не совсем уверен, чего вы хотите достичь, поэтому не располагайте конкретным решением, кроме полного отказа от рекурсивной настройки, слишком сложно сделать правильный выбор. Варианты могут быть

  • сделать стеклянную панель (корневой панели фрейма) видимой и установить на ней waitCursor
  • используйте JLayer (jdk7) или JXLayer (jdk6) в меньшей области и установите для него waitCursor
  • используйте менее навязчивую визуализацию, например JProgressBar или JXBusyLabel ( в проекте SwingX ) где-то

Приложение (для @mKorbel: -)

проблема легко воспроизводима, с небольшими изменениями в OP 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 голос
/ 12 января 2012

1) у вас есть код перенаправления

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

на задание BackGround, вы можете реализовать javax.swing.Timer , SwingWorke r или обернутьстроки кода внутри Runnable # Thread , пример здесь

2) вам также нужно восстановить Cursor на Error/Exception, поэтому, вероятно, причина, по которой Cursor не былизменено

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...