简体   繁体   English

JTable中JComboBox的可用性功能

[英]Usability features for JComboBox within JTable

I'm trying to build a table which includes JComboBoxes as both the renderer and editor components. 我正在尝试建立一个包含JComboBoxes作为渲染器和编辑器组件的表。 This mostly works fine, however there are two things I can't seem to solve. 这通常可以正常工作,但是有两件事我似乎无法解决。

  1. Tabbing between cells should make the JComboBox active 在单元格之间切换应使JComboBox处于活动状态
  2. Clicking the drop-down arrow should immediately open the option list 单击下拉箭头应立即打开选项列表

Regarding 1, the editable combo should place focus within the embedded text field, the fixed combo should allow the down arrow to open the list of options. 关于1,可编辑组合应该将焦点放在嵌入式文本字段内,固定组合应允许向下箭头打开选项列表。

Regarding 2, I find that this sometimes works depending on what other cell is currently active, but other times I have to double click. 关于2,我发现这有时会起作用,这取决于当前处于活动状态的其他单元格,但是有时我必须双击。 I cannot make this behaviour consistent. 我无法使这种行为保持一致。

For convenience I have included a clear example which (I believe) uses the recommended approach for embedding JComboBoxes within Jtables. 为了方便起见,我提供了一个明确的示例(我相信),该示例使用推荐的方法将JComboBoxes嵌入Jtables中。

Thank you for constructive advice. 感谢您的建设性建议。

import java.awt.Component;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableCombos
{
    public static void main(String[] args)
    {
        JFrame frame = new JFrame("Frame");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        AbstractTableModel model = new DefaultTableModel()
        {
            String[] columnHeaders = new String[]{"label", "combo-edit", "combo-fixed"};
            Class<?>[] columnClasses = new Class<?>[]{String.class, Double.class, Double.class};
            List<Object[]> data = new ArrayList<>();
            {
                data.add(new Object[]{"row 1", 1.0d, 2.0d});
                data.add(new Object[]{"row 2", 2.0d, 3.0d});
            }

            @Override
            public int getColumnCount()
            {
                return columnHeaders.length;
            }

            @Override
            public boolean isCellEditable(int row, int column)
            {
                return column != 0;
            }

            @Override
            public int getRowCount()
            {
                if (data == null) // race condition
                    return 0;
                return data.size();
            }

            @Override
            public Object getValueAt(int row, int column)
            {
                return data.get(row)[column];
            }

            @Override
            public void setValueAt(Object aValue, int row, int column)
            {
                data.get(row)[column] = aValue;
            }

            @Override
            public Class<?> getColumnClass(int column)
            {
                return columnClasses[column];
            }

            @Override
            public String getColumnName(int column)
            {
                return columnHeaders[column];
            }
        };

        JTable table = new JTable(model);
        table.setSurrendersFocusOnKeystroke(true);

        TableColumn c1 = table.getColumnModel().getColumn(1);
        TableColumn c2 = table.getColumnModel().getColumn(2);

        JComboBox<Double> editorComboEditable = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d});
        editorComboEditable.setEditable(true);
        c1.setCellEditor(new DefaultCellEditor(editorComboEditable));
        c2.setCellEditor(new DefaultCellEditor(new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d})));

        final JComboBox<Double> rendererComboEditable = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d});
        rendererComboEditable.setEditable(true);
        final JComboBox<Double> rendererComboFixed = new JComboBox<>(new Double[]{1.0d, 2.0d, 3.0d});
        c1.setCellRenderer(new TableCellRenderer()
        {
            @Override
            public Component getTableCellRendererComponent(JTable t, Object value, boolean isSelected, boolean hasFocus, int row, int column)
            {
                rendererComboEditable.setSelectedItem(value);
                return rendererComboEditable;
            }
        });
        c2.setCellRenderer(new TableCellRenderer()
        {
            @Override
            public Component getTableCellRendererComponent(JTable t, Object value, boolean isSelected, boolean hasFocus, int row, int column)
            {
                rendererComboFixed.setSelectedItem(value);
                return rendererComboFixed;
            }
        });

        frame.getContentPane().add(new JScrollPane(table));

        frame.pack();
        frame.setVisible(true);
    }
}

Both of your issues be resolved by overriding the DefaultCellEditor#isCellEditable method and returning true 通过重写DefaultCellEditor#isCellEditable方法并返回true可以解决两个问题

You may need to set JTable#setSurrendersFocusOnKeystroke to true as well 您可能还需要将JTable#setSurrendersFocusOnKeystroke设置为true

Update 更新资料

The short answer is "It's messy". 简短的回答是“很乱”。 The long answer is "it's very messy" 长答案是“这很混乱”

I did a "continuos editing" process some time back. 不久前,我做了一个“持续编辑”过程。 Basically, I overrode the Enter and Tab key bindings. 基本上,我覆盖了EnterTab键的绑定。

What I'd did was basically stop any active cell editor, take note of the current cell and then tried to finding the next editable cell, looping back around to the start (cell 0x0) if required. 我所做的基本上是停止任何活动的单元格编辑器,记下当前单元格,然后尝试查找下一个可编辑的单元格,并根据需要循环回到起始位置(单元格0x0)。

When I found a editable cell, I called JTable#esitCellAt to start editing the cell. 找到可编辑单元格后,我调用了JTable#esitCellAt开始编辑该单元格。

To get the popup to be visible when the cell starts editing, you will need to override the addNotify method of the JComboBox and, using SwingUtilities#invokeLater , set the popup visible 为了使该弹出窗口在单元格开始编辑时可见,您将需要重写JComboBoxaddNotify方法,并使用SwingUtilities#invokeLater将弹出窗口设置为可见

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

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