繁体   English   中英

Java/JFC中的行选择模式和单单元选择模式的切换 Swing JTable

[英]Switch between row selection mode and single cell selection mode in Java/JFC Swing JTable

在一个主要是一组 JTables 和 JTextFields 的应用程序中,我试图让它可以通过键盘和鼠标访问。 我的想法是帮助用户使用 VK_TAB 键在组件之间导航的最佳方式。

我的第一个目标是在用户尝试导航到相邻的 JTextField 时阻止 JTables “吞下” VK_TAB 键。 我试图在下面组合一个最小的可编译和可运行的示例。 我询问了焦点 JTable 对 VK_ENTER 的反应:之后,它会通过将焦点转移到下一个单元格来对 VK_TAB 做出反应,直到按下 ESC。

下面的可运行示例是我根据我得到的答案所做的结果。 编译代码时,行选择模式处于活动状态,并且 Tab 键在文本字段和表格之间跳跃。 当您按 Enter 时,它会切换到单个编辑模式,您可以使用 tab 键更改单元格,直到按 esc 键。

我仍然遇到的问题是:当您编辑单元格并按 esc 键时,仍然选择了单个单元格。 相反,应该选择整行。 我怎样才能做到这一点?

谢谢!

package TableTest;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;

public class MyFrame extends JFrame {

    private static final long serialVersionUID = 1L;

    public MyFrame() {
        super();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                MyFrame frame = new MyFrame();
                frame.init();
                frame.setVisible(true);
            }

        });
    }

    private void init() {
        JPanel contentPane = new JPanel(new BorderLayout());// new GridBagLayout()
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);

        JTable table = new JTable(new DefaultTableModel(new Object[][] { { 1, 2, 3 }, //
                { 4, 5, 6 }, //
                { 7, 8, 9 }, //
                { "#", 0, "*" }, }, //
                new String[] { "First", "Second", "Third" }));

        // When TAB is hit, go to next Component instead of next cell
        final KeyStroke tabKey = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
        table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(tabKey, "tabNext");
        final AbstractAction tabNext = new AbstractAction() {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent ae) {
                KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
            }
        };
        table.getActionMap().put("tabNext", tabNext);

        // When Shift+TAB is hit, go to previous Component instead of previous cell
        final KeyStroke shiftTabKey = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK);
        table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(shiftTabKey, "tabBefore");
        final AbstractAction tabBefore = new AbstractAction() {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent event) {
                KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent();
            }
        };
        table.getActionMap().put("tabBefore", tabBefore);

        // on VK_ENTER, navigate in JTable only ("edit mode")
        final KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
        final AbstractAction editModeAction = new AbstractAction() {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent event) {
                editMode(table, tabKey, shiftTabKey);
            }
        };
        table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(enterKey, "editModeAction");
        table.getActionMap().put("editModeAction", editModeAction);

        // On VK_ESCAPE or when JTable loses focus, quit the "edit mode"
        final KeyStroke escKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
        final AbstractAction quitEditModeAction = new AbstractAction() {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent event) {
                quitEditMode(table, tabKey, shiftTabKey);
            }
        };
        table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(escKey, "quitEditModeAction");
        table.getActionMap().put("quitEditModeAction", quitEditModeAction);
        final FocusListener listener = new FocusListener() {
            @Override
            public void focusGained(FocusEvent event) {
                //do nothing
            }

            @Override
            public void focusLost(FocusEvent event) {
                quitEditMode(table, tabKey, shiftTabKey);
            }
        };
        table.addFocusListener(listener);

        JTextField jtf = new JTextField("Text here");

        contentPane.add(jtf, BorderLayout.NORTH);
        contentPane.add(table, BorderLayout.CENTER);

        pack();

        //printActions(table);
    }

    private void editMode(JTable table, final KeyStroke tabKey, final KeyStroke shiftTabKey) {
        System.out.println("editing activated");
        table.setCellSelectionEnabled(true);
        InputMap input = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        input.remove(shiftTabKey);
        input.remove(tabKey);
        input.put(shiftTabKey, "selectPreviousColumnCell");
        input.put(tabKey, "selectNextColumnCell");
    }

    private void quitEditMode(JTable table, final KeyStroke tabKey, final KeyStroke shiftTabKey) {
        System.out.println("editing de-activated");
        table.setCellSelectionEnabled(false);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        InputMap input = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        input.remove(shiftTabKey);
        input.remove(tabKey);
        input.put(shiftTabKey, "tabBefore");
        input.put(tabKey, "tabNext");
    }

    // print a String representation of each KeyStroke from the InputMap
    private void printActions(JTable table) {
        InputMap input = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        if (input != null && input.allKeys() != null) {
            for (KeyStroke key : input.allKeys()) {
                if (key != null) {
                    printKeyStroke(key);
                    printActionName(input, key);
                }
            }
        }
    }

    // build the String represantation
    private void printKeyStroke(KeyStroke key) {
        StringBuilder tk = new StringBuilder("[");
        int modifiers = key.getModifiers();
        if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0)
            tk.append("shift+");
        if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0)
            tk.append("ctrl+");
        if ((modifiers & InputEvent.META_DOWN_MASK) != 0)
            tk.append("cmd+");
        if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0)
            tk.append("alt+");
        tk.append("'");
        tk.append(KeyEvent.getKeyText(key.getKeyCode()));
        tk.append("'=");
        tk.append("keycode=");
        tk.append(key.getKeyCode());
        tk.append("]");
        System.out.print(tk.toString());
    }

    private void printActionName(InputMap input, KeyStroke key) {
        System.out.print(": ");
        Object string = input.get(key);
        if (string != null && string instanceof String)
            System.out.println(string.toString());
    } 

}

通过对您的quitEditMode方法进行一些调整,您将获得想要的结果:

    private void quitEditMode(JTable table, final KeyStroke tabKey, final KeyStroke shiftTabKey) {
        System.out.println("editing de-activated");
        table.setCellSelectionEnabled(false);
        table.getCellEditor(table.getSelectedRow(), table.getSelectedColumn() ).stopCellEditing();
        table.setRowSelectionAllowed( true );
        table.setRowSelectionInterval( table.getSelectedRow(), table.getSelectedRow() );
        InputMap input = table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        input.remove(shiftTabKey);
        input.remove(tabKey);
        input.put(shiftTabKey, "tabBefore");
        input.put(tabKey, "tabNext");
    }

暂无
暂无

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

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