2016-10-26 6 views
1

Я добавил JPopupMenu в JTable с setComponentPopupMenu. Проблема заключается в том, что, хотя открыт/виден, когда я щелкнул левой кнопкой мыши по строке вне всплывающего меню, меню закрывается, но строка не выбрана, поэтому я должен щелкнуть ее снова, чтобы выделить ее. Есть ли способ исправить это?Принудительный выбор строки JTable, если щелкнуть снаружи видимым JPopupMenu

EDIT

Я добавил примеры кода.

Кстати, это поведение происходит только в Windows LaF. Я только что протестировал его, и похоже, что Java LaF по умолчанию позволяет выбирать строку слева при открытии JPopupMenu.

import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Point; 

import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JMenuItem; 
import javax.swing.JPanel; 
import javax.swing.JPopupMenu; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.PopupMenuEvent; 
import javax.swing.event.PopupMenuListener; 

public class TableSTACK { 

    private static void createAndShowGUI() { 

     String[] headers = {"Column 1", "Column 2"}; 

     Object[][] data = { {"Row", "1"}, {"Row", "2"}, 
       {"Row", "3"}, {"Row", "4"}, {"Row", "5"}, 
       {"Row", "6"}, {"Row", "7"}, {"Row", "8"}, }; 

     JTable table = new JTable(data, headers); 
     table.setFillsViewportHeight(true); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize());   

     final JMenuItem item1 = new JMenuItem(); 
     item1.setText("Menu Item 1");  
     final JMenuItem item2 = new JMenuItem(); 
     item2.setText("Menu Item 2"); 
     final JMenuItem item3 = new JMenuItem(); 
     item3.setText("Menu Item 3"); 

     final JPopupMenu popupMenu = new JPopupMenu(); 
     popupMenu.add(item1); 
     popupMenu.addSeparator(); 
     popupMenu.add(item2); 
     popupMenu.add(item3); 
     table.setComponentPopupMenu(popupMenu); 

     popupMenu.addPopupMenuListener(new PopupMenuListener() { 
      @Override 
      public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 
       SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         // force selection of row upon right-click (it works) 
         int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table)); 
         if (rowAtPoint > -1) { 
          table.setRowSelectionInterval(rowAtPoint, rowAtPoint); 
         } 
        } 
       }); 
      } 

      @Override 
      public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 
       SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         // force row selection upon exiting popup menu 
         // does not work; rowAtPoint always returns -1 
         int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(null, new Point(0, 0), table)); 
         //int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table)); 
         if (rowAtPoint > -1) { 
          table.setRowSelectionInterval(rowAtPoint, rowAtPoint); 
         } 
        } 
       }); 
      } 

      @Override 
      public void popupMenuCanceled(PopupMenuEvent e) { 
       // TODO 
      } 
     }); 


     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.anchor = GridBagConstraints.NORTHWEST; 
     gbc.gridy = 0; 
     gbc.weightx = 1.0; 
     gbc.weighty = 1.0; 
     gbc.fill = GridBagConstraints.BOTH; 
     gbc.gridx = 0; 

     JScrollPane scrollPane = new JScrollPane(table); 

     JPanel contentPane = new JPanel(); 
     contentPane.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); 
     contentPane.setLayout(new GridBagLayout()); 
     contentPane.add(scrollPane, gbc); 

     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setContentPane(contentPane); 
     frame.pack(); 
     frame.setMinimumSize(new Dimension(500, 400)); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (InstantiationException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (IllegalAccessException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (UnsupportedLookAndFeelException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       createAndShowGUI(); 
      } 
     }); 
    } 
} 
+0

Используйте редактор ячеек, например ['TablePopupEditor'] (http://stackoverflow.com/a/3591230/230513). Если это не дубликат, отредактируйте свой вопрос, включив в него [mcve], который показывает ваш пересмотренный подход. – trashgod

+0

Это было первоначально закрыто как дубликат: http://stackoverflow.com/questions/3590897/jtable-design-to-synchronize-with-back-end-data-structure. Я не думаю, что этот вопрос касается всплывающего редактора. Речь идет об использовании «JPopupMenu» и нажатии на таблицу, когда меню открыто. Я снова открыл вопрос. – camickr

+0

Я отредактировал мой вопрос. – AndroidX

ответ

2

Это вопрос LAF.

Это работает для меня, когда я использую LAF по умолчанию, но не работает, когда я использую платформу LAF, для меня это Windows.

Потенциальным решением для Windows является использование MouseListener для выбора строки. Обратите внимание, что код добавляется к событию mouseReleased. По какой-то причине таблица не получает событие mousePressed, хотя в соответствии с AWTEventListener таблица является источником события mousePressed.

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class TablePopupListener extends JPanel 
{ 
    public TablePopupListener() 
    { 
     JTable table = new JTable(10, 5); 
     add(new JScrollPane(table)); 

     JPopupMenu popup = new JPopupMenu(); 
     popup.add(new JMenuItem("Do Something1")); 
     popup.add(new JMenuItem("Do Something2")); 

     table.setComponentPopupMenu(popup); 

     table.addMouseListener(new MouseAdapter() 
     { 
      public void mousePressed(MouseEvent e) 
      { 
       System.out.println("Pressed JTable"); 
      } 

      public void mouseReleased(MouseEvent e) 
      { 
       System.out.println("Released JTable"); 

       int row = table.rowAtPoint(e.getPoint()); 

       if (row != -1 
       && !table.isRowSelected(row)) 
       { 
        table.setRowSelectionInterval(row, row); 
       } 
      } 
     }); 
    } 

    private static void createAndShowGUI() 
    { 
     try 
     { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } 
     catch (Exception ex) { System.out.println(ex); } 

     JFrame frame = new JFrame("TablePopupListener"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new TablePopupListener()); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 

     Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() 
     { 
      public void eventDispatched(AWTEvent e) 
      { 
       String event = null; 

       switch (e.getID()) 
       { 
        case MouseEvent.MOUSE_PRESSED: event = "Pressed: " ; break; 
        case MouseEvent.MOUSE_RELEASED: event = "Released: " ; break; 
        case MouseEvent.MOUSE_ENTERED: event = "Entered: " ; break; 
        case MouseEvent.MOUSE_EXITED: event = "Exited: " ; break; 
        default: event = null; break; 
       } 

       if (event != null) 
       { 
        System.out.println(); 
        System.out.println(event + e.getSource().getClass()); 
       } 
      } 
     }, AWTEvent.MOUSE_EVENT_MASK); 
    } 

    public static void main(String[] args) 
    { 
     EventQueue.invokeLater(() -> createAndShowGUI()); 
/* 
     EventQueue.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       createAndShowGUI(); 
      } 
     }); 
*/ 
    } 
} 
+0

Так что, я думаю, что я буду держать 'PopupMenuListener' для принудительного выбора строки строки при щелчке правой кнопкой мыши, и я добавлю' MouseListener', чтобы принудительно выбрать строку, щелкнув левой кнопкой мыши, когда будет вид 'JPopupMenu'. Слишком плохо, что это должен быть сложный ... Спасибо – AndroidX