通过鼠标右键单击使用 JPopupMenu 在 JTable 中选择行
Row Selection in JTable with JPopupMenu via Right Mouse Click
下面的代码创建了一个简单的 JFrame
,其中包括一个 JTable
和 JPopupMenu
。右键单击 select 单击的行并显示弹出窗口。
问题是:
当用户 Maximize
将 JFrame 显示到屏幕上并右键单击到最后 1-2-3-4-5 或第 6 行时,弹出窗口出现在错误的位置并且 select 由于弹出窗口出现错误的行高度对应屏幕高度。
我怎样才能做到这一点?
MCVE;
package popuptestapp;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
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;
import javax.swing.table.DefaultTableModel;
public class PopupTestApp {
public static boolean RIGHT_TO_LEFT = false;
public static void addComponentsToPane(Container pane) {
if (!(pane.getLayout() instanceof BorderLayout)) {
pane.add(new JLabel("Container doesn't use BorderLayout!"));
return;
}
if (RIGHT_TO_LEFT) {
pane.setComponentOrientation(
java.awt.ComponentOrientation.RIGHT_TO_LEFT);
}
JScrollPane jScrollPane = new JScrollPane();
JTable table = new JTable();
table.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{"", "", "", "", "", "", "", ""}
},
new String [] {
"Column1", "Column2", "Column3", "Column4", "Column5", "Column6", "Column7", "Column8"
}
) {
boolean[] canEdit = new boolean [] {
false, false, false, false, false, false, false, false
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
DefaultTableModel model1 = (DefaultTableModel) table.getModel();
model1.setRowCount(0);
//Fill the table with rows
for (Integer i = 0; i<=250; i++){
model1.addRow(new String[]{"", "", "", "", "", "", "", ""});
}
jScrollPane.setViewportView(table);
pane.add(jScrollPane, BorderLayout.PAGE_END);
//creating JPopupMenu
JPopupMenu popupForTable = new JPopupMenu();
JMenuItem menuItem1;
JMenuItem menuItem2;
JMenuItem menuItem3;
JMenuItem menuItem4;
JMenuItem menuItem5;
JMenuItem menuItem6;
JMenuItem menuItem7;
JMenuItem menuItem8;
JMenuItem menuItem9;
JMenuItem menuItem10;
popupForTable.add(menuItem1 = new JMenuItem ("menuItem1"));
popupForTable.add(menuItem2 = new JMenuItem ("menuItem2"));
popupForTable.add(menuItem3 = new JMenuItem ("menuItem3"));
popupForTable.add(menuItem4 = new JMenuItem ("menuItem4"));
popupForTable.add(menuItem5 = new JMenuItem ("menuItem5"));
popupForTable.add(menuItem6 = new JMenuItem ("menuItem6"));
popupForTable.add(menuItem7 = new JMenuItem ("menuItem7"));
popupForTable.add(menuItem8 = new JMenuItem ("menuItem8"));
popupForTable.add(menuItem9 = new JMenuItem ("menuItem9"));
popupForTable.add(menuItem10 = new JMenuItem ("menuItem10"));
popupForTable.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Point mousePoint = new Point();
mousePoint = MouseInfo.getPointerInfo().getLocation();
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupForTable, new Point(0, 0), table));
if (rowAtPoint > -1) {
table.setRowSelectionInterval(rowAtPoint, rowAtPoint);
}
}
});
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
});
table.setComponentPopupMenu(popupForTable);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("BorderLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(500, 500));
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Use the content pane's default BorderLayout. No need for
//setLayout(new BorderLayout());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
/* Use an appropriate Look and Feel */
try {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
我认为这是一个很好的例子,说明您应该如何 use/create jpopupmenu。 Link
看看SwingUtilities.convertPoint() doc
因此,更正您的 convertPoint()
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(null, mousePoint, table));
我解决了问题。首先感谢this问题中的@clamp。
---已解决---
我已从代码中删除以下行;
popupForTable.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Point mousePoint = new Point();
mousePoint = MouseInfo.getPointerInfo().getLocation();
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupForTable, new Point(0, 0), table));
if (rowAtPoint > -1) {
table.setRowSelectionInterval(rowAtPoint, rowAtPoint);
}
}
});
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
});
table.setComponentPopupMenu(popupForTable);
并将此 MouseListener
添加到 table;
table.addMouseListener(new MouseAdapter() {
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 = popupForTable;
popup.show(e.getComponent(), e.getX(), e.getY());
table.setRowSelectionInterval(r, r);
}
}
});
感谢所有对此问题感兴趣的人。也许这个解决方案对将来的人有帮助。
下面的代码创建了一个简单的 JFrame
,其中包括一个 JTable
和 JPopupMenu
。右键单击 select 单击的行并显示弹出窗口。
问题是:
当用户 Maximize
将 JFrame 显示到屏幕上并右键单击到最后 1-2-3-4-5 或第 6 行时,弹出窗口出现在错误的位置并且 select 由于弹出窗口出现错误的行高度对应屏幕高度。
我怎样才能做到这一点?
MCVE;
package popuptestapp;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
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;
import javax.swing.table.DefaultTableModel;
public class PopupTestApp {
public static boolean RIGHT_TO_LEFT = false;
public static void addComponentsToPane(Container pane) {
if (!(pane.getLayout() instanceof BorderLayout)) {
pane.add(new JLabel("Container doesn't use BorderLayout!"));
return;
}
if (RIGHT_TO_LEFT) {
pane.setComponentOrientation(
java.awt.ComponentOrientation.RIGHT_TO_LEFT);
}
JScrollPane jScrollPane = new JScrollPane();
JTable table = new JTable();
table.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{"", "", "", "", "", "", "", ""}
},
new String [] {
"Column1", "Column2", "Column3", "Column4", "Column5", "Column6", "Column7", "Column8"
}
) {
boolean[] canEdit = new boolean [] {
false, false, false, false, false, false, false, false
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
DefaultTableModel model1 = (DefaultTableModel) table.getModel();
model1.setRowCount(0);
//Fill the table with rows
for (Integer i = 0; i<=250; i++){
model1.addRow(new String[]{"", "", "", "", "", "", "", ""});
}
jScrollPane.setViewportView(table);
pane.add(jScrollPane, BorderLayout.PAGE_END);
//creating JPopupMenu
JPopupMenu popupForTable = new JPopupMenu();
JMenuItem menuItem1;
JMenuItem menuItem2;
JMenuItem menuItem3;
JMenuItem menuItem4;
JMenuItem menuItem5;
JMenuItem menuItem6;
JMenuItem menuItem7;
JMenuItem menuItem8;
JMenuItem menuItem9;
JMenuItem menuItem10;
popupForTable.add(menuItem1 = new JMenuItem ("menuItem1"));
popupForTable.add(menuItem2 = new JMenuItem ("menuItem2"));
popupForTable.add(menuItem3 = new JMenuItem ("menuItem3"));
popupForTable.add(menuItem4 = new JMenuItem ("menuItem4"));
popupForTable.add(menuItem5 = new JMenuItem ("menuItem5"));
popupForTable.add(menuItem6 = new JMenuItem ("menuItem6"));
popupForTable.add(menuItem7 = new JMenuItem ("menuItem7"));
popupForTable.add(menuItem8 = new JMenuItem ("menuItem8"));
popupForTable.add(menuItem9 = new JMenuItem ("menuItem9"));
popupForTable.add(menuItem10 = new JMenuItem ("menuItem10"));
popupForTable.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Point mousePoint = new Point();
mousePoint = MouseInfo.getPointerInfo().getLocation();
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupForTable, new Point(0, 0), table));
if (rowAtPoint > -1) {
table.setRowSelectionInterval(rowAtPoint, rowAtPoint);
}
}
});
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
});
table.setComponentPopupMenu(popupForTable);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("BorderLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(500, 500));
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Use the content pane's default BorderLayout. No need for
//setLayout(new BorderLayout());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
/* Use an appropriate Look and Feel */
try {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
我认为这是一个很好的例子,说明您应该如何 use/create jpopupmenu。 Link
看看SwingUtilities.convertPoint() doc
因此,更正您的 convertPoint()
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(null, mousePoint, table));
我解决了问题。首先感谢this问题中的@clamp。
---已解决---
我已从代码中删除以下行;
popupForTable.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Point mousePoint = new Point();
mousePoint = MouseInfo.getPointerInfo().getLocation();
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupForTable, new Point(0, 0), table));
if (rowAtPoint > -1) {
table.setRowSelectionInterval(rowAtPoint, rowAtPoint);
}
}
});
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// TODO Auto-generated method stub
}
});
table.setComponentPopupMenu(popupForTable);
并将此 MouseListener
添加到 table;
table.addMouseListener(new MouseAdapter() {
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 = popupForTable;
popup.show(e.getComponent(), e.getX(), e.getY());
table.setRowSelectionInterval(r, r);
}
}
});
感谢所有对此问题感兴趣的人。也许这个解决方案对将来的人有帮助。