Помещение JToggleButton с помощью JPanel в ячейку JTable - PullRequest
5 голосов
/ 06 марта 2012

Мне нужен JToggleButton (с настраиваемым фоном), который содержит JPanel с несколькими JLabel внутри себя. Эта часть работает.

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

Я пытался решить эту проблему несколькими способами, но та же проблема сохраняется. A) Поместить JPanel с метками непосредственно на JToggleButton # add (). B) использование JLayeredPane для размещения Button и JPanel на разных слоях, где JToggleButton принимает ограничение Integer (-), так что JPanel с JLabels остается видимым сверху

У вас есть какие-нибудь советы? Спасибо

Ниже приведен пример кода, который иллюстрирует проблему. Нажатие на кнопку работает только во второй раз.

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

Ответы [ 2 ]

8 голосов
/ 13 марта 2012

Когда таблица захватывает событие мыши для выбора ячейки, она передает событие мыши в самый глубокий компонент независимо от того, может ли этот компонент обрабатывать события мыши.В вашем примере первый щелчок заканчивается на одном из JLabels, полностью минуя JToggleButton.Как только 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 голосов
/ 14 марта 2012
...