【问题标题】:JTable JComboBox is defaulting to display 1st item when list is expanded当列表展开时,JTable JComboBox 默认显示第一项
【发布时间】:2015-02-23 01:10:12
【问题描述】:

我一直在尝试确定为什么我的 JComboBox 通过大量 Google 搜索显示列表中的第一项,但我很难找到相关帮助。可能是我不知道正确的术语(因此这个问题的标题过于具体),因此找不到可以解释我的问题的信息。我检查了 JComboBox API,以及它使用的一些侦听器和模型,但它们似乎不太可能成为候选人。

有问题的 JComboBox 在 JTable 中,所以我不知道这是否会改变它的默认行为。我使用的代码如下:

//row and col are final due to usage inside anonymous inner class
public TableCellEditor getCellEditor(final int row, final int col)
{
    String[] listItems = new String[arrayList.getSize()];
    int i = -1;

    for(String s : arrayList)
    {
        i++;
        listItems[i] = s;
    }

    JComboBox<String> box = new JComboBox<>(listItems);
    box.addItemListener(new ItemListener()
    {
        public void itemStateChanged(ItemEvent e)
        {
            if(e.getStateChange() == ItemEvent.SELECTED)
            {
                if(e.getItem().equals("Add/Edit Projectile"))
                {
                    //Where Editor is a JFrame that will be opened 
                    new Editor();
                }
            }
        }
    });

    DefaultCellEditor list = new DefaultCellEditor(box);
}

请注意,我的程序中的 Arraylist 不包含字符串,而是一组更复杂的自定义对象,我认为这会分散主要问题的注意力。

我没有在 JTable 中包含 JComboBox 的渲染器,因为我对它的出现方式感到非常满意,并且认为我的问题更多是我忽略了在模型中实现/实现的错误。

我还提供了一些屏幕截图来更好地描述我的问题。第一个图像是未选择 JComboBox 时的图像,仅显示当前选定的项目。

第二张图片是当我刚刚单击 JComboBox 以显示列表时。如图所示,无论它是什么,它都会立即调出第一个项目。

如果有人对在哪里查看/解决方案有任何建议,我将不胜感激。


编辑

我的特定表有两列,其中左列是变量名,右列是与变量关联的值。表格的作用是显示选定对象的属性,其中不同对象的不同变量的每个值可能不一样。

在这种特殊情况下,单元格显示一个 JComboBox,其中包含我们正在制作的游戏中的所有可用 Projectiles。每个敌人都有不同类型的默认投射物。因此,当我在我们的游戏区域中单击不同的敌人时,表格将显示它们当前的所有属性(如果它们没有被更改,则为默认值)。

敌人确实有一个用于射弹的吸气剂,所以我可以确定当前选择的敌人是什么,获取它的射弹,执行 toString() 以查找它在列表中的表示方式,然后执行 setValueAt() .

目前唯一的问题是,当列表展开时,它总是选择列表中的第一项。

【问题讨论】:

  • 首先,不要使用ItemListener in the CellEditor, add a TableModelListener` 到TableModel 并监视单元格值的更改。其次,JComboBox 还应该显示什么?您尚未将所选值设置为任何值...
  • 我将切换到 TableModelListener。这样做有什么特别的好处,不管它们是否与我的问题有关?总是很高兴学习更好的编程实践!该表实际上应该只显示列表中每个项目中表示的自定义对象的 toString()。唯一需要跟踪的事件是单击“添加/编辑弹丸”项目时,因为这需要调出一个新的 JDialog。除此之外,它们只是后端数据的简单表示。
  • 主要原因是,当用户做出选择时,决定应该发生什么不是编辑器或模型的责任。编辑器负责允许用户选择或更改单元格的值,模型负责管理数据
  • 这很有道理,我会记住这一点,以备将来实施。我还将确保更改当前表的实现,使其符合此范例。非常感谢你!

标签: java swing jtable jcombobox jlist


【解决方案1】:

除非JComboBox 的值是为每一行动态生成的,否则您应该能够提前准备CellEditor,例如...

JComboBox cb = new JComboBox(new String[]{"1", "2", "3", "4"});
DefaultCellEditor editor = new DefaultCellEditor(cb);

JTable table = new JTable(new DefaultTableModel(5, 1));
table.getColumnModel().getColumn(0).setCellEditor(editor);

这会将编辑器的选定值设置为编辑过程开始时单元格的值

更新

在每行动态生成组合框值的情况下,您可以执行类似...

JComboBox cb = new JComboBox();
DefaultCellEditor editor = new DefaultCellEditor(cb) {

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        JComboBox editor = (JComboBox) getComponent();
        String[] listItems = new String[arrayList.getSize()];
        int i = -1;
        for (String s : arrayList) {
            i++;
            listItems[i] = s;
        }

        DefaultComboBoxModel model = new DefaultComboBoxModel(listItems);
        editor.setModel(model);
        editor.setSelectedItem(value);
        return editor;
    }
};

JTable table = new JTable(new DefaultTableModel(5, 1));
table.getColumnModel().getColumn(0).setCellEditor(editor);

注意editor.setSelectedItem(value);的使用,这会将选定的值设置为单元格当前值...

您还可以重复使用该模型,每次都将其清除并用新值重新填充它。如果您有大量行,您可能会发现这更有效,因为您不需要在每次编辑单元格时不断创建新模型

【讨论】:

  • 我将编辑我的问题,因为这实际上不适用于我的情况。简而言之,基本上所有的行都是不同的,只有两列。每行可能有不同的单元格编辑器和渲染器。我现在会更新问题,看看它是否会改变我实施修复的方式。
  • @Stevo 使用动态行值更新
  • 当列表展开时,我仍然遇到第一个值显示为所选项目的问题。我不知道这是否会改变问题,但该值仅在列表扩展期间显示为该值。在您单击远离 JComboBox 以使其不选择值后,它将返回显示正确的值。这有意义吗,还是我只是把事情弄糊涂了?如果需要澄清,我可以在原始帖子中添加另一张图片。
  • 考虑提供一个runnable example 来证明您的问题。这不是代码转储,而是您正在做的事情的一个示例,它突出了您遇到的问题。这将导致更少的混乱和更好的响应
  • 好的,我已经阅读了您在上一条评论中提供的链接,因此我将着手提供一个快速示例。完成后,我会将其添加到我的原始帖子中。干杯
【解决方案2】:

这是一个老歌......

您的问题很可能是您没有在组合中使用的类中实现“等于”。

Combo 需要在准备时选择当前项,并通过迭代模型的元素并选择与单元格中的值相等的第一个元素来实现。如果没有遇到,则将组合保持原样(前一个单元格编辑中的第一个元素或最后使用的元素)

【讨论】:

  • 太棒了。它有帮助。
【解决方案3】:

这是您应该默认使用先前选择的元素的方式:

//...
Object selectedItem = box.getSelectedItem();
//Add some elements to the jComboBox
box.setSelectedItem(selectedItem);

【讨论】:

  • 由于 OP 只完成了JComboBox&lt;String&gt; box = new JComboBox&lt;&gt;(listItems); 而不添加任何更多值,因此除了保留当前选择的项目之外,它不会做太多事情,这可能是第一个项目......跨度>
  • 是否应该将这段特定的代码添加到 PopMenuListener() 中?所以如果我点击JComboBox,我假设监听器会收到通知,然后我会在那里设置当前选择的值?
  • 关于我的问题中的 MadProgrammer 的 cmets,我如何将这个特殊的想法应用于 TableModelListener?还是这些想法不相容?
  • @Stevo 它们是程序的不同部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-17
  • 1970-01-01
  • 2018-08-04
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多