2016-10-07 96 views
1

我的主课是一个包含图形组件的窗口,其中包括JTableJTable + JPopupMenu + ActionListener =噩梦

我创建了一个公共类ContextMenu,这是一个JPopupMenu的自定义实现,并包含多个JMenuItem

我在我的JTable上注册了一个mouseListener,在检测到右键单击时显示ContextMenu的实例。

问题如下:“如何根据所选的JMenuItem将选定的行传递给不同的功能?”

显而易见的答案是在我的JMenuItem上设置ActionListener,但请记住JTableJPopupMenu处于不同的类/对象。

一些代码snipet胜过千言万语。

public class Tab implements ITab { 
private ContextMenu contextMenu; 
private JTable table; 
private List<SomeObject> toProcess; 
--- code -- 
private JScrollPane drawScrollTable() { 
     Object columns[] = { 
      "something", 
      "somethingElse" 
     }; 
     Object rows[][] = {}; 
     table = new JTable(new DefaultTableModel(rows, columns)); 
     JScrollPane scrollPane = new JScrollPane(table); 

     table.setSelectionForeground(Color.BLACK); 
     table.addMouseListener(new MouseAdapter() {   
      @Override 
      public void mouseReleased(MouseEvent e) { 
       int selectedRow = table.rowAtPoint(e.getPoint()); 

       if (selectedRow >= 0 && selectedRow < table.getRowCount()) { 
        if (!table.getSelectionModel().isSelectedIndex(selectedRow)) { 
         table.setRowSelectionInterval(selectedRow, selectedRow); 
        } 
       } 

       if (e.isPopupTrigger() && e.getComponent() instanceof JTable) { 
        this.show(e); 
       } 
      } 

      private void show(MouseEvent e){ 
       contextMenu.show(e.getComponent(), e.getX(), e.getY()); 
      } 
     }); 

     return scrollPane; 
    } 
-- code -- 
} 

public class ContextMenu extends JPopupMenu { 
    JMenuItem item; 

    public ContextMenu(IBurpExtenderCallbacks callbacks){ 
     this.item= new JMenuItem("item"); 

     this.item(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) {  
       // Do action involving the selected row, even better if possible action involving the value hold in the column 0 of the selected row and the toProcess private field 
      } 
     }); 

     add(item); 
    } 
} 

我不知道我问的是否可能。

+0

远远高于张贴代码片段更好 - 创建和发布一个有效的[MCVE],这是一个** **小编译和执行的程序为我们详细的展示您的* *的问题。如果你能做到这一点,这将大大提高你得到一个体面的答案的机会。请注意,所有代码和通信都应在您的原始问题中完成,而不是在链接中完成。 –

回答

1

MouseListener应收集所有相关信息,为您ContextMenu,在运输包装它(内部私有?)并在实际输入上下文菜单之前传递此信息。

table.addMouseListener(new MouseAdapter() {   
     @Override 
     public void mouseReleased(MouseEvent e) { 
      int selectedRow = table.rowAtPoint(e.getPoint()); 

      if (selectedRow >= 0 && selectedRow < table.getRowCount()) { 
       if (!table.getSelectionModel().isSelectedIndex(selectedRow)) { 
        table.setRowSelectionInterval(selectedRow, selectedRow); 
       } 
      } 

      if (e.isPopupTrigger() && e.getComponent() instanceof JTable) { 
       this.show(e); 
      } 
     } 

     private void show(MouseEvent e){ 
      int clickedRow=table.rowAtPoint(e.getPoint()); 
      int clickedCol=table.columnAtPoint(e.getPoint()); 
      Object data=table.getValueAt(row, i); 

      DataClickedOnTable transportMeThere=new DataClickedOnTable(
       table, data, clickedRow, clickedColumn 
      ); 
      contextMenu.setDataFromTable(transportMeThere); 
      contextMenu.show(e.getComponent(), e.getX(), e.getY()); 
     } 
    }); 
    ///.... 
    ///... 


// Just an example of structure transporting the data 
// Add whatever data members are relevant 
private /* inner */ class DataClickedOnTable { 
    public TestTable source; 
    public Object data; 
    public int row; 
    public int column; 

    public DataClickedOnTable(
    TestTable source, Object data, int row, int col 
    ) { 
    this.source=source; 
    this.data=data; 
    this.col=col; 
    this.row=row; 
    } 
} 
public class ContextMenu extends JPopupMenu { 
    JMenuItem item1; 
    JMenuItem item2; 

    Object dataFromTable; // make it an Integer 

