2011-09-14 18 views
10

JPopupMenuMouse CursorJPopupMenu ile JTable

üzerinde Mouse Cursor ise sadece tetikleme ve JPopupMenu gösterimini nasıl engelleyebilirim? soru: getBounds olarak seçili satırdan başka bir yol varsa ve Mouse konumu ile bunu belirleyin/karşılaştırın ...

sscce, sadece aranmayan zıt durumu gösterdi, herhangi bir satır seçilebilir ve 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

Bu arada güzel SSCCE. –

+0

yapar. değil. alt sınıf. . _görünüm_ . için. _model_. nedenler. – kleopatra

+0

Benim için en iyi çalışan çözüm (kleopatra tarafından da) şu ana kadar bağlantılandırılmadı: http://stackoverflow.com/a/17316876/411282 –

cevap

7

o vurgular, çünkü ilginç bir soru JComponent üzerinde eksik api :-)

Hepimizin bildiği gibi, popupMenus'u kaydettirmenin önerilen yolu componentPopupMenu özelliğini kullanmaktır. İlgili API getPopupLocation (LAF derin AWTEventHelper tarafından) olarak adlandırılan

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

, ne bu eksikliği daha da can sıkıcı

JPopupMenu getComponentPopupMenu(MouseEvent); 

eksik (ve aslında bu gereksinimi için gerekli) olduğu'dan sonra getComponentPopup(). Böylece, pop-up'ı tetikleyebilecek olan son fare olayını saklamak gibi bir hack için bir yol yok ve daha sonra hangi pencereyi döndüreceğine karar verin. Ve konum için null döndüren, yalnızca fare konumunda görüntülenmesine neden olur.

Tek (kirli) kesmek (benim bir MouseListener ile ellerimi kirletmek için benim isteksizliğim etrafında) ;-) getComponentPopup'u geçersiz kılmak ve yoksa

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

    }; 

yan etki veya bir sorun olmayabilir, hangi o pop-up gösteren sürece fare yerde masanın üstünde olduğu gibi klavye tarafından tetiklenen değil mi geçerli fare konumuna bağlı olarak dönmemeyi.

+0

detaylar için teşekkür geliyor, ne kadar kolay öğrenme ....hehehe, emin yazılan cevap ve başka sorunum kapanış ise, benim 1 – mKorbel

+0

'JTable' gömme bir' JScrollPane' kullanımı nedeniyle ek bir sorun, bence, olabilir. Geçmişte, olaylar herhangi bir satırdaki dışında tıklandığında 'JTable' üzerinde meydana gelmiyor sorunlarınız hatırlıyorum (iç * ama *' JScrollPane', boş uzayda): Ben 'JScrollPane' kendisinde olayları dinlemek zorunda kaldı (ya da "JViewport" tam olarak hatırlayamıyor). Yani belki de, belki de, (JScrollPane'in JTable'dan daha yüksek olduğu zaman olması gereken) bunu göz önünde bulundurmalısınız. – jfpoilpret

+0

@jfpoilpret bu – mKorbel

12

Böyle bir şey mi arıyorsunuz?

sadece seçili satırları üzerinde gösterilmesini açılır pencere engellemek için seçilen satır (lar) sadece

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

Ya converse, üzerinde açılır pencere göstermek için:

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 farklı bakış açıma rağmen :). Aslında sizinki kolay bir hızlı ve güzel bir çözümdür. – Heisenbug

+1

+1 - bir kez tüm bu döngü ve isRowSelected (satır) :-) – kleopatra

+1

için elle kontrol elle değiştirerek değiştirdik. Tamamen yanılmışım. Yapmak istediğim şey mümkün değil gibi görünüyor. Ama Kleopatra, bilmek isterim: Hücre oluşturucuların fare olayını idare edememesi için iyi bir neden var mı? – Heisenbug