Иногда возникает потребность в раздельной обработке одинарного и двойного клика. Например, у нас есть дерево, где каждый элемент содержит чекбокс. Мы хотим, чтобы поведение дерева было следующим: одинарный клик должен просто выделять элемент или снимать выделение, в то время как двойной клик должен обрабатываться стандартным для дерева образом.
На первый взгляд задача достаточно простая, можно сделать свой слушатель событий мыши и использовать метод getClickCount() класса MouseEvent . Однако при этом мы сталкиваемся с непреодолимой проблемой: при одинарном и двойном клике всегда будет вызываться метод mouseClicked(MouseEvent e) при том, что getClickCount() выдаст 1. Т.е. мы никак не можем сказать, в момент обработке события мыши с getClickCount() равным 1, будет ли потом вызов этого же события с getClickCount() равным 1.
Решить эту проблему можно с помощью javax.swing.Timer. Сперва несколько слов об этом классе. Этот класс служит для того, чтобы запустить одно или несколько действий после определенного интервала ожидания. Наиболее ценным свойством этого класса является то, что действия выполняются в основном потоке GUI или потоке обработки событий. Так, как класс запускает дополнительный поток, а мы работаем в потоке обработке событий, что накладывает некоторые особенности на реализацию многозадачности, нам не надо думать об этих особенностях. Т.е. нам не надо думать о специфике многозадачности в swing.
Ниже приведен код слушателя обработки событий мыши.
public class NodeMouseListener extends MouseAdapter { private JTree tree; private boolean singleClick = true; private Timer timer; private TreePath path = null;; private int row = 0; private final int delay = 170;
NodeMouseListener(JTree tree) { this.tree = tree; ActionListener al = new ActionListener(){ public void actionPerformed(ActionEvent evt) { if(singleClick){ processSingleClick(); } } }; timer = new javax.swing.Timer(delay, al); timer.setRepeats(false); } public void mouseClicked(MouseEvent e) { checkClicks(e); } private void checkClicks(MouseEvent e){ int x = e.getX(); int y = e.getY(); int row = tree.getRowForLocation(x, y); path = tree.getPathForRow(row); if(e.getClickCount() == 1){ singleClick = true; timer.start(); }else{ singleClick = false; } } private void processSingleClick(){ if(path != null){ //обрабатываем одинарный клик здесь } }
}
Этот класс надо зарегистрировать в экземпляре класса дерева, как один из слушателей событий мыши.
Если подобрать delay, то можно добиться такого поведения дерева, как требуется в задаче.
|