Java DefaultTableModel从多个表中收集数据

时间:2014-12-18 11:35:40

标签: java entity-relationship validation defaulttablemodel

我有数据关系

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);
  }
}

所以我的问题是:

  1. 我怎么想出现一个包含人和课程所有列的JTable?我应该通过出席以及如何做到这一点吗?

  2. 我如何从AttendsTM的人员和课程中收集数据?我做得对吗?

  3. 任何建议都会非常受欢迎。提前谢谢。

2 个答案:

答案 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或类似的东西。

<强>更新

如果我理解你的评论,有两个基本问题:

  1. 加载数据的位置
  2. 如何添加新列
  3. 我在控制器类中执行这两个操作,然后将数据传递给表模型,即您甚至可能不需要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;
    }
};