0

JTable セルをクリックすると、行が「選択」されます。他のものをクリックすると、選択が解除されるようにしたいです。

テーブル上でマウスリスナーを使用してこれを行うことを考えていますが、認識方法がわかりません(テーブルではなくクリックします)。何か案は?

これは私がしようとしているものです:

 jTable.addMouseListener(new MouseAdapter(){
                @Override
                public void mouseClicked(MouseEvent e){
                    System.out.println("click");}});

しかし、最初の列をクリックしたときにのみクリックが印刷され、テーブルではないものをクリックしたときは印刷されません。

そのイベントを認識したら、次のメソッドを呼び出します。

public void loseCellFocus()
{
    jTable.getCellEditor().stopCellEditing();
    jTable.clearSelection();
}
4

2 に答える 2

1

私はいつかこれをJTree. フォーカスリスナーなどが機能しませんでした。Toolkit.getDefaultToolkit().addAWTEventListener最後に、私が使用した解決策は、キーボードとマウスのイベントを使用してキャプチャすることです。イベントのコンポーネント階層で を探しJTree、アイテムがツリーに属していない場合はメソッドを呼び出して選択を削除します。

必要に応じてコードを検索できます。

編集

受け入れられた回答の AWTEventListener は、必要以上に複雑です。

        final AWTEventListener focusTracker = new AWTEventListener() {
            @Override public void eventDispatched(AWTEvent event) {
                if (event.getID() != MouseEvent.MOUSE_CLICKED && event.getID() != KeyEvent.KEY_PRESSED)
                    return;
                if (!isPartOfTable((Component) event.getSource())) {
                    if (table.isEditing()) {
                        TableCellEditor cellEditor = table.getCellEditor();
                        cellEditor.cancelCellEditing();
                    }
                    table.clearSelection();
                    table.dispatchEvent(new FocusEvent(table, FocusEvent.FOCUS_LOST));
                }
            }

            protected boolean isPartOfTable(Component component) {
                while (component != null && component != table)
                    component = component.getParent();
                return component == table;
            }

        };
        Toolkit.getDefaultToolkit().addAWTEventListener(focusTracker, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);

注: フレームが閉じているときは、リスナーを削除する必要があります。外側をクリックしたときに表のセルがまだ強調表示されているのが好きではありませんでした。そのため、フォーカスが失われたイベントをテーブルに投稿しています。

于 2015-08-13T05:41:42.303 に答える
1

FocusListenerにアタッチされた を使用するJTableと、フォーカスがテーブルから離れたときに通知されます。

詳細については、フォーカス リスナーの作成方法を参照してください。

例えば...

    table.addFocusListener(new FocusAdapter() {
        @Override
        public void focusLost(FocusEvent e) {
            loseCellFocus();
        }           
    });

もちろん、これは、キーボード フォーカスを受け取ることができる新しいコンポーネントにキーボード フォーカスが転送された場合にのみ機能します。

これにより、呼び出されたセルをクリックするとすぐに、loseCellFocus() メソッドがすぐに呼び出されます。

フォーカスがJTable#setSurrendersFocusOnKeystroke移されたコンポーネントがJTable

例えば...

table.addFocusListener(new FocusAdapter() {
    @Override
    public void focusLost(FocusEvent e) {
        if (e.getOppositeComponent().getParent() != table) {
            loseCellFocus();
        }
    }
});

実行可能な例...

さて、それは面倒になりました。FocusListenerに を追加するだけでなくJTable、コンポーネントに追加する必要がありましたTableCellEditor:P

