繁体   English   中英

将JToggleButton与JPanel放在JTable单元格中

[英]Placing JToggleButton with JPanel within into a JTable cell

我需要一个JToggleButton(具有自定义背景),其中包含一个JPanel,其中包含多个JLabel。 那部分有效。

此按钮随后放在JTable单元格中,并由用户按下。 问题是我只能在第二次点击时按下按钮。 在第一次点击时,首先使用JLabel跳转到面板,然后再转到实际按钮。

我尝试了几件事来尝试解决这个问题,但同样的问题仍然存在。 A)将带有标签的JPanel直接放在JToggleButton#add()上。 B)使用JLayeredPane将Button和JPanel放置到不同的层上,其中JToggleButton采用约束整数( - ),以便具有JLabel的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);
}
}

当表捕获鼠标事件以选择单元格时,它将鼠标事件传递给最深的组件,而不管该组件是否可以处理鼠标事件。 在您的示例中,第一次单击最终会在其中一个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);

在此之后,按钮内任何组件上的任何鼠标事件也将到达按钮,从而改变其状态。 执行此操作后,我发现按钮会根据需要对每次单击做出反应。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM