2012-03-06 3 views
5

JToggleButton (사용자 정의 배경 있음)에 JLabel이 여러 개있는 JPanel이 있어야합니다. 그 부분은 작동합니다.JTable 셀에 JPanel과 함께 JToggleButton 배치하기

이 버튼은 나중에 JTable 셀에 배치되며 사용자가 누르기위한 것입니다. 문제는 두 번째 클릭시에만 버튼을 누를 수 있다는 것입니다. 첫 번째 클릭에서 Apperenty는 JLabels로 패널로 먼저 이동하고 이후에는 실제 버튼으로 포커스를 이동합니다.

이 문제를 해결하기 위해 여러 가지 시도를했지만 동일한 문제가 계속 발생합니다. A) 레이블이있는 JPanel을 JToggleButton # add()에 직접 배치합니다. B) JLayeredPane을 사용하여 JToggleButton이 JLabels이있는 JPanel이 맨 위에 표시되도록 Integer (-) 제약 조건을 취하는 다른 레이어에 Button 및 JPanel을 배치합니다.

팁이 있습니까? 감사합니다

다음은 문제를 설명하는 샘플 코드입니다. 버튼을 클릭하면 두 번째에만 작동합니다.

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

직접 문제와 관련이없는 : 편집기 구현 _invalid_이다 : 편집이 내부 이유로 종료 될 때 그 청취자에게 통지 절대 안된다. 귀하의 문제에 관해서는 기본적으로 a) 첫 번째 클릭시 편집이 시작되었는지 확인해야합니다. b) 해당 클릭을 가져 와서 구성 요소 좌표를 편집 할 때의 위치를 ​​계산하고 편집시 "실제"대상 구성 요소 (버튼)로 디스패치합니다. 패널 – kleopatra

+2

표 : 당신은 tableModel의 구성 요소를 유지하지 않습니다. TableModel 구현이 비싸기 때문에 (편집 가능하지만 셀 값을 변경하는 API가 누락되었음을 알립니다.) 어쩌면 읽고 이해해야합니다. 별로 평범하지 않은 물건의 중간에 뛰어 오르기 전에 테이블의 기초 :-) – kleopatra

+0

@kleopatra, 당신의 팁에 감사드립니다. a) 연결 방법/방법을 a) 첫 번째 클릭시 편집이 시작되었는지 확인하십시오. b) 해당 클릭을 가져 와서 구성 요소 좌표를 편집 할 때 위치를 계산하고 편집 패널의 "실제"대상 구성 요소로 전달하십시오. 아니요. 실제 타겟에 이벤트를 보내면 무슨 뜻인지, doClick()이 무슨 뜻인지 알 수 있습니다.그렇다면 jToggleButton이 제공하는 클릭 애니메이션을 잃어 버릴 까봐 걱정됩니다. – d56

답변

0
+1

은 아마도 당신의 경력을 저장하지 않을 것입니다 ;-) _correctly_ 테이블/렌더러/편집자를 사용하는 방법을 더 잘 배웁니다 ... – kleopatra

+0

그 솔루션에는 어떤 문제가 있습니까? – d56

+0

모든 난 단지 (이 부분 ((ClickableCustomButtonInTable) (SwingUtilities.getAncestorOfClass (ClickableCustomButtonInTable.class, SwingUtilities.getDeepestComponentAt (테이블, me.getX을 의미 질문 ... – kleopatra

8

테이블이 셀을 선택하기 위해 마우스 이벤트를 캡처하면 해당 구성 요소가 마우스 이벤트를 처리 할 수 ​​있는지 여부에 관계없이 가장 깊은 구성 요소로 마우스 이벤트를 전달합니다. 예에서 첫 번째 클릭은 JToggleButton을 우회하여 JLabels 중 하나에서 끝납니다. JToggleButton이 활성 셀 편집기가되면 마우스 클릭이 정상적으로 작동합니다. 초점을 잃는다면 다시 한 번 두 번 클릭해야 활성화 할 수 있습니다.

데모에서 포함 된 패널이 아니라 단추 테두리를 클릭하면 단추가 제대로 작동하는 것을 볼 수 있습니다.

이 문제를 해결하는 한 가지 방법은 JToggleButton 내의 모든 구성 요소를 대상으로하는 모든 마우스 이벤트를 확인하는 것입니다. 생성자의 호출의 끝에서 다음

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

과 : :이 사용하여이 정적 방법을 수행 할 수 있습니다 또한 버튼에 도달 할 것이 버튼 내에서 모든 구성 요소에 따라 어떤 마우스 이벤트 후

addEventBubble(this,this); 

및 그러므로 그 상태를 바꿔라. 이 작업을 수행 한 후 원하는대로 모든 클릭에 반응하는 버튼을 발견했습니다.

+0

http://www.coderanch.com/t/570021/GUI/java에서 다른 해결책을 얻었습니다./click-event-custom-JToggleButton-JTable "부서지기 쉽지만 코드는 적습니다. 나는 그때 그것을 붙잡을 것이라고 생각한다. 설명 및 솔루션을 제공해 주셔서 감사합니다. – d56

+0

"부서지기 쉽다"는 말은 실제로 그것을위한 단어입니다. 공유해 주셔서 감사합니다. –

관련 문제