我有数据关系
Person-Attends-Course
Person
-------
id: integer primary key
name: string
prename: string
age: integer
Course
-------
courseName: string primary key
hours: integer
Attends
--------
id: integer primary key references Person
courseName: string primary key references Course
我需要进行数据验证。经过长时间的互联网搜索,我决定通过扩展DefaultTableModel来实现它。到目前为止,我创建了下面的代码,我有一些问题:
班级人员
class Person{
private String name, prename,id;
private int age;
public Person(){}
public String getName(){return this.name;}
public String getPrename(){return this.prename;}
public int getAge(){return this.age;}
public String getId(){return this.id;}
public void setName(String name){
try{
if(name.equals(""))
JOptionPane.showMessageDialog(null, "Must insert name");
else
this.name = name;
}
catch(NullPointerException e){
this.name = "";
}
}
public void setPrename(String prename){
if(prename.equals(""))
JOptionPane.showMessageDialog(null, "Must insert prename");
else
this.prename = prename;
}
public void setAge(int age){
try{
if(age <0 || age >=100)
JOptionPane.showMessageDialog(null, "Must insert valid age");
else
this.age = age;
}
catch(Exception e){
this.age = 0;
}
}
public void setId(String id){
this.id = id;
}
}
Class PersonTM
class PersonTM extends DefaultTableModel{
private final List<Person> personlist;
private final String[] columnNames = {"id", "name", "prename","age"};
private final Class[] columnClass = {String.class, String.class, String.class, Integer.class};
public PersonTM(){this.personlist = new ArrayList<>();}
@Override
public Class<?> getColumnClass(int columnIndex){
return columnClass[columnIndex];
}
@Override
public String getColumnName(int column){
return columnNames[column];
}
public String[] getColumnNames(){return this.columnNames;}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Person row = personlist.get(rowIndex);
switch(columnIndex){
case 0:
return row.getId();
case 1:
return row.getName();
case 2:
return row.getPrename();
case 3:
return row.getAge();
default:
return null;
}
}
@Override
public void setValueAt(Object obj, int rowIndex, int columnIndex){
Person row = personlist.get(rowIndex);
switch(columnIndex){
case 0:
row.setId((String)obj);
break;
case 1:
row.setName((String)obj);
break;
case 2:
row.setPrename((String)obj);
break;
case 3:
row.setAge((Integer)obj);
break;
}
}
}
课程
class Courses{
private String courseName;
private int hours;
public Courses(){}
public String getCourseName(){return this.courseName;}
public int getHours() {return this.hours;}
public void setCourseName(String courseName){
if(courseName.equals(""))
JOptionPane.showMessageDialog(null, "Must insert courseName");
else
this.courseName = courseName;
}
public void setHours(int hours){
if(hours <=0 || hours >=50)
JOptionPane.showMessageDialog(null, "Must insert valid hours");
else
this.hours = hours;
}
}
课程课程
class CoursesTM extends DefaultTableModel{
private final List<Courses> courseslist;
private final String[] columnNames = {"course name","hours"};
private final Class[] columnClass = {String.class,Integer.class};
public CoursesTM(){this.courseslist = new ArrayList<>();}
@Override
public Class<?> getColumnClass(int columnIndex){
return columnClass[columnIndex];
}
@Override
public String getColumnName(int column){
return columnNames[column];
}
public String[] getColumnNames(){return this.columnNames;}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Courses row = courseslist.get(rowIndex);
switch(columnIndex){
case 0:
return row.getCourseName();
case 1:
return row.getHours();
default:
return null;
}
}
@Override
public void setValueAt(Object obj, int rowIndex, int columnIndex){
Courses row = courseslist.get(rowIndex);
switch(columnIndex){
case 0:
row.setCourseName((String)obj);
break;
case 1:
row.setHours((Integer)obj);
break;
}
}
}
班级出席
//here I am a little confused
class Attends{
private final Person p;
private final Course c;
public Attends(Person p,Course c){
this.p = p;
this.c = c;
}
public Person getPerson(){return this.p;}
public Course getCourse(){return this.c;}
}
Class AttendsTM
class AttendsTM extends DefaultTableModel{
private final PersonTM p;
private final CoursesTM c;
private final Map<Person,List<Course>> attendslist;
private String[] columnNames;
private final Class[] columnClass = {Person.class,Courses.class};
public AttendsTM(Map<Person,List<Courses>> attendslist){
this.attendslist = attendslist;
this.p = new PersonTM();
this.c = new CoursesTM();
}
public void setColumnNames(){
for (int i = 0; i < p.getColumnCount(); i++)
columnNames[i] = p.getColumnName(i);
for (int i = p.getColumnCount(); i < c.getColumnCount(); i++)
columnNames[i] = c.getColumnName(i);
}
}
班级查看器
class viewer extends JFrame{
private final JScrollPane scrollPane;
private final AttendsTM model;
private final JTable table;
public viewer(){
//collect data from db
Person p1 = new Person();
p1.setId("00001");
p1.setName("John");
p1.setPrename("Johnson");
p1.setAge(30);
Person p2 = new Person();
p2.setId("00002");
p2.setName("Jack");
p2.setPrename("Jackson");
p2.setAge(30);
Courses c1 = new Courses();
c1.setCourseName("History of art");
c1.setHours(25);
Courses c2 = new Courses();
c2.setCourseName("Music");
c2.setHours(15);
List<Courses> coursesList = new ArrayList<>();
coursesList.add(c1);
coursesList.add(c2);
Map<Person,List<Courses>> attendsMap = new LinkedHashMap<>();
attendsMap.put(p1, coursesList);
attendsMap.put(p2, coursesList);
model = new AttendsTM(attendsMap);
table = new JTable(model);
//add a blank row at the end of Jtable
model.addRow(new Object[model.getColumnCount()]);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
table.setCellSelectionEnabled(true);
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(true);
//resize columns and use horizontal scroll bar to view data
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
//disable column dragging
table.getTableHeader().setReorderingAllowed(false);
scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
public void initializeUI(){
add(scrollPane);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(300,300);
setVisible(true);
}
}
类TableModelExample
public class TableModelExample {
public static void main(String[] af){
Runnable runnable = new Runnable(){
@Override
public void run() {
new viewer().initializeUI();
}
};
EventQueue.invokeLater(runnable);
}
}
所以我的问题是:
我怎么想出现一个包含人和课程所有列的JTable?我应该通过出席以及如何做到这一点吗?
我如何从AttendsTM的人员和课程中收集数据?我做得对吗?
任何建议都会非常受欢迎。提前谢谢。
答案 0 :(得分:1)
我没有彻底阅读你的代码(它相当多)但基本上你做了以下事情:
如果您正在使用DefaultTableModel
,则最有可能使用构造函数DefaultTableModel(Object[][] data, Object[] columnNames)
。在这种情况下,您需要加载您的人员和课程,并构建您需要显示的数据的2D数组。另外,您只需根据需要传递列名称,例如如果2D数组中每一行的第一个元素包含该人的姓名,那么您将传递类似&#34; name&#34;作为列名数组中的第一个元素。
2D阵列的布局取决于您希望如何显示数据。行的每个元素都对应于表中的单元格。如果您希望每个课程和人员有一行,您只需生成多行,最有可能获得冗余/重复单元格。当然,您可以填充第一个单元格并清空所有多余的元素,以便在需要的地方渲染空单元格,但在这种情况下,您不应该允许排序。
如果您想将一个人所有课程放入一个单元格中,您可以使用预先格式化的字符串(AFAIK,默认渲染器可以显示html格式的文本)或提供您自己的渲染器。
使用重复单元格的简单方法示例:
Object[][] data = new Object[numrows][];
int curRow = 0;
for( Person p : persons ) { //assuming you have loaded the persons already
for( Course c : p.getCourses() ) { //loop over all courses a person has taken
Object[] row = new Object[numcols]; //create a new row array
//just an example of how to fill the elements
row[0] = p.getName(); //column 1 will contain the person's name
row[1] = c.getCourseName(); //column 2 will contain the course name
...
data[curRow] = row;
curRow++;
}
}
然后您只需将该数组传递给DefaultTableModel
构造函数。
结果可能如下所示:
+-------------+------------------------+
| Person name | Course |
+=============+========================+
| Vassilis De | Java Programming |
+-------------+------------------------+
| Thomas | Java Programming |
+-------------+------------------------+
| Thomas | How to answer in SO |
+-------------+------------------------+
| Thomas | Writing good examples |
+-------------+------------------------+
| Thomas | Being polite |
+-------------+------------------------+
请注意,这只是介绍了如何从已加载的数据构建表模型。如何加载数据取决于您的应用程序,但在示例中我假设您使用的是JPA或类似的东西。
<强>更新强>
如果我理解你的评论,有两个基本问题:
我在控制器类中执行这两个操作,然后将数据传递给表模型,即您甚至可能不需要AttendsTM
等。查看MVC模式以获取有关如何操作的更多信息创建和使用控制器。
保存输入的数据时,控制器将从表模型中读取数据,并以允许您向数据库中添加新条目的方式进行解释。如何完成这取决于您的应用程序。
使用自定义表模型可能有一个原因(例如,作为DefaultTableModel
的子类):如果要向模型添加一些键,这些键允许您识别实体但不应显示在实体中在表格中,您可以覆盖getValueAt()
等,以隐藏某些列。
答案 1 :(得分:0)
Vector<Object> columnNames = new Vector<Object>();
Vector<Object> data = new Vector<Object>();
假设您从数据库获取Table1List,Table1也包含Table2对象。在我的例子中,我使用JPA
//获取列名
columnNames.addElement("Table1 Attribute 1"); columnNames.addElement("Table1 Attribute 2"); columnNames.addElement("Table1 Attribute 3"); columnNames.addElement("Other Table Attribute 1"); columnNames.addElement("Other Table Attribute 2");
// Display Row value
for (Table1 Table1Obj: Table1List) {
Vector<Object> row = new Vector<Object>();
Table2 Table2Obj = getTable2DataFromDatabase(Table1Obj.getTable1Id());
row.addElement(Table1Obj.getTable1 Name());
row.addElement(Table1Obj.getTable1 Email());
row.addElement(Table1Obj.getTable1 Phone());
row.addElement(Table2Obj.getTable1 ID());
row.addElement(Table1Obj.getTable1 Name());
data.addElement(row);
// Create table with database data
final DefaultTableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
@Override
public Class getColumnClass(int column) {
for (int row = 0; row < getRowCount(); row++) {
Object o = getValueAt(row, column);
if (o != null) {
return o.getClass();
}
}
return Object.class;
}
};