簡體   English   中英

Java DefaultTableModel從多個表收集數據

[英]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);
  }
}

所以我的問題是:

  1. 我應該如何顯示“個人”和“課程”中所有列的JTable? 我應該通過與會者來做到這一點嗎?

  2. 如何從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或類似的東西。

更新:

如果我正確理解您的評論,則有兩個基本問題:

  1. 在哪里加載數據
  2. 如何添加新列

我將在控制器類中做這兩種事情,然后將數據傳遞到表模型,即,您甚至可能不需要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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM