2016-10-26 4 views
1

setComponentPopupMenuJTableJPopupMenuを追加しました。問題は、JPopupMenuが開いている/見えているうちに、ポップアップメニューの外にある行を左クリックしたときにメニューが閉じても行が選択されていないため、再度強調表示する必要があることです。それを修正する方法はありますか?表示されているJPopupMenuの外側をクリックすると、JTableの行選択が強制的に実行されます

EDIT

私は、サンプルコードを追加しました。

ところでこの現象はWindows LaFでのみ発生します。私はちょうどそれをテストしたところで、JPopupMenuが開いている間、デフォルトのJava LaFが左クリックの行選択を許可するように見えます。

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'を残しておき、' JPopupMenu'が表示されている間は左クリックすると 'MouseListener'を追加して行の選択を強制します。あまりにもそれは複雑でなければならない悪い...ありがとう – AndroidX

関連する問題