[英]Java DefaultTableModel gather data from multiple tables
我有數據關系
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
我需要進行數據驗證。 在Internet上進行長時間搜索后,我決定通過擴展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;
}
}
類人TM
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;
}
}
課堂課程TM
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的人員和課程中收集數據? 我做對了嗎?
任何建議都是很好的。 先感謝您。
我沒有徹底閱讀您的代碼(很多),但是基本上您會執行以下操作:
如果使用的是DefaultTableModel
,則很可能會使用構造函數DefaultTableModel(Object[][] data, Object[] columnNames)
。 在這種情況下,您將加載人員和課程,並構建一個需要顯示的二維數據數組。 另外,您只需要根據需要傳遞列名,例如,如果2D數組中每行的第一個元素包含人的名字,則您將傳遞“ name”之類的內容作為列名數組中的第一個元素。
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()
等以隱藏某些列。
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;
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.