2015-08-13 1 views
0

Когда вы нажимаете на ячейку JTable, строка становится «выбрана», я хочу, чтобы при щелчке по чему-либо еще она не была выбрана.Потерять ячейку JTable

Я собираюсь сделать это с помощью прослушивателя мыши на столе, но не знаю, как распознать (не нажимайте на таблицу). Есть идеи?

Это то, что я пытаюсь:

jTable.addMouseListener(new MouseAdapter(){ 
       @Override 
       public void mouseClicked(MouseEvent e){ 
        System.out.println("click");}}); 

Но это только печатает нажмите, когда я нажимаю в первой колонке и, конечно, не тогда, когда я нажимаю на то, что это не таблица.

Когда я узнаю, что событие я назвал бы этот метод:

public void loseCellFocus() 
{ 
    jTable.getCellEditor().stopCellEditing(); 
    jTable.clearSelection(); 
} 
+0

Используйте 'FocusListener', прикрепленный к' JTable' – MadProgrammer

ответ

1

Использовать FocusListener прикрепленные к JTable, это скажет вам, когда фокус перемещается от стола.

См How to Write a Focus Listener для более подробной информации

Например ...

table.addFocusListener(new FocusAdapter() { 
     @Override 
     public void focusLost(FocusEvent e) { 
      loseCellFocus(); 
     }   
    }); 

Это, конечно, работать только когда фокус клавиатуры передается новый компонент, способный для приема фокус клавиатуры

Это вызывает вызов метода loseCellFocus() сразу, как только я нажимаю на любую ячейку, это называется

Вы можете использовать JTable#setSurrendersFocusOnKeystroke или проверить, если компонент, который фокус был передан ребенок в JTable

К примеру ...

table.addFocusListener(new FocusAdapter() { 
    @Override 
    public void focusLost(FocusEvent e) { 
     if (e.getOppositeComponent().getParent() != table) { 
      loseCellFocus(); 
     } 
    } 
}); 

Runnable Пример ...

Хорошо, это стало беспорядочным. Мало того, что я должен добавить FocusListener к JTable, но я должен был убедиться, что один был добавлен к TableCellEditor компонента: P

Это доказательство концепции только, я бы специализированные классы, которые способны либо для пропагандистские мероприятия или запуская необходимый функциональные возможности с помощью какого-то общего интерфейса

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.Container; 
import java.awt.EventQueue; 
import java.awt.event.FocusAdapter; 
import java.awt.event.FocusEvent; 
import javax.swing.DefaultCellEditor; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.JViewport; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.EmptyBorder; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellEditor; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setLayout(new BorderLayout()); 

      JTable table = new JTable(new DefaultTableModel(10, 10)); 

      JTextField editorField = new JTextField(10); 
      editorField.setBorder(new EmptyBorder(1, 1, 1, 1)); 
      editorField.addFocusListener(new FocusAdapter() { 
       @Override 
       public void focusLost(FocusEvent e) { 
        TableCellEditor cellEditor = table.getCellEditor(); 
        if (cellEditor != null) { 
         if (!cellEditor.stopCellEditing()) { 
          cellEditor.cancelCellEditing(); 
         } 
        } 

        Component gotFocus = e.getOppositeComponent(); 
        if (!gotFocus.equals(table)) { 
         table.clearSelection(); 
        } 
       } 
      }); 
      DefaultCellEditor editor = new DefaultCellEditor(editorField); 
      table.setDefaultEditor(Object.class, editor); 

      add(new JScrollPane(table)); 
      table.addFocusListener(new FocusAdapter() { 

       @Override 
       public void focusLost(FocusEvent e) { 
        Component gotFocus = e.getOppositeComponent(); 
        if (!gotFocus.getParent().equals(table)) { 
         TableCellEditor cellEditor = table.getCellEditor(); 
         if (cellEditor != null) { 
          if (!cellEditor.stopCellEditing()) { 
           cellEditor.cancelCellEditing(); 
          } 
         } 
         table.clearSelection(); 
        } 
       } 

      }); 

      JTextField field = new JTextField(10); 
      add(field, BorderLayout.SOUTH); 
     } 

    } 

} 

AWTEventListener Пример ...

Ладно, на самом деле не хочет идти по этому пути, как она заканчивается в беспорядке перекрестных условий, но , В основном это контролирует ВСЕ MouseEvent и FocusEvent s, он делает некоторые обратные результаты для проверки действительных условий (так как мы должны убедиться, что не только если JTable является частью события, но и если редактор является частью события), а на основе по этим результатам останавливает редактирование ячеек и очищает выбор ...

