JavaFX dynamic TableView未显示数据库中的数据

JavaFX dynamic TableView未显示数据库中的数据,java,javafx,javafx-2,javafx-8,Java,Javafx,Javafx 2,Javafx 8,我使用场景生成器创建了一个TableView,如下所示- 这是FXML代码- <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import java.lang.*?> <?import javafx.scene.layout.*?> <Pane maxHeight="-Infinity" maxWidth="-Infinity" mi

我使用场景生成器创建了一个TableView,如下所示-

这是FXML代码-

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>


<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="508.0" prefWidth="483.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="imran.jfx.application.Controller">
   <children>
      <TableView fx:id="tableview" layoutX="19.0" layoutY="94.0" prefHeight="402.0" prefWidth="443.0">
        <columns>
          <TableColumn fx:id="id" prefWidth="75.0" text="ID" />
          <TableColumn fx:id="english" prefWidth="170.0" text="English" />
            <TableColumn fx:id="bangla" prefWidth="197.0" text="Bangla" />
        </columns>
      </TableView>
      <Button fx:id="showTableview" layoutX="188.0" layoutY="52.0" mnemonicParsing="false" onAction="#showTableData" text="Show Tables" />
   </children>
</Pane>

我尝试连接数据库,并尝试将数据从数据库显示到tableview。我尝试将这些东西实现到控制器类中,如下所示-

package imran.jfx.application;

import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ResourceBundle;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.util.Callback;

public class Controller implements Initializable{

    private ObservableList<ObservableList> data;

    @FXML
    private TableView<?> tableview;

    @FXML
    private TableColumn<?, ?> id;

    @FXML
    private TableColumn<?, ?> english;

    @FXML
    private TableColumn<?, ?> bangla;

    @FXML
    private Button showTableview;

    ResultSet result;
    PreparedStatement doQuery;
    Connection conn;
    String query;

