如何使用javafx将数据从数据库加载到tableview

如何使用javafx将数据从数据库加载到tableview,java,javafx,Java,Javafx,我是javafx的初学者。我只是使用java jtable加载数据的方式,但我无法将数据加载到tableview,我已经尝试了下面的方法。如何将数据加载到tableview @FXML private TableColumn<?, ?> table1; public void table_load() { int c; try { Class.forName("com.mysql.jdbc.Driver"); con = Drive

我是javafx的初学者。我只是使用java jtable加载数据的方式,但我无法将数据加载到tableview,我已经尝试了下面的方法。如何将数据加载到tableview

@FXML
private TableColumn<?, ?> table1;

public void table_load()
{
    int c;

    try {
        Class.forName("com.mysql.jdbc.Driver");
        con = DriverManager.getConnection("jdbc:mysql://localhost/addressbook", "root","");
        pst = con.prepareStatement("select * from records");
        ResultSet rs = pst.executeQuery();
        ResultSetMetaData rd = rs.getMetaData();
        c = rd.getColumnCount();
        df = (DefaultTableModel)table1.getCellData(0);
        df.setRowCount(0);

        while (rs.next())
        {
            Vector v = new Vector();
            for (int i=1; i<=c; i++)
            {
                v.add(rs.getString("id"));
                v.add(rs.getString("name"));
                v.add(rs.getString("address"));
                v.add(rs.getString("phone"));
            }
            df.addRow(v);
        }
    } catch (SQLException ex) {

    } catch (ClassNotFoundException ex) {
       Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
    }
}
@FXML
私人表格第1栏;
公共空表_load()
{
INTC;
试一试{
Class.forName(“com.mysql.jdbc.Driver”);
con=DriverManager.getConnection(“jdbc:mysql://localhost/addressbook“,”根“,”);
pst=con.prepareStatement(“从记录中选择*);
ResultSet rs=pst.executeQuery();
ResultSetMetaData rd=rs.getMetaData();
c=rd.getColumnCount();
df=(DefaultTableModel)table1.getCellData(0);
df.setRowCount(0);
while(rs.next())
{
向量v=新向量();

对于(int i=1;i通常不直接将数据添加到TableColumn。通常的方法是使用可以添加的类型的对象。假设结果集包含
Customer
类型的对象,并且可以从结果集中提取一个或多个Customer对象。然后,您更愿意使用以下内容(需要在
fxml
文件中定义:

  • 类似于
    TableView customerView
  • 许多表列如下所示:
    • TableColumn-idColumn
    • TableColumn name column
    • TableColumn addressColumn
    • TableColumn电话列
您需要为列设置值工厂,以清楚显示哪个属性

  • idColumn.setCellValueFactory(新的PropertyValueFactory(“[客户类中的属性名称]”);

  • idColumn.setCellValueFactory(新属性ValueFactory(“id”);
最后一步应该是用数据填充表视图:

customerView.setItems(observableCustomers);

其中,
observatecustomers
是类型列表
observateList
javafx.collections.FXCollections
将帮助您在此创建相应的对象

它应该与此类似:

@FXML
TableView <Customer> customerView;

@FXML
TableColumn<Customer, String> idColumn;
@FXML
TableColumn<Customer, String> nameColumn;
@FXML
TableColumn<Customer, String> addressColumn;
@FXML
TableColumn<Customer, String> phoneColumn;

ObservableList<Customer> observableCustomers;

// init method or constructor, whatever suits your needs
private void initTable() {

    observableCustomers = FXCollections.observableArrayList();
    idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
    nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
    addressColumn.setCellValueFactory(new PropertyValueFactory<>("address"));
    phoneColumn.setCellValueFactory(new PropertyValueFactory<>("phone"));
}

public void table_load()
{

    try {
        Class.forName("com.mysql.jdbc.Driver");
        con = DriverManager.getConnection("jdbc:mysql://localhost/addressbook", "root","");
        pst = con.prepareStatement("select * from records");
        ResultSet rs = pst.executeQuery();
        ResultSetMetaData rd = rs.getMetaData();

        // CAST/TRANSFORMATION TO BE DONE BY YOU
        List<Customer> customerList = ((List<Customer>) rs.toList());

        // only if necessary
        observableCustomers.clear();
        // add customers
        observableCustomers.addAll(customerList);

    } catch (SQLException ex) {

    } catch (ClassNotFoundException ex) {
        Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
    }

}
@FXML
TableView自定义视图;
@FXML
TableColumn-idColumn;
@FXML
TableColumnNameColumn;
@FXML
表列地址列;
@FXML
TableColumn-phoneColumn;
观察者观察者;
//init方法或构造函数,任何适合您需要的
私有void initTable(){
observableCustomers=FXCollections.observableArrayList();
idColumn.setCellValueFactory(新属性ValueFactory(“id”);
nameColumn.setCellValueFactory(新属性ValueFactory(“名称”);
addressColumn.setCellValueFactory(新属性ValueFactory(“地址”);
setCellValueFactory(新属性ValueFactory(“电话”));
}
公共空表_load()
{
试一试{
Class.forName(“com.mysql.jdbc.Driver”);
con=DriverManager.getConnection(“jdbc:mysql://localhost/addressbook“,”根“,”);
pst=con.prepareStatement(“从记录中选择*);
ResultSet rs=pst.executeQuery();
ResultSetMetaData rd=rs.getMetaData();
//演员/转换由您完成
列表客户列表=((列表)rs.toList());
//只有在必要的时候
observeCustomers.clear();
//添加客户
addAll(customerList);
}catch(SQLException-ex){
}捕获(ClassNotFoundException ex){
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE,null,ex);
}
}

与Swing不同,JavaFX TableView不使用单独的模型。相反,数据就是模型。您可以使用TableView的setItems方法将此数据传递给TableView

这意味着您需要创建一个类来保存数据。由于您的表名为
records
,因此我将数据类命名为
Record

如果查看JavaFX类的文档,您应该注意到一个模式。Bean属性是封装的属性,由三个方法组成:

  • 一种读取方法,总是以
    get
    开头,后跟大写字母。ª
  • 一种写入方法,总是以
    set
    开头,后跟大写字母
  • 属性方法,其名称始终以
    property
    结尾

例如,考虑类。它有一个“不透明”属性,用这些方法表示:

您的数据类需要遵循相同的模式:

public class Record {
    private final StringProperty id;
    private final StringProperty name;
    private final StringProperty address;
    private final StringProperty phone;

    public Record() {
        id = new SimpleStringProperty(this, "id");
        name = new SimpleStringProperty(this, "name");
        address = new SimpleStringProperty(this, "address");
        phone = new SimpleStringProperty(this, "phone");
    }

    public StringProperty idProperty() { return id; }
    public String getId() { return id.get(); }
    public void setId(String newId) { id.set(newId); }

    public StringProperty nameProperty() { return name; }
    public String getName() { return name.get(); }
    public void setName(String newName) { name.set(newName); }

    public StringProperty addressProperty() { return address; }
    public String getAddress() { return address.get(); }
    public void setAddress(String newAddress) { address.set(newAddress); }

    public StringProperty phoneProperty() { return phone; }
    public String getPhone() { return phone.get(); }
    public void setPhone(String newPhone) { phone.set(newPhone); }

    @Override
    public String toString() {
        return String.format("%s[id=%s, name=%s]",
            getClass().getName(), getId(), getName());
    }
}
创建这些对象非常简单:

@FXML
private TableView<Record> table;

@FXML
private TableColumn<Record, String> idColumn;

@FXML
private TableColumn<Record, String> nameColumn;

@FXML
private TableColumn<Record, String> addressColumn;

@FXML
private TableColumn<Record, String> phoneColumn;

// ... 

    ObservableList<Record> records = FXCollections.observableArrayList();

    try (ResultSet rs = pst.executeQuery()) {
        while (rs.next())
        {
            Record record = new Record();
            record.setId(rs.getString("id"));
            record.setName(rs.getString("name"));
            record.setAddress(rs.getString("address"));
            record.setPhone(rs.getString("phone"));

            records.add(record);
        }
    }

    table.setItems(records);

返回类型为原始布尔值的读取方法可以使用
is
而不是
get


²只读属性不需要Write方法。

您不能将Swing模型与JavaFX一起使用。您必须创建一个数据类,并将该类对象的ObservableList传递给TableView的
setItems
方法。(我个人将该数据类命名为
Record
)请学习java命名约定并遵守它们。我是javafx的初学者,这意味着您的第一步将是阅读并(至少)理解关于如何使用TableView的基本教程:)javafx标记wiki引用了一些不使用PropertyValueFactory的内容。它基于反射,这意味着它容易出错,编译器无法捕获错误。错误甚至不会在运行时出现;PropertyValueFactory显然会将其吞没。
nameColumn.setCellValueFactory(f->f.getValue().nameProperty())
更安全。
idColumn.setCellValueFactory(f -> f.getValue().idProperty());
nameColumn.setCellValueFactory(f -> f.getValue().nameProperty());
addressColumn.setCellValueFactory(f -> f.getValue().addressProperty());
phoneColumn.setCellValueFactory(f -> f.getValue().phoneProperty());