2011-09-14 33 views
10

làm thế nào tôi có thể ngăn chặn kích hoạt và hiển thị JPopupMenu chỉ nếu là Mouse Cursor qua chọn JTable'RowJTable với JPopupMenu

câu hỏi của tôi: nếu là có một cách khác như getBounds từ hàng đã chọn và xác định/so sánh rằng với Mouse vị trí ...

sscce đơn giản của tôi chứng minh chỉ cần bỏ muốn tình trạng ngược lại, bất kỳ hàng có thể được lựa chọn và JPopupMenu được kích hoạt từ cả 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

SSCCE đẹp bằng cách này. –

+0

. không phải. lớp con. các. _lượt xem_ . cho. _mô hình_. lý do. – kleopatra

+0

Giải pháp phù hợp nhất với tôi (cũng bởi kleopatra) chưa được liên kết ở đây: http://stackoverflow.com/a/17316876/411282 –

Trả lời

7

Đó là một câu hỏi thú vị, vì nó nổi bật thiếu api trên JComponent :-)

Như chúng ta đều biết, cách được khuyến nghị để đăng ký popupMenus là sử dụng thuộc tính componentPopupMenu. api liên quan là

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

gì là mất tích (và thực sự cần thiết cho yêu cầu này) được

JPopupMenu getComponentPopupMenu(MouseEvent); 

thiếu này là tất cả những khó chịu hơn, như getPopupLocation được gọi là (bởi AWTEventHelper sâu trong LAF) sau getComponentPopup(). Vì vậy, không có mất nhiều thời gian cho một hack như lưu trữ sự kiện chuột cuối cùng mà có thể đã kích hoạt popup và sau đó quyết định đó/nếu để trả lại popup. Và trả về null cho vị trí sẽ chỉ dẫn đến việc hiển thị nó ở vị trí của chuột

Chỉ (bẩn) hack (xung quanh sự miễn cưỡng hoàn toàn của tôi để có được bàn tay của tôi bẩn với một MouseListener ;-) là ghi đè getComponentPopup và quyết định có hay không hoặc không trả lại nó dựa trên vị trí hiện tại của chuột

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(); 
     } 

    }; 

tác dụng phụ là con chuột ở bất kỳ đâu trên bàn, điều này có thể không phải là vấn đề.

+0

cảm ơn vì đã xây dựng, việc học dễ dàng như thế nào ....hehehe, chắc chắn rằng bài viết của bạn là câu trả lời và đóng một vấn đề khác của tôi, +1 của tôi – mKorbel

+0

Có thể có một vấn đề khác, tôi nghĩ, do việc sử dụng 'JScrollPane' nhúng' JTable'. Trong quá khứ, tôi nhớ có vấn đề với các sự kiện không xảy ra trên 'JTable' khi nhấp vào bên ngoài bất kỳ hàng nào (nhưng * bên trong *' JScrollPane', trong không gian trống): Tôi phải nghe các sự kiện trên chính 'JScrollPane' (hoặc 'JViewport' không thể nhớ chính xác). Vì vậy, có lẽ @mKorbel, bạn cũng sẽ phải xem xét điều đó (điều đó sẽ xảy ra bất cứ khi nào 'JScrollPane' cao hơn' JTable'). – jfpoilpret

+0

@jfpoilpret không có ý tưởng làm thế nào có thể tiêu thụ các sự kiện từ chuột để JViewPort, bạn có thể cung cấp một ví dụ về consiming MouseEvents từ/đến JViewPort, bởi vì tôi xem xét điều này là hoàn toàn điếc JComponent :-) – mKorbel

12

Bạn đang tìm kiếm một cái gì đó như thế này có lẽ?

Để hiển thị cửa sổ bật lên trên hàng đã chọn (s) chỉ

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()); 
     } 
    } 
    } 

Hoặc ngược lại, để ngăn chặn cửa sổ bật lên hiển thị trên hàng lựa chọn duy nhất:

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()); 
     } 
    } 
+1

+1 bất chấp quan điểm khác nhau của tôi :). Trong thực tế của bạn là một giải pháp dễ dàng nhanh chóng dễ dàng. – Heisenbug

+1

+1 - một khi bạn đã thay thế tất cả vòng lặp đó và kiểm tra thủ công bằng isRowSelected (hàng) :-) – kleopatra

+1

xin lỗi tất cả. Tôi đã hoàn toàn sai. Có vẻ như những gì tôi muốn làm, là không thể. Nhưng @ kleopatra, tôi muốn biết: có lý do nào tốt cho thực tế là các trình kết xuất ô không thể xử lý sự kiện chuột không? – Heisenbug