我编写了一个管理MySQL数据库的GUI Java程序。用户选择他/她想用JT填充JTable的列(从数据库中选择哪些表和列)。
我对JTable的列名进行了硬编码,因此即使用户选择仅显示列子集中的数据,也会显示所有列名。
问题在于,当用户选择的列数与JTable预期的顺序不同时,数据会显示在错误的列中。这有点难以解释,所以这里的屏幕截图是将类型数据加载到长度列中:
tableGenerator类:
package gui;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Vector;
public class TableGenerator
{
private ArrayList columnNames = new ArrayList();
private ArrayList data = new ArrayList();
private Vector columnNamesVector = new Vector();
private Vector dataVector = new Vector();
private int columns = 0;
private int rows = 0;
@SuppressWarnings("unchecked")
public TableGenerator(ResultSet rs)
{
try{
ResultSetMetaData md = rs.getMetaData();
columns = md.getColumnCount();
// Get column names
columnNames.add("Title");
columnNames.add("Year");
columnNames.add("Length");
columnNames.add("Genre");
columnNames.add("Actor");
columnNames.add("Producer");
columnNames.add("Director");
columnNames.add("Writer");
// Get row data
while (rs.next())
{
ArrayList row = new ArrayList(columnNames.size());
for (int i = 1; i <= columns; i++)
{
row.add(rs.getObject(i));
}
data.add( row );
rows++;
}
}
catch (SQLException e)
{
System.out.println( e.getMessage() );
}
// Create Vectors and copy over elements from ArrayLists to them
// Vector is deprecated but I am using them in this example to keep
// things simple - the best practice would be to create a custom defined
// class which inherits from the AbstractTableModel class
for (int i = 0; i < data.size(); i++)
{
ArrayList subArray = (ArrayList)data.get(i);
Vector subVector = new Vector();
for (int j = 0; j < subArray.size(); j++)
{
subVector.add(subArray.get(j));
}
dataVector.add(subVector);
}
for (int i = 0; i < columnNames.size(); i++ )
columnNamesVector.add(columnNames.get(i));
}
public Vector getColumns(){
return columnNamesVector;
}
public Vector getData(){
return dataVector;
}
public ArrayList getColumnNames(){
return columnNames;
}
public int getNumberOfRows(){
return rows;
}
}
我使用DefaultTableModel进行了一些修改..:
model = new DefaultTableModel(rows, columns){
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
@Override
public Class<?> getColumnClass(int column) {
if (column < classes.length)
return classes[column];
return super.getColumnClass(column);
};};
答案 0 :(得分:2)
您的查询应始终返回所有列的数据。这意味着数据将以相同的方式存储在TableModel中。
然后,您可以更改要显示的列的视图。也就是说,您可以从TableColumns
的{{1}}中删除TableColumnModel
,并且只会显示用户想要查看的数据,即使它仍在模型中可用。然后意味着用户可以随时单击任何复选框,您不需要重做数据库查询,只需将TableColumn添加回表。
查看Table Column Manager以获取此方法的示例。此类使用弹出菜单来管理列,但您仍然可以使用复选框。您只需调用JTable
的相应方法来隐藏/显示列。也就是说,假设复选框的标签与表格中的标题匹配,您只需使用复选框文本隐藏/显示列。
另一种方法是不对列名进行硬编码(如果构建查询以仅获取特定列),而是从ResultSet的元数据中获取列名。来自Table From Database的TableColumnManager
显示了如何做到这一点。代码是通用的,因此适当的渲染器用于日期,整数等。