【问题标题】:JComboBox in JTable display invalid dataJTable中的JComboBox显示无效数据
【发布时间】:2014-09-08 06:34:23
【问题描述】:

我有一个JTable,我根据数据库select 查询动态填充其列。此JTable 的一列将接受JComboBox。现在,请看下面的代码。

private class ViewClientsDisplayData extends ComponentAdapter
     {
        @Override
        public void componentShown(ComponentEvent e) 
        {
            dbConnector = new DBHandler();
            dbConnector.makeConnection();

            ResultSet rs =  dbConnector.selectAllDetails("select client_id, Name from Client");

            DefaultTableModel model = (DefaultTableModel) ViewClientsTable.getModel();
            model.setRowCount(0);

            try {
                if(rs.isBeforeFirst()==false)
                {
                    JOptionPane.showMessageDialog(null,"The table is empty");
                }
                else
                {
                    try
                    {
                        while(rs.next())
                        {
                            int id = rs.getInt("client_id");
                            String name = rs.getString("Name");

                            ResultSet getPortfolios =  dbConnector.selectAllDetails("select portfolio_id from Portfolio where Client_Name = '"+name+"'");
                            JComboBox combo = new JComboBox();
                            combo.removeAllItems();

                            while(getPortfolios.next())
                            {
                                combo.addItem(getPortfolios.getString("portfolio_id"));
                            }

                            JButton update = new JButton("Update");
                            JButton delete = new JButton("Delete");

                            JPanel btnPanel = new JPanel();
                            btnPanel.setLayout(new FlowLayout());
                            btnPanel.add(update);
                            btnPanel.add(delete);


                            Object[]row = {id, name, 0, "", new ButtonColumn(ViewClientsTable,null,"delete",4)};

                            model.addRow(row);
                            ViewClientsTable.getColumn("Portfolio").setCellEditor(new DefaultCellEditor(combo));

                        }
                        dbConnector.closeConnection();
                    }
                    catch(SQLException sqlE)
                    {
                        sqlE.printStackTrace();
                        JOptionPane.showMessageDialog(null,sqlE.getLocalizedMessage());
                        dbConnector.closeConnection();
                    }
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
     }

dbConnector.selectAllDetails() 方法

public ResultSet selectAllDetails(String query)
    {
        ResultSet r = null;
        try
        {
            Statement st = con.createStatement();

            r = st.executeQuery(query);
        }
        catch(SQLException sql)
        {
            sql.printStackTrace();
        }

        return r;
    }

这里的问题是我的JComboBox 没有按预期填充。它应该根据提供的搜索查询填充数据,但是,它会在所有行中显示相同的项目,即项目 03 是客户名称 AAA 的投资组合 ID em>。

下面是我的client 表(带有虚拟输入)

下面是我的Portfolio 表(带有虚拟输入)

为什么会这样?为什么JComboBox 不显示相关数据,而是重复相同的数据?

PS:我知道我们不应该根据 name 进行搜索,但我们应该从 ``unique id` 进行搜索,但这是对 SO 帖子的快速编辑。

【问题讨论】:

  • 不要将组件放入模型中,您的模型应该只保存数据。列的渲染是渲染器的责任,应该单独应用于表格......
  • 这里经常被问到,JDBC 没有,MadProgrammer 的评论比他的回答要好

标签: java swing jdbc jtable jcombobox


【解决方案1】:

首先将数据与视图分离,模型数据不应包含任何类型的 UI 组件或 UI 相关信息。做出这些决定不是模型的责任。模型携带数据,仅此而已。

表格中的单个单元格只包含一个值,无论它可能设置为什么。它只携带一个状态或值。

值在屏幕上的表现方式是渲染器的领域,值的修改方式是编辑器的领域。

构建你的TableModel 并用数据填充它,将其传递给JTable,它已经配置了所需的渲染器和编辑器来显示和编辑你的数据...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

public class TableComboBox {

    public static void main(String[] args) {
        new TableComboBox();
    }

    public TableComboBox() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                DefaultTableModel model = new DefaultTableModel(new Object[]{"A", "B", "C", "D"}, 5);
                JTable table = new JTable(model);

                JComboBox bCombo = new JComboBox(new Object[]{"Apples", "Bannans", "Pears", "Grapes"});
                JComboBox cCombo = new JComboBox(new Object[]{"Elephants", "Monkeys", "Cats", "Dogs"});
                JComboBox dCombo = new JComboBox(new Object[]{"Unicorns", "Dragons", "Pixis", "Blobs"});

                DefaultCellEditor bEditor = new DefaultCellEditor(bCombo);
                DefaultCellEditor cEditor = new DefaultCellEditor(cCombo);
                DefaultCellEditor dEditor = new DefaultCellEditor(dCombo);

                TableColumnModel cm = table.getColumnModel();
                cm.getColumn(1).setCellEditor(bEditor);
                cm.getColumn(2).setCellEditor(cEditor);
                cm.getColumn(3).setCellEditor(dEditor);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

查看How to Use TablesUsing Other EditorsConcepts: Editors and Renderers了解更多详情

【讨论】:

  • OP 缺少对 setValueAt 与 rendere/editor 初始值的更好解释,这是主要问题,但因为 OP 总是在这里忽略 SO 规则
  • @mKorbel 老实说,我不认为 OP 了解 MVC 的基础知识
  • +1 s/he 只需要回答,(你没有发送它),但是 the_same_answer_like_as_question
【解决方案2】:

如果您在 JTable 中显示此 JCombobox,则应根据行在 JComboBox 中设置正确的值。 为此,我通常使用我扩展的 AbstractTableModel。 在 getValueAt 方法中,你得到一个 rowindex 和 columnindex,你应该使用行索引来正确初始化 JComboBox。 Als 为每个显示的行使用单独的 JComboBox。

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    Object value = null;
    if(rowIndex > rows.size())
        return null;
    Item item = rows.get(rowIndex);

    switch (columnIndex) {
    case 0: //Your combobox
        JComboBox value= new JComboBox(listitems);
        jc.setSelectedItem(item.name);
        break;

.......

    return value;
}

我希望这会有所帮助。

【讨论】:

  • 仅供参考:在模型中放置 UI 组件是绝对不可接受的
猜你喜欢
  • 2016-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
相关资源
最近更新 更多