如何从 table 对象将 SelectedItem 或 setSelectedIndex 设置为 DefaultComboBoxModel

How to setSelectedItem OR setSelectedIndex to DefaultComboBoxModel from table object

Class组合项

public class ComboItems {

    private Long key;
    private String value;

    public ComboItems(Long key, String value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public String toString() {
        return value;
    }

    public Long getKey() {
        return key;
    }

    public String getValue() {
        return value;
    }
}

将Class ComboItem 设置为ComboBox

private void loadSupplier(FormBuy formBuy) {
        List<Supplier> suppliers = supplierJdbc.selectSuppliers("%%");
        DefaultComboBoxModel defaultComboBoxModel = new DefaultComboBoxModel();
        suppliers.forEach(supplier -> {
            defaultComboBoxModel.addElement(new ComboItems(supplier.getId(), supplier.getName()));
        });
        formBuy.getjComboBoxSupplier().setModel(defaultComboBoxModel);
    }

显示给 DefautTableModel

    private void loadTable(DefaultTableModel defaultTableModel, FormBuy formBuy) {
            defaultTableModel.getDataVector().removeAllElements();
            defaultTableModel.fireTableDataChanged();
            

List<ResponseListTableBuy> buys = buyJdbc.selectBuys("%" + formBuy.getjTextFieldSearch().getText() + "%");
        Object[] objects = new Object[10];
        for (ResponseListTableBuy buy : buys) {
            objects[0] = buy.getId();
            objects[1] = buy.getSupplier().getName();
            objects[2] = buy.getCategory().getName();
            objects[3] = buy.getItem().getName();
            objects[4] = buy.getUnit().getName();
            objects[5] = buy.getCountItem();
            objects[6] = buy.getBuyPrice();
            objects[7] = new BigDecimal(buy.getCountItem() * buy.getBuyPrice().intValue());
            objects[8] = buy.getSellPrice();
            objects[9] = buy.getDate();
            defaultTableModel.addRow(objects);
        }
}

目前为止还好!。我输入这段代码时出错

从 table 获取代码到组合框

formBuy.getjComboBoxSupplier().getModel().setSelectedItem(defaultTableModel.getValueAt(formBuy.getjTableBuy().getSelectedRow(), 1).toString());

并将其作为错误

System.out.println(((ComboItems) formBuy.getjComboBoxSupplier().getModel().getSelectedItem()).getKey());

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.String cannot be cast to aliimron.combobox.ComboItems
    at aliimron.controller.ControllerBuy.mouseClicked(ControllerBuy.java:97)
    at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:270)
    at java.awt.Component.processMouseEvent(Component.java:6542)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6304)
    at java.awt.Container.processEvent(Container.java:2239)
    at java.awt.Component.dispatchEventImpl(Component.java:4889)
    at java.awt.Container.dispatchEventImpl(Container.java:2297)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4544)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476)
    at java.awt.Container.dispatchEventImpl(Container.java:2283)
    at java.awt.Window.dispatchEventImpl(Window.java:2746)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
    at java.awt.EventQueue.access0(EventQueue.java:97)
    at java.awt.EventQueue.run(EventQueue.java:709)
    at java.awt.EventQueue.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
    at java.awt.EventQueue.run(EventQueue.java:733)
    at java.awt.EventQueue.run(EventQueue.java:731)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

所以流程是从组合项到组合框再到 table 然后从 table 返回到组合框。你如何将它从 table 返回到组合框

因此,您使用...构建模型

defaultComboBoxModel.addElement(new ComboItems(supplier.getId(), supplier.getName()));

这很好,你将信息封装到一个对象中,但是,然后你使用

formBuy.getjComboBoxSupplier().getModel().setSelectedItem(defaultTableModel.getValueAt(formBuy.getjTableBuy().getSelectedRow(), 1).toString());

等等,太多了,让我们看看能不能稍微清理一下...