    public ContextMenu(IBurpExtenderCallbacks callbacks){ 
     this.item1 = new JMenuItem("item"); 
     this.item2 = new JMenuItem("item"); 

     this.item1(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) {  
       // You already have the relevant data in the dataFromTable 
       // Do want you need in this context 
      } 
     }); 
     this.item2(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) {  
       // You already have the relevant data in the dataFromTable 
       // Do want you need to do in this context 
      } 
     }); 

     add(item1); 
     add(item2); 
    } 

    void setDataFromTable(DataClickedOnTable data) { 
     this.dataFromTable=data; 
     // filter possible actions based on the received data - some 
     // actions are possible, some won't. 
     // Example: 
     this.item1.setEnabled(null!=data && (data.row % 2)==0); 
     this.item2.setEnabled(
      null!=data 
     && ((data.row % 2)==1 || data.data instanceof Number) 
    ); 

    } 
} 
+1

非常感谢这个解决方案,我认为它可以解决我的问题,并让我继续开发我的项目。但是,我不明白为什么'DataClickedOnTable'应该是一个私有的内部类。我的'Tab'公共类的内部类或我的'ContextMenu'公共类的内部类? –

+0

@ AresS31“为什么DataClickedOnTable应该是私人内部类。”只是一个建议,不是强制性的。但是因为它只是为了在你的MouseListener和ContextMenu之间传输数据(它应该是支持你的表格的框架的内部类),所以不要让其他代码不能访问它...... ummm。 .. 需要知道。 –

+1

好吧,我看到我的ContextMenu不是一个内部类,我将它作为一个公共类,这就是为什么我问这个问题,因为当我将它设置为私有内部时,ContextMenu无法访问它。我只是把所有的东西都做成公开课。一旦项目结束,我会清理它。再次感谢! –

1

脏道:通过参考。
清洁方式:通过MCV

构建程序

我的肮脏的方式Minimal, Complete, and Verifiable example

import java.awt.BorderLayout; 
import java.awt.event.*; 

import javax.swing.*; 
import javax.swing.table.DefaultTableModel; 

public class TableTest extends JPanel { 
    private TableClass tableClass = new TableClass(); 

    public TableTest() { 
     setLayout(new BorderLayout()); 
     add(tableClass); 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("TableTest"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new TableTest()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

class ContextMenu extends JPopupMenu { 
    private JMenuItem item; 
    private TableClass tableClass; // dirty direct reference ***** 

    public ContextMenu(TableClass tableClass){ 
     this.tableClass = tableClass; 
     this.item= new JMenuItem("item"); 

     this.item.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) {  
       int row = tableClass.getSelectedRow(); 
       JTable table = tableClass.getTable(); 
       System.out.println("row: " + row); 
       StringBuilder sb = new StringBuilder("Data: "); 
       for (int i = 0; i < table.getColumnCount(); i++) { 
        sb.append(table.getValueAt(row, i)); 
        if (i != table.getColumnCount() - 1) { 
         sb.append(", "); 
        } 
       } 
       System.out.println(sb); 
      } 
     }); 

     add(item); 
    } 
} 

class TableClass extends JPanel { 
    // ***** passing **this** into the ContextMenu class 
    private ContextMenu contextMenu = new ContextMenu(this); 
    private static final Integer[][] DATA = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; 
    private static final String[] COLUMN_NAMES = {"A", "B", "C"}; 
    private DefaultTableModel model = new DefaultTableModel(DATA, COLUMN_NAMES); 
    private JTable table = new JTable(model); 

    public TableClass() { 
     table.addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseReleased(MouseEvent e) { 
       int selectedRow = table.rowAtPoint(e.getPoint()); 
       if (selectedRow >= 0 && selectedRow < table.getRowCount()) { 
        if (!table.getSelectionModel().isSelectedIndex(selectedRow)) { 
         table.setRowSelectionInterval(selectedRow, selectedRow); 
        } 
       } 
       if (e.isPopupTrigger() && e.getComponent() instanceof JTable) { 
        showPopUp(e); 
       } 
      } 

      private void showPopUp(MouseEvent e) { 
       contextMenu.show(e.getComponent(), e.getX(), e.getY());     
      } 
     }); 

     setLayout(new BorderLayout()); 
     add(new JScrollPane(table)); 
    } 

    public int getSelectedRow() { 
     return table.getSelectedRow(); 
    } 

    public int getSelectedColumn() { 
     return table.getSelectedColumn(); 
    } 

    public JTable getTable() { 
     return table; 
    } 
}