これは概念実証のみです。イベントを発生させたり、共通のインターフェイスを介して必要な機能をトリガーしたりできる特殊なクラスが必要です。

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new BorderLayout());

            JTable table = new JTable(new DefaultTableModel(10, 10));

            JTextField editorField = new JTextField(10);
            editorField.setBorder(new EmptyBorder(1, 1, 1, 1));
            editorField.addFocusListener(new FocusAdapter() {
                @Override
                public void focusLost(FocusEvent e) {
                    TableCellEditor cellEditor = table.getCellEditor();
                    if (cellEditor != null) {
                        if (!cellEditor.stopCellEditing()) {
                            cellEditor.cancelCellEditing();
                        }
                    }

                    Component gotFocus = e.getOppositeComponent();
                    if (!gotFocus.equals(table)) {
                        table.clearSelection();
                    }
                }
            });
            DefaultCellEditor editor = new DefaultCellEditor(editorField);
            table.setDefaultEditor(Object.class, editor);

            add(new JScrollPane(table));
            table.addFocusListener(new FocusAdapter() {

                @Override
                public void focusLost(FocusEvent e) {
                    Component gotFocus = e.getOppositeComponent();
                    if (!gotFocus.getParent().equals(table)) {
                        TableCellEditor cellEditor = table.getCellEditor();
                        if (cellEditor != null) {
                            if (!cellEditor.stopCellEditing()) {
                                cellEditor.cancelCellEditing();
                            }
                        }
                        table.clearSelection();
                    }
                }

            });

            JTextField field = new JTextField(10);
            add(field, BorderLayout.SOUTH);
        }

    }

}

AWTEventListener の例...

よし、クロスコンディションがめちゃくちゃになってしまうので、このルートはあまり行きたくなかったが。基本的に、これは ALLMouseEventFocusEvents を監視し、いくつかの後方サマーサルトを実行して有効な条件をテストし (aJTableがイベントの一部であるかどうかだけでなく、エディターがイベントの一部であるかどうかも確認する必要があるため)、それらの結果に基づいています。 、セルの編集を停止し、選択をクリアします...

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JTable table = new JTable(new DefaultTableModel(5, 5));
            setLayout(new GridBagLayout());
            setBorder(new EmptyBorder(20, 20, 20, 20));
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(new JScrollPane(table), gbc);
            add(new JTextField(10), gbc);

            Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
                @Override
                public void eventDispatched(AWTEvent event) {
                    if (event instanceof FocusEvent) {
                        FocusEvent focusEvent = (FocusEvent) event;
                        if (focusEvent.getID() == FocusEvent.FOCUS_LOST) {
                            Component focusTo = focusEvent.getOppositeComponent();
                            Component focusFrom = focusEvent.getComponent();

                            JTable table = getTableFrom(focusFrom);
                            if (focusTo == null || !focusTo.getParent().equals(table)) {

                                stopCellEditing(table);
                                clearSelection(table);

                            }
                        }
                    } else if (event instanceof MouseEvent) {
                        MouseEvent mouseEvent = (MouseEvent) event;
                        if (mouseEvent.getID() == MouseEvent.MOUSE_CLICKED) {
                            Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
                            JTable table = getTableFrom(focusOwner);
                            System.out.println("     table = " + table);
                            System.out.println("focusOwner = " + focusOwner);
//                          if ((table != null && mouseEvent.getComponent() != table) || (focusOwner != null && !focusOwner.getParent().equals(table))) {
                            if ((table != null && mouseEvent.getComponent() != table) && (focusOwner != null && !focusOwner.getParent().equals(table))) {
                                stopCellEditing(table);
                                clearSelection(table);
                            }
                        }
                    }
                }

                protected JTable getTableFrom(Component component) {
                    JTable table = null;
                    if (component instanceof JTable) {
                        table = (JTable) component;
                    } else if (component != null && component.getParent() instanceof JTable) {
                        table = (JTable) component.getParent();
                    }
                    return table;
                }

                protected void clearSelection(JTable table) {
                    if (table != null) {
                        table.clearSelection();
                    }
                }

                protected void stopCellEditing(JTable table) {

                    if (table != null) {
                        TableCellEditor cellEditor = table.getCellEditor();
                        if (cellEditor != null) {
                            if (!cellEditor.stopCellEditing()) {
                                cellEditor.cancelCellEditing();
                            }
                        }
                    }
                }
            }, AWTEvent.FOCUS_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);
        }

    }

}

この例は基本的にすべてJTableの s に対して機能します (AWTEventListenerが登録されると) が、イベント ソースの一部を変更してそれらを互いに比較することにより、単一のテーブルを監視するように構成できます :P

于 2015-08-13T05:13:38.710 に答える