import java.awt.AWTEvent; 
import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.KeyboardFocusManager; 
import java.awt.Toolkit; 
import java.awt.event.AWTEventListener; 
import java.awt.event.FocusEvent; 
import java.awt.event.MouseEvent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JTextField; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.EmptyBorder; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellEditor; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      JTable table = new JTable(new DefaultTableModel(5, 5)); 
      setLayout(new GridBagLayout()); 
      setBorder(new EmptyBorder(20, 20, 20, 20)); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridwidth = GridBagConstraints.REMAINDER; 
      add(new JScrollPane(table), gbc); 
      add(new JTextField(10), gbc); 

      Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { 
       @Override 
       public void eventDispatched(AWTEvent event) { 
        if (event instanceof FocusEvent) { 
         FocusEvent focusEvent = (FocusEvent) event; 
         if (focusEvent.getID() == FocusEvent.FOCUS_LOST) { 
          Component focusTo = focusEvent.getOppositeComponent(); 
          Component focusFrom = focusEvent.getComponent(); 

          JTable table = getTableFrom(focusFrom); 
          if (focusTo == null || !focusTo.getParent().equals(table)) { 

           stopCellEditing(table); 
           clearSelection(table); 

          } 
         } 
        } else if (event instanceof MouseEvent) { 
         MouseEvent mouseEvent = (MouseEvent) event; 
         if (mouseEvent.getID() == MouseEvent.MOUSE_CLICKED) { 
          Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 
          JTable table = getTableFrom(focusOwner); 
          System.out.println("  table = " + table); 
          System.out.println("focusOwner = " + focusOwner); 
//       if ((table != null && mouseEvent.getComponent() != table) || (focusOwner != null && !focusOwner.getParent().equals(table))) { 
          if ((table != null && mouseEvent.getComponent() != table) && (focusOwner != null && !focusOwner.getParent().equals(table))) { 
           stopCellEditing(table); 
           clearSelection(table); 
          } 
         } 
        } 
       } 

       protected JTable getTableFrom(Component component) { 
        JTable table = null; 
        if (component instanceof JTable) { 
         table = (JTable) component; 
        } else if (component != null && component.getParent() instanceof JTable) { 
         table = (JTable) component.getParent(); 
        } 
        return table; 
       } 

       protected void clearSelection(JTable table) { 
        if (table != null) { 
         table.clearSelection(); 
        } 
       } 

       protected void stopCellEditing(JTable table) { 

        if (table != null) { 
         TableCellEditor cellEditor = table.getCellEditor(); 
         if (cellEditor != null) { 
          if (!cellEditor.stopCellEditing()) { 
           cellEditor.cancelCellEditing(); 
          } 
         } 
        } 
       } 
      }, AWTEvent.FOCUS_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK); 
     } 

    } 

} 

Этот пример в основном работает для ВСЕХ JTable с (когда AWTEventListener зарегистрирован), но вы можете настроить его, чтобы контролировать одну таблицу, изменяя некоторые из источников событий и сравнивая их друг с другом: P

+0

Звучит идеально! Попытка теперь – Aequitas

+0

Это вызывает вызов метода 'loseCellFocus()' сразу, как только я нажимаю на любую ячейку, это называется – Aequitas

+0

. Вы можете использовать ['JTable # setSurrendersFocusOnKeystroke'] (http://docs.oracle.com/) javase/7/docs/api/javax/swing/JTable.html # setSurrendersFocusOnKeystroke (boolean)) или проверьте, является ли компонент, на который был направлен объект, дочерний элемент 'JTable' – MadProgrammer

0

Я сделал это когда-нибудь с JTree. Диспетчер фокуса и т. Д. Не работал. Наконец, решение, которое я использовал, - использовать Toolkit.getDefaultToolkit().addAWTEventListener и захватывать события клавиатуры и мыши. Посмотрите на JTree в иерархии компонентов события и вызовите метод удаления выделения, если элемент не принадлежит дереву.

Я могу найти код, если вам нужно.

Редактировать

AWTEventListener в принятом ответ является немного более сложным, чем это необходимо.

 final AWTEventListener focusTracker = new AWTEventListener() { 
      @Override public void eventDispatched(AWTEvent event) { 
       if (event.getID() != MouseEvent.MOUSE_CLICKED && event.getID() != KeyEvent.KEY_PRESSED) 
        return; 
       if (!isPartOfTable((Component) event.getSource())) { 
        if (table.isEditing()) { 
         TableCellEditor cellEditor = table.getCellEditor(); 
         cellEditor.cancelCellEditing(); 
        } 
        table.clearSelection(); 
        table.dispatchEvent(new FocusEvent(table, FocusEvent.FOCUS_LOST)); 
       } 
      } 

      protected boolean isPartOfTable(Component component) { 
       while (component != null && component != table) 
        component = component.getParent(); 
       return component == table; 
      } 

     }; 
     Toolkit.getDefaultToolkit().addAWTEventListener(focusTracker, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK); 

Примечание: вам необходимо удалить слушателя, когда рамка закрыта. Мне не понравилось, что ячейка таблицы все еще подсвечивается при нажатии на нее. Поэтому я отправляю фокус, потерянный в таблицу.