formBuy
    .getjComboBoxSupplier()
    .getModel()
    .setSelectedItem(
        defaultTableModel.getValueAt(
            formBuy.getjTableBuy().getSelectedRow(), 1
        ).toString()
    );

所以,基本上,您正在尝试使用 String 来设置模型的值,但模型需要 ComboItems 的实例 ...

所以,你有几个选择...

#1。你可以...

TableModel 提供 ComboItems,然后使用自定义单元格渲染器渲染它,然后您可以使用诸如...

formBuy
    .getjComboBoxSupplier()
    .getModel()
    .setSelectedItem(
        (ComboItems)defaultTableModel.getValueAt(
            formBuy.getjTableBuy().getSelectedRow(), 1
        )
    );

设置选中的组合框项目。

为了我的钱,这是更“正确”的方法,请参阅

了解更多详情

#2。你可以...

根据 table 中的 String 直接在模型中查找项目。

可能是这样的...

String value = (String)defaultTableModel.getValueAt(formBuy.getjTableBuy().getSelectedRow(), 1);

DefaultComboBoxModel model = formBuy.getjComboBoxSupplier().getModel()
for (int index = 0; index < model.getSize(); index++) {
    ComboItems items = (ComboItems) model.getElementAt(index);
    if (items.getValue().equalsIgnoreCase(value)) {
        formBuy
            .getjComboBoxSupplier()
            .getModel()
            .setSelectedItem(items);
        break;
    }
}

但老实说,您最好选择选项 #1

扩展...

我可能关注的一件事是尝试以更有意义的方式将您的数据联系在一起,这样您就不需要进行这些“侧面查找”,例如,您的数据似乎是可以表示为 key/value 对,让我们从这里开始......

public interface KeyValueExpressible {
    public String getKey();
    public String getValue();
}

public abstract class AbstractKeyValue implements KeyValueExpressible {
    private String key;
    private String value;

    public AbstractKeyValue(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return key;
    }

    public String getValue() {
        return value;
    }
    
}

好的,但这对您有何帮助?那么,现在您可以将约束缩小到实际数据类型,例如...

public class Supplier extends AbstractKeyValue {

    public Supplier(String key, String value) {
        super(key, value);
    }
    
}

巧妙的是,这仍然可以在您需要的任何地方使用 KeyValueExpressible,但可以在您需要 Supplier 时提供更精细的级别约束,sweet

现在您可以使用诸如...

之类的方法构建组合框
List<Supplier> suppliers = supplierJdbc.selectSuppliers("%%");
DefaultComboBoxModel<KeyValueExpressible> defaultComboBoxModel = new DefaultComboBoxModel<>();
suppliers.forEach(supplier -> {
    defaultComboBoxModel.addElement(supplier);
});
formBuy.getjComboBoxSupplier().setModel(defaultComboBoxModel);

nb: DefaultComboBoxModel<KeyValueExpressible> 也可以是 DefaultComboBoxModel<Supplier>,但是 DefaultComboBoxModel<KeyValueExpressible> 允许我们做很酷的魔术,比如...

public class KeyValueExpressibleListCellRenderer extends DefaultListCellRenderer {
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        if (value instanceof KeyValueExpressible) {
            KeyValueExpressible keyValue = (KeyValueExpressible) value;
            setText(keyValue.getValue());
        }
        return this;
    }
}
// Why doesn't DefaultListCellRenderer support generics 

然后可以使用类似...

JComboBox<KeyValueExpressible> comboBox = new JComboBox<>(defaultComboBoxModel);
comboBox.setRenderer(new KeyValueExpressibleListCellRenderer());

这是一个很好的可重复使用的,甜蜜的。

现在,我们可以开始扩展这个概念,例如,假设我们有类似...

public interface ResponseListTableBuy {
    public String getId();
    public Supplier getSupplier();
    //...
}

然后我们可以封装TableModel,比如...

