Java Swing JTable;右键菜单(如何使其“选择”即高亮行)

34

简短说明:我需要一个“右键单击事件”来高亮显示单元格行。

我在 Java Swing(Netbeans Matisse)中使用 ScrollPane 中的 JTable。我在 JTable 上有一个 MouseClicked 事件监听器,它执行以下操作:

if (evt.getButton() == java.awt.event.MouseEvent.BUTTON3) {
          System.out.println("Right Click");
          JPopUpMenu.show(myJTable, evt.getX(), evt.getY())
}

问题在于...每当我右键单击JTable时,行都不会被突出显示(我已将选择设置为仅限行)。我查找了几个setSelected()函数,但没有找到合适的。默认情况下,左键单击会自动突出显示该行。如何设置右键单击的方式?

3个回答

90

像这样:

table.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseReleased(MouseEvent e) {
        int r = table.rowAtPoint(e.getPoint());
        if (r >= 0 && r < table.getRowCount()) {
            table.setRowSelectionInterval(r, r);
        } else {
            table.clearSelection();
        }

        int rowindex = table.getSelectedRow();
        if (rowindex < 0)
            return;
        if (e.isPopupTrigger() && e.getComponent() instanceof JTable ) {
            JPopupMenu popup = createYourPopUp();
            popup.show(e.getComponent(), e.getX(), e.getY());
        }
    }
});

......


1
就是这样:]... mouseReleased() 的前半部分是我需要的。将被投票并接受为答案。谢谢,你真棒! - user402642
6
好的回答。一个细节是:在某些平台上(比如Mac OS X),弹出菜单是通过mousePressed而不是mouseReleased触发的,所以如果你使用这段代码,在Mac OS X上运行你的应用程序时,弹出菜单将不会显示出来。 - gabuzo
获取rowIndex两次的目的是什么?我的意思是,rrowindex之间有什么区别? - Ad Infinitum
完美的解决方案。请记住,如果您使用此解决方案,请勿使用setComponentPopupMenu()方法。 - m4heshd
1
请看Oliver Hoffmann在2016年8月26日12:26的评论: 没有必要进行手动选择处理,JTable已经尊重SHIFT和CTRL键等。原始解决方案中唯一需要更改的是,如果已选择了焦点行,则不使用setRowSelectionInterval(),例如:if (!table.getSelectionModel().isSelectedIndex(r)) table.setRowSelectionInterval(r, r); - neflow

3

被接受的答案没有考虑像ctrlshift这样的修饰键,然而它们表明当前选择不应该被替换,而是应该被扩展。

此外,我通过检查mousePressedmouseReleased来添加多操作系统支持。

接下来,您可以找到一个完整的示例,说明如何使用ListSelectionModel调整所选行,包括MouseEvent#getModifiers检查。之后,可以打开(可选的)JPopupMenu

JPopupMenu contextMenu = new JPopupMenu();
// ...
// add elements to the popup menu
// ...

table.addMouseListener(new MouseAdapter() {
  @Override
  public void mousePressed(MouseEvent e) {
    handleRowClick(e);
    if (e.isPopupTrigger()) {
      doPop(e);
    } else {
      hidePop();
    }
  }

  @Override
  public void mouseReleased(MouseEvent e) {
    if (e.isPopupTrigger()) {
      doPop(e);
    }
  }

  private void handleRowClick(MouseEvent e) {
    ListSelectionModel selectionModel = table.getSelectionModel();
    Point contextMenuOpenedAt = e.getPoint();
    int clickedRow = table.rowAtPoint(contextMenuOpenedAt);

    if (clickedRow < 0) {
      // No row selected
      selectionModel.clearSelection();
    } else {
      // Some row selected
      if ((e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) {
        int maxSelect = selectionModel.getMaxSelectionIndex();

        if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
          // Shift + CTRL
          selectionModel.addSelectionInterval(maxSelect, clickedRow);
        } else {
          // Shift
          selectionModel.setSelectionInterval(maxSelect, clickedRow);
        }
      } else if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
        // CTRL
        selectionModel.addSelectionInterval(clickedRow, clickedRow);
      } else {
        // No modifier key pressed
        selectionModel.setSelectionInterval(clickedRow, clickedRow);
      }
    }
  }

  private void doPop(MouseEvent e) {
    if (table.getSelectedRowCount() == 0) {
      return;
    }
    contextMenu.setVisible(true);
    contextMenu.show(e.getComponent(), e.getX(), e.getY());
  }

  private void hidePop() {
    contextMenu.setVisible(false);
  }
});

2
不需要手动选择处理,JTable已经支持SHIFT和CTRL键等。原始解决方案中唯一需要更改的是,如果已经选择了焦点行,则不使用setRowSelectionInterval(),例如:if (!table.getSelectionModel().isSelectedIndex(r)) table.setRowSelectionInterval(r, r); - Oliver Hoffmann

0

您可以创建另一个MouseEvent(此示例在JTable子类中; processMouseEvent() 具有protected访问权限,否则可以使用dispatchEvent() 方法)。负责使用修饰符更新选择。

addMouseListener(new MouseAdapter() {
    @Override public void mousePressed(MouseEvent e) { checkForPopupMenu(e); }
    @Override public void mouseReleased(MouseEvent e) { checkForPopupMenu(e); }
    private void checkForPopupMenu(MouseEvent e) {
        if (e.isPopupTrigger()) {
            processMouseEvent(new MouseEvent(e.getComponent(), e.getID(), e.getWhen(), e.getModifiersEx(), e.getX(), e.getY(), 1, false, MouseEvent.BUTTON1));
            if (getSelectedRowCount() != 0)
                popup.show(e.getComponent(), e.getX(), e.getY());
        }
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接