带 JComboBox 编辑器的 JTable:是否可以通过一键按下键盘来编辑单元格值

发布于 2024-08-19 11:57:24 字数 769 浏览 6 评论 0原文

我有一个包含 JComboBox 编辑器的 JTable 初始化有点像

JComboBox comboBox = ...;
TableColumn tc = table.getColumnModel().getColumn(i);
tc.setCellEditor(new DefaultCellEditor(comboBox));

This 工作正常,但我希望能够在表中导航并仅使用键盘更新值。现在,组合框可以做到这一点,但如果我想更新值“1”,我必须首先按一个键激活组合框,然后按“1”选择该项目。

所以,我想要的是我可以按“1”,并且只需按一下键即可选择该项目。

对于文本单元格,我已经设法使用prepareEditor 来完成此操作,如下所示......

@Override
public Component prepareEditor(TableCellEditor editor, int row, int column) {
    Component c = super.prepareEditor(editor, row, column);
    if (c instanceof JTextComponent) {
        ((JTextComponent) c).selectAll();
    } 
    return c;
}

但我还没有设法弄清楚如何处理组合框。

一种可能性可能是自己的 TableCellEditor 但如果有一个更简单的解决方案那就太好了 =)

br, 灯子

I'm having a JTable containing JComboBox editors initialized somewhat like

JComboBox comboBox = ...;
TableColumn tc = table.getColumnModel().getColumn(i);
tc.setCellEditor(new DefaultCellEditor(comboBox));

This is working otherwise fine but I'd like to be able to navigate in the table and update the values with keyboard only. Now this is possible with the combo boxes but if I want to update the value "1" I must first press a key to activate the combo box and then press "1" to select the item.

So, what I want is that I could press "1" and the item would be selected with only one key press.

For the text cells I've managed to do this with prepareEditor like the following...

@Override
public Component prepareEditor(TableCellEditor editor, int row, int column) {
    Component c = super.prepareEditor(editor, row, column);
    if (c instanceof JTextComponent) {
        ((JTextComponent) c).selectAll();
    } 
    return c;
}

... but I haven't managed to figure out what to do with the combo box.

One possibility could be own TableCellEditor but if there's a more simple solution that would be nice =)

br,
Touko

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不再让梦枯萎 2024-08-26 11:57:24

如果有人仍然感兴趣,我对 Touko 的代码做了一个简单的修改,这对我有用:

public class CustomTable extends JTable {
    private static final long serialVersionUID = -8855616864660280561L;

    public CustomTable(TableModel tableModel) {
        super(tableModel);
    }

    @Override
    public Component prepareEditor(TableCellEditor editor, int row, int column) {
        final Component comp =  super.prepareEditor(editor, row, column);

        // Text component should select all text when initiated for editing.
        if (comp instanceof JTextComponent)
            ((JTextComponent) comp).selectAll();

        // Try to obtain focus for the editor component.
        SwingUtilities.invokeLater(new Runnable() {
            @Override public void run() { comp.requestFocusInWindow(); }
        });

        return comp;
    }
}

所以基本上,我只是在稍后使用 SwingUtilities.invokeLater 请求编辑器组件的焦点。采用这种方法的原因是,如果编辑器组件尚不可见,焦点请求将会失败。

希望这可以帮助任何人。

In case anyone is still interested, I do a simple modification to Touko's code and this works for me:

public class CustomTable extends JTable {
    private static final long serialVersionUID = -8855616864660280561L;

    public CustomTable(TableModel tableModel) {
        super(tableModel);
    }

    @Override
    public Component prepareEditor(TableCellEditor editor, int row, int column) {
        final Component comp =  super.prepareEditor(editor, row, column);

        // Text component should select all text when initiated for editing.
        if (comp instanceof JTextComponent)
            ((JTextComponent) comp).selectAll();

        // Try to obtain focus for the editor component.
        SwingUtilities.invokeLater(new Runnable() {
            @Override public void run() { comp.requestFocusInWindow(); }
        });

        return comp;
    }
}

So basically, I'm just requesting focus for the editor component at some later time using SwingUtilities.invokeLater. The reason for this approach is because focus request will fail if the editor component is not yet visible.

Hope this can help anyone.

岛徒 2024-08-26 11:57:24

您必须将 KeyListener 添加到您的代码中。

最好的解决方案是将其添加到放置 JComboBoxJTable 组件中,并实现方法 keyPressed(KeyEvent e)>keyReleased(KeyEvent e) 是为了知道哪个是关键并执行必要的操作。

这里我给你举个例子:

JTable table = new JTable();

// Your necessary code (create combo box, cell editor...etc)

table.addKeyListener(new KeyListener() {

    public void keyTyped(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        switch(keyCode) {
        case KeyEvent.VK_1:
            // manage key 1
            break;
        case KeyEvent.VK_A:
            // manage key A
            break;
        case KeyEvent.VK_F1:
            // manage key F1
            break;
        case KeyEvent.VK_TAB:
            // manage key TAB
            break;
        default:
            // manage other keys
        }
    }
});

你也可以将此解决方案与字典结合起来,字典将 keyCode 与操作界面相关联。

第二个解决方案需要以下代码:
全局属性(字典):

Map<Integer,MyAction> keyActions = new Hashmap<Integer,MyAction>();

自己的操作接口:

public interface MyAction {

    public void doAction();
}

KeyListener.keyPressed() 函数如下:

public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    MyAction ma = keyActions.get(keyCode);
    if (ma != null) {
        ma.doAction();
    }
    else {
        // do default action for other keys
    }
}

我希望这对您有帮助。

问候!

You must add a KeyListener to your code.

The best solution is add it to the JTable component where you are laying the JComboBox and implement the method keyPressed(KeyEvent e) or the keyReleased(KeyEvent e) one in order to know which is the key and do the necessary action.

Here I give you an example:

JTable table = new JTable();

// Your necessary code (create combo box, cell editor...etc)

table.addKeyListener(new KeyListener() {

    public void keyTyped(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        switch(keyCode) {
        case KeyEvent.VK_1:
            // manage key 1
            break;
        case KeyEvent.VK_A:
            // manage key A
            break;
        case KeyEvent.VK_F1:
            // manage key F1
            break;
        case KeyEvent.VK_TAB:
            // manage key TAB
            break;
        default:
            // manage other keys
        }
    }
});

You also can combine this solution with a dictionary which relates the keyCode with an action interface.

This second solution needs the following code:
A global attribute (the dictionary):

Map<Integer,MyAction> keyActions = new Hashmap<Integer,MyAction>();

A own action interface:

public interface MyAction {

    public void doAction();
}

And the KeyListener.keyPressed() function would be the following:

public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    MyAction ma = keyActions.get(keyCode);
    if (ma != null) {
        ma.doAction();
    }
    else {
        // do default action for other keys
    }
}

I hope this helps you.

Regards!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文