public class BuyTableModel extends AbstractTableModel {
    
    private List<ResponseListTableBuy> buys;
    
    private String[] columnNames = new String[]{
        "id",
        "Supplier",
        "Category",
        "Item",
        "Unit",
        "Count",
        "Buy price",
        "Total",
        "Sell price",
        "Date"
    };

    public BuyTableModel(List<ResponseListTableBuy> buys) {
        this.buys = buys;
    }

    @Override
    public int getRowCount() {
        return buys.size();
    }

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

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

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0: return String.class;
            case 1: return KeyValueExpressible.class;
            case 2: return KeyValueExpressible.class;
            case 3: return KeyValueExpressible.class;
            case 4: return KeyValueExpressible.class;
            case 5: return Integer.class;
            case 6: return Double.class;
            case 7: return BigDecimal.class;
            case 8: return Double.class;
            case 9: return LocalDate.class;
        }
        return String.class;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        ResponseListTableBuy buy = buys.get(rowIndex);
        switch (columnIndex) {
            case 0: return buy.getId();
            case 1: return buy.getSupplier();
            case 2: return buy.getCategory();
            case 3: return buy.getItem();
            case 4: return buy.getUnit();
            case 5: return buy.getCountItem();
            case 6: return buy.getBuyPrice();
            // This should be a computed porperty, just saying...
            case 7: return new BigDecimal(buy.getCountItem() * buy.getBuyPrice().intValue());;
            case 8: return buy.getSellPrice();
            case 9: return buy.getDate();
        }
    }
    
}

然后……

public class KeyValueExpressibleTableCellRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        if (value instanceof KeyValueExpressible) {
            KeyValueExpressible keyValue = (KeyValueExpressible) value;
            setText(keyValue.getValue());
        }
        return this;
    }
    
}

更多魔法!

您可以使用类似...

的方法来应用它
JTable table = new JTable();
table.setDefaultRenderer(KeyValueExpressible.class, new KeyValueExpressibleTableCellRenderer());

突然间,您所说的每一列都是 KeyValueExpressible.class 将通过此渲染器渲染!甜!

我们已经在模型中封装了数据;我们有视图以所需的方式和需要时呈现数据...我们可以做到...

formBuy
    .getjComboBoxSupplier()
    .getModel()
    .setSelectedItem(
        (KeyValueExpressible)defaultTableModel.getValueAt(
            formBuy.getjTableBuy().getSelectedRow(), 1
        )
    );

nb:您可以让 BuyTableModel 为您进行试镜,但我想我可能已经让您大吃一惊

一个巧妙的小技巧...

您可能会发现自己处于这样一种情况,即您有两个实例 KeyValueExpressible 表示相同的数据(您可以使用一个公共工厂来管理它,但那是另一个话题)。

在这些情况下,您需要一些方法来判断这两个实例是相同的,这就是 equalshashCode 出现的地方,例如...

public abstract class AbstractKeyValue implements KeyValueExpressible {

    private String key;
    private String value;

    public AbstractKeyValue(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return key;
    }

    public String getValue() {
        return value;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj instanceof KeyValueExpressible) {
            return false;
        }
        KeyValueExpressible keyValue = (KeyValueExpressible) obj;
        return keyValue.getKey().equals(getKey()) && keyValue.getValue().equals(getValue());
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 29 * hash + Objects.hashCode(this.key);
        hash = 29 * hash + Objects.hashCode(this.value);
        return hash;
    }
    
}

现在,具有相同 keyvalue 的任何两个实例都将相等,亲爱的!

现在,如果您更愿意收紧约束,您也可以执行类似...

public class Supplier extends AbstractKeyValue {

    public Supplier(String key, String value) {
        super(key, value);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Supplier) {
            return false;
        }
        return super.equals(obj);
    }

}

现在只有两个具有相同 key/value 的 Supplier 会相等,亲爱的!