注意:这不是重复,我已经签出:I can't get my JTable to show anything和I get the Jtable but no data
虽然这些问题看起来非常相似,但它们与我所遇到的问题并不相同。让我解释一下:
我有一个GUI,其中有几个JTable从MySQL数据库中填充。在我的初始GUI上,表格工作正常。但是,有一次我将用户带到一个新的JFrame。在此框架上,由于某种原因,表格显示并填充了列名称,但没有数据。我不能为我的生活找出原因。
以下是我的第一个GUI中的代码:
iTable = new JTable(writeItemResult(res4));
iTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
iTable.getColumnModel().getColumn(0).setPreferredWidth(27);
iTable.getColumnModel().getColumn(1).setPreferredWidth(375);
iTable.getColumnModel().getColumn(2).setPreferredWidth(150);
iTable.getColumnModel().getColumn(0).setResizable(false);
sorter = new TableRowSorter<TableModel>(iTable.getModel());
iTable.setRowSorter(sorter);
JScrollPane scrollpane3 = new JScrollPane(iTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollpane3.setPreferredSize(new Dimension(500, 150));
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 16;
c.gridwidth = 6;
pane.add(scrollpane3, c);
我的writeItemResult方法:
public static DefaultTableModel writeItemResult (ResultSet res4) throws SQLException {
ResultSetMetaData metaData = res4.getMetaData();
Vector<String> columnNames = new Vector<String>();
int columnCount = metaData.getColumnCount();
for (int column = 1; column <= columnCount; column++) {
columnNames.add(metaData.getColumnName(column));
}
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while (res4.next()) {
Vector<Object> vector = new Vector<Object>();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
vector.add(res4.getObject(columnIndex));
}
data.add(vector);
}
return new DefaultTableModel(data, columnNames);
}
我的res4结果集:
statement2 = connect.createStatement();
res4 = statement2.executeQuery("SELECT id, prompt, type FROM items ORDER BY prompt");
所以,正如我所说,上面的代码WORKS对我的第一个JFrame很好。我的第一个JFrame的整个代码太大了,所以除非特别要求,否则我不会费心去粘贴它。
以下是我的第二个JFrame的完整代码,正如我所说,返回表和列名但没有数据:
} if (e.getSource() == design) {
int str = fTable.getSelectedRow();
int stc = fTable.getSelectedColumn();
if (stc != 0) {
JOptionPane.showMessageDialog(null, "Error: Please click the Form ID of the form you wish to modify.", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
selObj = (Object) fTable.getModel().getValueAt(str, stc);
try {
p_statement6.setString(1, selObj.toString());
res6 = p_statement6.executeQuery();
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
while (res6.next()){
formID1 = res6.getString("id");
formName1 = res6.getString("title");
}
} catch (SQLException e1) {
e1.printStackTrace();
}
int width = 900;
int height = 900;
designForm = new JFrame("Designer");
designForm.setSize(width,height);
pane = designForm.getContentPane();
pane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
if (shouldFill) {
//natural height, maximum width
c.fill = GridBagConstraints.HORIZONTAL;
}
des_name = new JLabel("<html><small>Designing: "+formName1+"</small></html>");
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
pane.add(des_name, c);
test = new JButton("Test");
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 1;
pane.add(test, c);
test.addActionListener(this);
designForm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension sD = Toolkit.getDefaultToolkit().getScreenSize();
designForm.setLocation((sD.width - width)/2, (sD.height-height)/2);
designForm.setResizable(true);
designForm.setVisible(true);
} if (e.getSource() == test) {
try {
iTable = new JTable(writeItemResult(res4));
iTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
iTable.getColumnModel().getColumn(0).setPreferredWidth(27);
iTable.getColumnModel().getColumn(1).setPreferredWidth(330);
iTable.getColumnModel().getColumn(2).setPreferredWidth(140);
iTable.getColumnModel().getColumn(0).setResizable(false);
sorter = new TableRowSorter<TableModel>(iTable.getModel());
iTable.setRowSorter(sorter);
JScrollPane scrollpane4 = new JScrollPane(iTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollpane4.setPreferredSize(new Dimension(500, 150));
JOptionPane.showMessageDialog(null, scrollpane4);
} catch (Exception e1) {
e1.printStackTrace();
}
}
如果你很好奇,p_statement6是:
p_statement6 = connect.prepareStatement("SELECT * from checklists where id = ?");
顺便说一句,我没有错误。
破桌图片:
工作表图片:
所以,这就是我觉得适用的一切。如果您需要更多信息,请随时提出。
感谢@peeskillet,我的问题的解决方案很简单:我试图使用一个耗尽的结果集。只需设置结果集Scroll_Insensitive和Concur_Updatable,问题就解决了。
答案 0 :(得分:1)
下面:
int str = fTable.getSelectedRow();
int stc = fTable.getSelectedColumn();
...
selObj = (Object) fTable.getModel().getValueAt(str, stc); // wrong indexes!!
这些索引属于 视图 。如果您想从表模型中获取值,则需要将它们转换为各自的 模型 索引:
selObj = fTable.getModel().getValueAt(fTable.convertRowIndexToModel(str), fTable.convertColumnIndexToModel(stc));
或者您可以直接从表中获得正确的选定值:
selObj = fTable.getValueAt(str, stc);
由于selObj.toString()
是查询参数,错误的值可能会导致空ResultSet
。因此,表格不会被填充。
请参阅:
我也会检查一下:
p_statement6 = connect.prepareStatement("SELECT * from checklists where id = ?");
p_statement6.setString(1, selObj.toString()); // is id a VARCHAR or is NUMERIC?
你说你这里没有任何错误,但是准备好的文章将被解析为:
SELECT * from checklists where id = '1';
如果id
列是VARCHAR,那么没关系,但如果它是某种数字类型,那么你可能会获得SQLException。
如果是这种情况,那么您需要将selObj
转换为Integer
并使用PreparedStatement.setInt(index, value)代替setString()
:
p_statement6.setInt(1, (Integer)selObj);
答案 1 :(得分:1)
您似乎尝试对两个表使用相同的ResultSet
。
new JTable(writeItemResult(res4));
这两个表都使用res4
。这样做的问题是,第一个工作正常,但它会耗尽ResultSet
的数据。数据已经完成。因此,在第二个rs.next()
中尝试writeItemResult(res4)
只能返回列标题,因为这只是元数据
默认的
ResultSet
对象不可更新,并且只有一个向前移动的游标。因此,您只能迭代一次,并且只能从第一行到最后一行。可以生成可滚动和/或可更新的ResultSet对象。以下代码片段(其中con是有效的Connection对象)说明了如何使结果集可滚动且对其他人的更新不敏感,并且可以更新。
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
static final int TYPE_SCROLL_INSENSITIVE
- 指示ResultSet对象类型的常量,该对象可滚动但通常对对ResultSet构成的数据的更改不敏感。static final int CONCUR_READ_ONLY
- 表示可能无法更新的ResultSet对象的并发模式的常量。因此,您必须执行上述操作才能使ResultSet
可滚动。然后你需要使用
void beforeFirst() throws SQLException
- 将光标移动到此ResultSet对象的前面,就在第一行之前。如果结果集不包含任何行,则此方法无效。因此,如果您只是将res4.beforeFirst()
放在writeItemResult()
中,它也适用于第二张表格。
另外,在旁注中,如果您希望表使用相同的数据,为什么不让它们共享相同的TableModel
?
table2.setModel(table1.getModel());
答案 2 :(得分:0)
替换
selObj = (Object) fTable.getModel().getValueAt(str, stc);
通过
selObj = (Object) fTable.getValueAt(str, stc);
和
iTable = new JTable(writeItemResult(res4));
通过
iTable = new JTable(writeItemResult(res6));