JTable с JPopupMenu
Как я могу предотвратить запуск и показ JPopupMenu
только если есть Mouse Cursor
над выбранным JTable'Row
мой вопрос: есть ли другой способ, как getBounds
из выбранной строки и определить / сравнить это с Mouse
позиция...
моя простая sscce показала только нежелательный противоположный статус, можно выбрать любую строку и JPopupMenu
срабатывает от целого JTable
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableCheckBox extends JFrame {
private static final long serialVersionUID = 1L;
private JTable table;
public TableCheckBox() {
Object[] columnNames = {"Type", "Company", "Shares", "Price", "Boolean"};
Object[][] data = {
{"Buy", "IBM", new Integer(1000), new Double(80.50), false},
{"Sell", "MicroSoft", new Integer(2000), new Double(6.25), true},
{"Sell", "Apple", new Integer(3000), new Double(7.35), true},
{"Buy", "Nortel", new Integer(4000), new Double(20.00), false}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
table = new JTable(model) {
private static final long serialVersionUID = 1L;
@Override
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
createPopupMenu();
}
private void createPopupMenu() {
JPopupMenu popup = new JPopupMenu();
JMenuItem myMenuItem1 = new JMenuItem("cccccccccccccccccccccc");
JMenuItem myMenuItem2 = new JMenuItem("bbbbbbbbbbbbbbbbbbbbbb");
popup.add(myMenuItem1);
popup.add(myMenuItem2);
MouseListener popupListener = new PopupListener(popup);
table.addMouseListener(popupListener);
}
private class PopupListener extends MouseAdapter {
private JPopupMenu popup;
PopupListener(JPopupMenu popupMenu) {
popup = popupMenu;
}
@Override
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
if (table.getSelectedRow() != -1) {
maybeShowPopup(e);
}
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TableCheckBox frame = new TableCheckBox();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
});
}
}
2 ответа
Это интересный вопрос, потому что он подчеркивает отсутствие API на JComponent:-)
Как все мы знаем, рекомендуемый способ регистрации popupMenus - использовать свойство componentPopupMenu. Связанный API
void setComponentPopupMenu(JPopupMenu);
JPopupMenu getComponentPopupMenu();
Point getPopupLocation(MouseEvent);
чего не хватает (и действительно нужно для этого требования)
JPopupMenu getComponentPopupMenu(MouseEvent);
этот недостаток еще более раздражает, так как getPopupLocation вызывается (AWTEventHelper глубоко в LAF) после getComponentPopup(). Так что нет никакой возможности для взлома, такого как сохранение последнего события мыши, которое могло бы вызвать всплывающее окно, а затем решить, что / если вернуть всплывающее окно. И возвращение нулевого значения для местоположения приведет только к его отображению в местоположении мыши
Единственный (грязный) хак (вокруг моего полного нежелания испачкать руки с помощью MouseListener;-) - это переопределить getComponentPopup и решить, возвращать ли его, основываясь на текущей позиции мыши
table = new JTable(model) {
/**
* @inherited <p>
*/
@Override
public JPopupMenu getComponentPopupMenu() {
Point p = getMousePosition();
// mouse over table and valid row
if (p != null && rowAtPoint(p) >= 0) {
// condition for showing popup triggered by mouse
if (isRowSelected(rowAtPoint(p))) {
return super.getComponentPopupMenu();
} else {
return null;
}
}
return super.getComponentPopupMenu();
}
};
побочным эффектом является то, что показ всплывающих окон не запускается с клавиатуры, если мышь находится где-нибудь над таблицей, что может быть или не быть проблемой.
Вы ищете что-то подобное?
Отображать всплывающее окно только для выбранных строк
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
// get row that pointer is over
int row = table.rowAtPoint(e.getPoint());
// if pointer is over a selected row, show popup
if (table.isRowSelected(row)) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
Или наоборот, чтобы всплывающее окно не отображалось только над выбранными строками:
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
int row = table.rowAtPoint(e.getPoint());
int[] selectedRows = table.getSelectedRows();
if (!table.isRowSelected(row)) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
}