JTable с JPopupMenu - PullRequest
       38

JTable с JPopupMenu

10 голосов
/ 15 сентября 2011

как я могу предотвратить запуск и показ 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 ]

12 голосов
/ 15 сентября 2011

Возможно, вы ищете что-то подобное?

Показать всплывающее окно только для выбранных строк

  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());
        }
     }
7 голосов
/ 15 сентября 2011

Это интересный вопрос, потому что он выделяет отсутствующий API в JComponent :-)

Как мы все знаем, рекомендуемый способ регистрации popupMenus - использовать свойство componentPopupMenu.Связанный API - это

 void setComponentPopupMenu(JPopupMenu);
 JPopupMenu getComponentPopupMenu();
 Point getPopupLocation(MouseEvent);

, чего не хватает (и действительно необходимо для этого требования):

JPopupMenu getComponentPopupMenu(MouseEvent);

этот недостаток еще более раздражает, так как вызывается getPopupLocation (AWTEventHelper deepв 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();
        }

    };

побочный эффект заключается в том, что всплывающее окно не запускается клавиатурой, пока мышь находится где-нибудь над таблицей, что может или нетбыть проблемой.

...