    @Override
    public void initialize(URL location, ResourceBundle resources) 
    {
        try 
        {
            Class.forName("org.sqlite.JDBC");
        } 
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        String url="jdbc:sqlite::resource:database/bn_words.db";
        try 
        {
            conn = DriverManager.getConnection(url);
        } 
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void buildData()
    {
          data = FXCollections.observableArrayList();

          try{
            Class.forName("org.sqlite.JDBC");
            String url="jdbc:sqlite::resource:database/bn_words.db";
            conn = DriverManager.getConnection(url);

            String SQL = "SELECT _id,en_word,bn_word from words";

            ResultSet rs = conn.createStatement().executeQuery(SQL);


            for(int i=0 ; i<rs.getMetaData().getColumnCount(); i++)
            {
                final int j = i;                
                TableColumn col = new TableColumn(rs.getMetaData().getColumnName(i+1));
                col.setCellValueFactory(new Callback<CellDataFeatures<ObservableList,String>,ObservableValue<String>>(){                    
                    public ObservableValue<String> call(CellDataFeatures<ObservableList, String> param) {                                                                                              
                        return new SimpleStringProperty(param.getValue().get(j).toString());                        
                    }                    
                });

                tableview.getColumns().addAll(col); 
                System.out.println("Column ["+i+"] ");
            }

            while(rs.next()){
                ObservableList<String> row = FXCollections.observableArrayList();
                for(int i=1 ; i<=rs.getMetaData().getColumnCount(); i++){
                    row.add(rs.getString(i));
                }
                System.out.println("Row [1] added "+row );
                data.add(row);

            }
            tableview.setItems(data);
          }catch(Exception e){
              e.printStackTrace();
              System.out.println("Error on Building Data");             
          }
      }

    @FXML
    void showTableData(ActionEvent event) {
        tableview = new TableView();
        buildData();
    }
}
包imran.jfx.application;
导入java.net.URL;
导入java.sql.Connection;
导入java.sql.DriverManager;
导入java.sql.PreparedStatement;
导入java.sql.ResultSet;
导入java.sql.SQLException;
导入java.util.ResourceBundle;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.value.observeValue;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.event.ActionEvent;
导入javafx.fxml.fxml;
导入javafx.fxml.Initializable;
导入javafx.scene.control.Button;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableColumn.CellDataFeatures;
导入javafx.scene.control.TableView;
导入javafx.util.Callback;
公共类控制器实现可初始化{
私有可观测列表数据;
@FXML
私有TableView TableView;
@FXML
私有表列id;
@FXML
私人英语专栏;
@FXML
孟加拉邦私人银行;
@FXML
私有按钮显示视图;
结果集结果;
预处理语句doQuery;
连接接头;
字符串查询;
@凌驾
公共void初始化(URL位置、ResourceBundle资源)
{
尝试
{
Class.forName(“org.sqlite.JDBC”);
} 
catch(classnotfounde异常){
e、 printStackTrace();
}
String url=“jdbc:sqlite::resource:database/bn_words.db”;
尝试
{
conn=DriverManager.getConnection(url);
} 
捕获(SQLE异常){
e、 printStackTrace();
}
}
public void buildData()
{
data=FXCollections.observearraylist();
试一试{
Class.forName(“org.sqlite.JDBC”);
String url=“jdbc:sqlite::resource:database/bn_words.db”;
conn=DriverManager.getConnection(url);
String SQL=“从单词中选择_id、en_word、bn_word”;
ResultSet rs=conn.createStatement().executeQuery(SQL);

对于(int i=0;iNo),请不要忽略这些警告。这些警告是因为您对“泛型”(即参数化)的类型使用原始类型。如果这样做,则可能会导致编译器无法捕获的类型不匹配。使用正确声明的类型并使其正确将使程序更加健壮

例如,
TableView
是一个泛型类型:它被声明为
TableView
。这里
T
是一个类型参数:您可以(粗略地说)将
T
视为表示表中每一行中事物类型的变量。当您创建实际的
TableView
时,您必须指定特定的
TableView
将包含的类型。在您的示例中,每一行都由
可观察列表
表示。现在,
可观察列表
is也是一个泛型类型:它被声明为
observateList
,其中
E
表示列表中每个元素的类型。在您的例子中,在
buildData()
方法中,您为每一行创建一个
observateList
。因此,您的表类型是
observateList
,因此您应该替换它

@FXML
private TableView<?> tableView ;
private ObservableList<ObservableList> data;

(请注意,由于这些是要添加到表中的列,因此不太清楚为什么在FXML中也定义了列;但对于您要问的问题来说,这有点离题。)

当您使用常规列表作为表的数据类型时,所有这些都变得非常复杂。因为在这里,您知道数据库中有多少列,以及这些列代表什么,所以我强烈建议通过定义一个类来表示每行中的数据,从而使表更加具体。我不知道您的应用程序是,所以我会(可能不正确)猜测它正在做一些翻译。所以我会这样做

public class TranslatedWord {

    private final StringProperty id = new SimpleStringProperty();

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

    private final StringProperty english = new SimpleStringProperty();

    public StringProperty englishProperty() {
        return english ;
    }
    public final String getEnglish() {
        return englishProperty().get();
    }
    public final void setEnglish(String english) {
        englishProperty().set(english);
    }

    private final StringProperty bangla = new SimpleStringProperty();

    public StringProperty banglaProperty() {
        return bangla ;
    }
    public final String getBangla() {
        return banglaProperty().get();
    }
    public final void setId(String bangla) {
        banglaProperty().set(bangla);
    }

}
现在,您创建了一个
TableView
TableColumn
,等等。您的
数据
变成了一个
可观察列表
,您的
buildData()
方法有如下代码

        while(rs.next()){
            TranslatedWord word = new TranslatedWord();
            word.setId(rs.getString("id"));
            word.setEnglish(rs.getString("english"));
            word.setBangla(rs.getString("bangla"));
            System.out.println("Row [1] added "+row );
            data.add(row);

        }
一旦你习惯了这种结构,你会发现这是一种更容易维护的样式,因为类型指定了它们所代表的内容


这段代码中还有很多其他错误:正如我前面所说的,您正在FXML中创建
TableView
TableColumn
s,但随后您在控制器中创建了新的并对其进行操作。因此,即使您修复了您实际询问的问题,您可能也会发现它不会以y的方式工作在您解决这些问题之前,您也需要这样做。但是消除编译错误和警告将是一个开始…

不,不要忽略这些警告。这些警告是因为您对“泛型”类型使用原始类型,即参数化。如果执行此操作,可能会导致编译器无法捕获的类型不匹配。使用正确声明的类型并使其正确将使程序更加健壮

例如,
TableView
是一个泛型类型:它被声明为
TableView
。这里
T
是一个类型参数:您可以(粗略地说)将
T
视为表示表中每一行中事物类型的变量。当您创建实际的
TableView
时,您必须指定特定的
TableView
将包含的类型。在您的示例中,每一行都由
可观察列表
表示。现在,
可观察列表
i它也是一个泛型类型:它被声明为
ObservableL
TableColumn<ObservableList<String>, String> col = new TableColumn<>(rs.getMetaData().getColumnName(i+1));
public class TranslatedWord {

    private final StringProperty id = new SimpleStringProperty();

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

    private final StringProperty english = new SimpleStringProperty();

    public StringProperty englishProperty() {
        return english ;
    }
    public final String getEnglish() {
        return englishProperty().get();
    }
    public final void setEnglish(String english) {
        englishProperty().set(english);
    }

    private final StringProperty bangla = new SimpleStringProperty();

    public StringProperty banglaProperty() {
        return bangla ;
    }
    public final String getBangla() {
        return banglaProperty().get();
    }
    public final void setId(String bangla) {
        banglaProperty().set(bangla);
    }

}
        while(rs.next()){
            TranslatedWord word = new TranslatedWord();
            word.setId(rs.getString("id"));
            word.setEnglish(rs.getString("english"));
            word.setBangla(rs.getString("bangla"));
            System.out.println("Row [1] added "+row );
            data.add(row);

        }