JTable не будет слушать Doubleclicks

Я пытаюсь реализовать функцию отмены (и повтора) для редактируемого JTable с компонентами по умолчанию. У JTable есть дополнительный класс для указания его свойств, который называется SpecifiedJTable.

Для этого я хотел захватить момент двойного щелчка по ячейке (то есть момент, когда ячейка выбрана/помечена для редактирования), чтобы поместить информацию в ячейке и ее координаты в стек.

Это должен сделать MouseListener ...по крайней мере, это была моя идея. Я пробовал так (стоя в конструкторе моего SpecifiedJTable класса)

class JTableSpecified extends JTable {
    private static final long serialVersionUID = 1L;
    private int c; // the currently selected column
    private int r; // the currently selected row

    public JTableSpecified(String[][] obj, String[] columnNames) {
        super(obj, columnNames); // constructs the real table
        // makes that you can only select one row at a time
        this.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        // makes that columns are not squeezed
        this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        // forbids to rearrange the columns
        getTableHeader().setReorderingAllowed(false);
        // adds action listener
        this.getModel().addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                r = getSelectedRow();
                c = getSelectedColumn();
                // get the String at row r and column c
                String s = (String) getValueAt(r, c);
                if (jobDisplayed) jobSwitch(c, s);
                else resSwitch(c, s);
            }
        });    
        this.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    System.out.println("test");
                }
            }
        });
    }
} 

но почему-то clickCounter не хочет достигать ничего, что выше 1.

Рад любому ответу и помощи. Спасибо.


person user1466944    schedule 19.06.2012    source источник
comment
В общем, должно работать. Я использую что-то подобное в своем собственном коде. Возможно, в вашей таблице зарегистрирован какой-то другой прослушиватель мыши, который использует некоторые события мыши и предотвращает их распространение на ваш прослушиватель.   -  person Enwired    schedule 19.06.2012
comment
Можете ли вы исправить код? Как бы это не скомпилировалось. Также, пожалуйста, вставьте более связанный код, предпочтительно SSCCE.   -  person Boro    schedule 19.06.2012
comment
в первую очередь благодаря вашим ответам. расширенный код теперь в вопросе. @user1442870 user1442870 не могли бы вы представить, какой это и что еще более важно: есть ли у вас что-то на уме, чтобы другие слушатели не потребляли события мыши? по крайней мере, tablemodelListener не является проблемой. я попытался деактивировать его, и mouseListener в конце концов не отреагировал.   -  person user1466944    schedule 19.06.2012
comment
расширенный код.. ..не SSCCE. Пожалуйста, ознакомьтесь с содержанием предлагаемых ссылок.   -  person Andrew Thompson    schedule 20.06.2012
comment
Хотя я использую аналогичный прослушиватель двойного щелчка мыши на некоторых моих собственных JTables, я понял, что делаю это только с нередактируемыми таблицами. Когда таблица доступна для редактирования, пользовательский интерфейс таблицы будет использовать некоторые из этих событий мыши.   -  person Enwired    schedule 20.06.2012


Ответы (4)


Проблема, с которой вы столкнулись, связана с использованием mouseClicked(), а не с использованием mousePressed(). В этом случае увеличить счетчик кликов оказывается очень сложно, но все же возможно. Мне потребовалось много кликов, а также движений мыши, чтобы увеличить счетчик кликов больше 1. Вы можете попробовать это сами, в своем коде. Чтобы получить счетчик больше 1, вам нужно сойти с ума от мыши, быстро нажимая и отпуская, одновременно перемещая мышь от ячейки к ячейке (или, может быть, я просто удачно щелкал между ячейками?).

Как вы можете видеть в этом полностью рабочем примере, сделанном из вашего кода, два нажатия мыши с использованием метода mousePressed() распознаются просто отлично.

public class JTableSpecified extends JTable {
    private static final long serialVersionUID = 1L;

