5

いくつかのJLabelを含むJPanelを含むJToggleButton(カスタム背景を持つ)が必要です。その部分は機能します。

このボタンは後でJTableセルに配置され、ユーザーが押すことを目的としています。問題は、2回目のクリックでしかボタンを押せないことです。最初のクリックでフォーカスが最初にJLabelsのあるパネルにジャンプし、その後で実際のボタンにジャンプします。

この問題を解決するためにいくつかのことを試みましたが、同じ問題が解決しません。A)ラベル付きのJPanelをJToggleButton#add()に直接配置します。B)JLayeredPaneを使用して、ボタンとJPanelを異なるレイヤーに配置します。JToggleButtonは制約Integer(-)を取り、JLabelsを含むJPanelが上部に表示されたままになります。

ヒントはありますか?ありがとう

以下は、問題を説明するサンプルコードです。ボタンのクリックは2回目のみ機能します。

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

2 に答える 2

9

テーブルがマウスイベントをキャプチャしてセルを選択すると、そのコンポーネントがマウスイベントを処理できるかどうかに関係なく、マウスイベントが最も深いコンポーネントに渡されます。あなたの例では、最初のクリックはJLabels、完全にバイパスして、の1つで終わりますJToggleButton。がJToggleButtonアクティブなセルエディタになると、マウスクリックは通常どおりに機能します。フォーカスを失った場合は、再度2回クリックしてアクティブにする必要があります。

デモで、含まれているパネルではなくボタンの境界線をクリックすると、ボタンが希望どおりに機能することに気付いた場合にも、これを確認できます。

これを回避する1つの方法は、内の任意のコンポーネントを対象とするすべてのマウスイベントを確認することです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);

この後、ボタン内のコンポーネントに対するマウスイベントもボタンに到達し、その状態が変化します。これを行った後、ボタンがすべてのクリックに必要に応じて反応することがわかりました。

于 2012-03-13T02:30:35.700 に答える
0

http://www.coderanch.com/t/570021/GUI/java/click-event-custom-JToggleButton-JTable

于 2012-03-13T20:25:24.867 に答える