2012-03-06 22 views
5

Bir JToggleButton'una (özel arka planı vardır) sahip olması gereken birkaç JLabels içeren bir JPanel içermesi gerekir. Bu bölüm çalışıyor.JToggleButton'unu JPanel ile bir JTable hücresine yerleştirme

Bu düğme daha sonra bir JTable hücresine yerleştirilir ve kullanıcılar tarafından basılması amaçlanır. Sorun şu ki sadece ikinci tıklamadaki düğmeye basabiliyorum. İlk tıklamada, odak ilk olarak JLabels ile panele ve daha sonra da gerçek butona atlar.

Bu sorunu çözmek için birkaç şey denedim, ancak aynı sorun devam ediyor. A) JPanel'in etiketleri ile doğrudan JToggleButton # add() üzerine yerleştirilmesi. JToggleButton alır JLayeredPane farklı Katmanlar üzerine Düğme ve Jpanel yerleşimi için kullandığı B) kısıt (Tamsayı - böylece JLabels ile JPanel

Herhangi ipucu var mı üst

görünür kalır)? Teşekkürler

Aşağıda, sorunu gösteren örnek kod yer almaktadır. Düğmeye tıklamak sadece ikinci kez çalışır. tablo ne olursa olsun bu bileşen fare olayları ele alamayacağını en derin bileşenine fare olayı geçen bir hücreyi seçmek için bir fare olayı yakalar

public class ClickableCustomButtonInTable extends JToggleButton { 

public ClickableCustomButtonInTable() { 
    Dimension d = new Dimension(100, 100); 
    JLabel lFirst = new JLabel("1st label"); 
    lFirst.setPreferredSize(d); 

    JLabel lSecond = new JLabel("2nd label"); 
    lSecond.setPreferredSize(d); 

    JPanel panel = new JPanel(); 
    panel.setOpaque(true); 

    panel.setLayout(new BorderLayout()); 
    panel.add(lFirst, BorderLayout.NORTH); 
    panel.add(lSecond, BorderLayout.SOUTH); 
    add(panel); 
    addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println("Button clicked"); 
     } 
    }); 
} 

private static class CustomButtonRenderer implements TableCellRenderer { 

    private final ClickableCustomButtonInTable button = new ClickableCustomButtonInTable(); 

    @Override 
    public Component getTableCellRendererComponent(JTable table, 
      Object value, boolean isSelected, boolean hasFocus, int row, 
      int column) { 
     return button; 
    } 
} 

private static class CustomButtonEditor extends AbstractCellEditor 
     implements TableCellEditor { 

    private final ClickableCustomButtonInTable button = new ClickableCustomButtonInTable(); 

    @Override 
    public Object getCellEditorValue() { 
     return button.getText(); 
    } 

    @Override 
    public Component getTableCellEditorComponent(JTable table, 
      Object value, boolean isSelected, int row, int column) { 
     return button; 
    } 

} 

public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    frame.setSize(new Dimension(200, 200)); 
    Container content = frame.getContentPane(); 
    TableModel model = new AbstractTableModel() { 

     @Override 
     public Object getValueAt(int rowIndex, int columnIndex) { 
      return null; 
     } 

     @Override 
     public int getRowCount() { 
      return 1; 
     } 

     @Override 
     public int getColumnCount() { 
      return 1; 
     } 

     @Override 
     public boolean isCellEditable(int rowIndex, int columnIndex) { 
      return true; 
     } 

     @Override 
     public Class<?> getColumnClass(int columnIndex) { 
      return ClickableCustomButtonInTable.class; 
     } 
    }; 

    JTable table = new JTable(model); 
    // table.setBounds(new Rectangle(0, 0, content.getWidth(), content 
    // .getHeight())); 
    table.setRowHeight(frame.getHeight()); 
    table.setDefaultRenderer(ClickableCustomButtonInTable.class, 
      new CustomButtonRenderer()); 
    table.setDefaultEditor(ClickableCustomButtonInTable.class, 
      new CustomButtonEditor()); 

    content.add(table); 
    content.setVisible(true); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 
} 
} 
+1

doğrudan sorunla ilgili: editör uygulaması _invalid_ olduğu: Düzenlemelerin iç nedenlerle işine zaman onun dinleyicileri bildirmek _must_. Probleminize gelince: temel olarak a) düzenlemenin ilk tıklamayla başlatıldığından emin olunuz b) tıkladığınızda, bileşen koordinatlarını düzenleme sırasındaki konumunu hesaplayın ve düzenleme üzerindeki "gerçek" hedef bileşenine (fi düğmesi) gönderin panel – kleopatra

+2

BTW: Table_Model uygulamanızın da balıkçılığınız olduğu gibi masaüstünüzdeki bileşenleri koruyabilirsiniz. (düzenlenebilir olmakla birlikte hücre değerlerini değiştirmek için herhangi bir api eksikse), belki de biraz değil-çok-önemsiz şeyler ortasında sağ atlama önce masa temelleri :-) – kleopatra

+0

Kleopatra, ipuçlarını için teşekkürler. Belki de a) düzenlemenin ilk tıklamada başlatıldığından emin olmanızı sağlayabilir misiniz? B) bu tıklamayı yakalayın, bileşen koordinatlarını düzenleme sırasındaki konumunu hesaplayın ve düzenleme panelindeki "gerçek" hedef bileşenine gönderiniz. olayı gerçek hedefe göndererek kastettiğinize emin olduğunuzda, ne demek istediğinizi call doClick().eğer öyleyse, korkarım jToggleButton'un sağladığı tıklama animasyonunu kaybederim. – d56

cevap

0
+1

muhtemelen büyük olasılıkla kariyerinizi kaydetmez ;-) Daha iyi tabloları/oluşturucuları/editörleri nasıl kullanacağınızı daha iyi öğrenin ... – kleopatra

+0

Bu çözümde sorun nedir? – d56

+0

her şey sadece (bu kısmı ((ClickableCustomButtonInTable) (SwingUtilities.getAncestorOfClass (ClickableCustomButtonInTable.class, SwingUtilities.getDeepestComponentAt (tablo, me.getX demek sorunuza ... – kleopatra

8

. Örneğinizde ilk tıklama, JToggleButton'u tamamen atlayarak JLabels'dan biri üzerinde biter. JToggleButton aktif hücre editörü haline geldiğinde, fare tıklamaları normal olarak çalışır. Odağı kaybetmek olsaydı, bir kez daha etkinleştirmek için iki tıklama gerektirir.

Ayrıca, demonuzda mevcut bulunan panelde değil, düğme kenarlığını tıklarsanız, düğmenin istediğiniz şekilde çalıştığını da görebilirsiniz.

Bu şekilde çalışmanın bir yolu, JToggleButton içinde herhangi bir bileşende hedeflenen herhangi bir fare olayının olmasını sağlamaktır. senin kurucu çağırmak sonunda o

static void addEventBubble(final Container target, Container container) { 
    for(Component comp:container.getComponents()) { 
     if (comp instanceof Container) { 
      addEventBubble(target, (Container) comp); 
     } 
     comp.addMouseListener(new MouseAdapter() { 
      private MouseEvent retarget(MouseEvent e) { 
       return new MouseEvent(target, e.getID(), e.getWhen(), 
         e.getModifiers(), e.getX(), e.getY(), 
         e.getClickCount(), e.isPopupTrigger(), 
         e.getButton()); 
      } 


      public void mousePressed(MouseEvent e) { 
       MouseEvent r = retarget(e); 
       for(MouseListener listen:target.getMouseListeners()) { 
        listen.mousePressed(r); 
       } 
      } 


      public void mouseReleased(MouseEvent e) { 
       MouseEvent r = retarget(e); 
       for(MouseListener listen:target.getMouseListeners()) { 
        listen.mouseReleased(r); 
       } 
      } 


      public void mouseClicked(MouseEvent e) { 
       MouseEvent r = retarget(e); 
       for(MouseListener listen:target.getMouseListeners()) { 
        listen.mouseClicked(r); 
       } 
      } 
     }); 
    } 
} 

ve:: Bu kullanarak bu statik yöntemi yapabileceği de düğmeye ulaşacak bu düğmeye içinde herhangi bir bileşen üzerine herhangi bir fare olayı sonrasında

addEventBubble(this,this); 

ve Bu yüzden devletini değiştir. Bunu yaptıktan sonra, istediğim gibi her tıklamaya tepki verdim.

+0

http://www.coderanch.com/t/570021/GUI/java adresinden başka bir çözüm daha verildi./click-event-custom-JToggleButton-JTable Bu "kırılgan" ancak daha az kod. Sanırım onunla yapışırdım. Açıklama ve çözüm için teşekkür ederim, ikisine de çok ihtiyacım vardı. – d56

+0

Baktım, "kırılgan" aslında bunun için bir kelime :) Paylaşım için teşekkürler. –