    public JTableSpecified(String[][] obj, String[] columnNames) {
        super(obj, columnNames); // constructs the real table
        // makes that you can only select one row at a time
        this.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        // makes that columns are not squeezed
        this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        // forbids to rearrange the columns
        getTableHeader().setReorderingAllowed(false);
        // adds action listener
        this.getModel().addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
            }
       });        
        this.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    System.out.println("test");
                }
                System.out.println("e.getClickCount() = " + e.getClickCount());
            }
        });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JPanel panel = new JPanel();
                panel.add(new JTableSpecified(new String[][]{{"oi", "oi2"}, {"oi3", "oi4"}}, new String[]{"Col1", "Col2"}));
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setContentPane(panel);
                f.pack();
                f.setVisible(true);
            }
        });
    }
}

Вывод. Может быть, вы действительно хотите использовать метод mousePressed()?

person Boro    schedule 20.06.2012
comment
да спасибо большое Боро. =) это действительно работает с mousePressed(). Довольно забавно видеть, что это было такое простое решение, которое я искал все время. После нескольких тестов он показал идеальный результат для моего приложения без каких-либо нежелательных событий. большое тебе спасибо. - person user1466944; 20.06.2012

Этот ответ расширяет ответ Боро.
Чтобы поймать каждый случай, который позволяет пользователю редактировать таблицу, мне также нужно будет добавить KeyListener для F2 (который имеет тот же эффект, что и двойной щелчок по ячейке) и отключить автоматический редактирование ячейки нажатием любой клавиши.
Я просто добавил его в конструктор сразу за mouseListener (см. выше)

// запрещает редактирование нажатием клавиши
this.putClientProperty(JTable.autoStartsEdit, Boolean.FALSE);

// keyListener, реагирующий на нажатие F2 (код клавиши 113)
this.addKeyListener(new KeyAdapter(){

public void keyPressed(KeyEvent e) {

if (e.getKeyCode() == 113) System.out.println(test);
}
});

person user1466944    schedule 20.06.2012
comment
+1 да мне нравится. Мне всегда нравится, когда люди разрешают редактирование с помощью F2 — «стандартной» клавиши для редактирования. - person Boro; 21.06.2012

BasicTableUI реагирует на двойной щелчок, переходя в режим редактирования ячейки, по которой был сделан двойной щелчок. Он выполняет множество сложных действий, часть из которых включает создание JTextField (или другого компонента), позволяющего редактировать данные, а затем предотвращение дальнейшего распространения события щелчка мыши.

Если ваша таблица или эта ячейка таблицы недоступны для редактирования, вы можете легко фиксировать события мыши с количеством кликов 2, 3, 4, .... Но поскольку вы хотите, чтобы ваша таблица была редактируемой, вам нужен другой подход.

Одной из идей было бы переопределить JTable.editCellAt()

Лучше забыть о том, чтобы возиться с JTable, и вместо этого прослушивать изменения данных в самой модели таблицы.

person Enwired    schedule 20.06.2012

ошибка в коде заключается в том, что метод mouseClicked вызывается, как только происходит первый щелчок. когда происходит двойной щелчок, метод mouseClicked вызывается снова. вы можете поместить статическую переменную (или переменную класса) для более раннего события щелчка, сохраняющего время (используя метод e.getWhen()). Проверьте разницу во времени и, если она достаточно мала, выполните свои действия (я бы предложил вызвать метод doubleClick).

вам, возможно, придется реализовать прослушиватель мыши в вашем классе JTableSpecified, поскольку статическая переменная может не быть помещена в ваш существующий код.

person vedant    schedule 20.06.2012
comment
хм, я думаю, это не настоящее решение моей проблемы: / потому что, когда вы реализуете это, вы можете щелкнуть по двум разным ячейкам, и он также сработает, потому что счетчик равен 2. может быть, я мог бы поместить этот прослушиватель в каждую ячейку... есть способ сделать это? или, может быть, есть еще лучший способ без прослушивателя мыши определить момент выбора. - person user1466944; 20.06.2012
comment
да, вы можете проверить позицию mouseEvent методом getPosition. Я этого не требовал, потому что, если разница во времени составляет всего 500 мс, невозможно щелкнуть, переместить и снова щелкнуть все за 500 мс. Но если вы хотите, вы можете сделать 2 переменные и проверить оба условия. В конце концов, двойной щелчок определяется как два быстрых последовательных щелчка без перемещения мыши. - person vedant; 21.06.2012