JavaFX动态TableView未显示数据库中的数据

时间:2015-09-27 14:21:14

标签: java javafx javafx-2 javafx-8

我使用Scene Builder创建了一个TableView,如下所示 - enter image description here

这是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。我尝试将这些内容实现到Controller Class中,如下所示 -

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

问题是,它显示了行tableview.setItems(data);的错误。我不知道这个错误的原因。如果我将行private TableView<?> tableview;编辑为private TableView tableview;,则它不会显示行tableview.setItems(data);的任何错误。然后应用程序运行良好。但是,当我单击Show Tables按钮时,它不会将数据显示到TableView中,但会将数据显示到控制台中。

亦显示多项警告如下─ enter image description here

enter image description here

我应该忽略这些错误吗?我如何解决我的问题?

1 个答案:

答案 0 :(得分:2)

不,不要忽略警告。警告是因为您使用原始类型用于&#34; generic&#34;类型,即参数化。如果这样做,您最终可能会遇到编译器未捕获的类型不匹配。使用正确声明的类型并使其正确将使您的程序更加健壮。

例如,

TableView是泛型类型:它被声明为TableView<T>。这里T类型参数:您可以(松散地说)将T视为一个变量,表示表格每行中事物的类型。当您创建实际的TableView时,您必须指定特定TableView将要包含的类型。在您的示例中,每行由ObservableList表示。现在,ObservableList也是泛型类型:它被声明为ObservableList<E>,其中E表示列表中每个元素的类型。在您的情况下,在buildData()方法中,您为每一行创建ObservableList<String>。因此,您的表格类型为ObservableList<String>,因此您应该替换

@FXML
private TableView<?> tableView ;

@FXML
private TableView<ObservableList<String>> tableView ;

属于items的{​​{1}}表示为TableView<T>。因为,对于您的表格,ObservableList<T>T,您需要将您的项目设为ObservableList<String>(请将其读作&#34;可观察的字符串列表和#34的可观察列表;) 。所以你应该替换

ObservableList<ObservableList<String>>

private ObservableList<ObservableList> data;

这些更改应该从private ObservableList<ObservableList<String>> data ; 删除编译错误。

您还应该修复tableView.setItems(data);的声明。 TableColumn定义为TableColumn。这里TableColumn<S,T>是表的类型(即表示表中一行的每个项的类型:它与S定义中的T相同),以及TableView是列中单元格中每个值的类型。您所有列中的单元格中的每个值都为T,因此在String中您应该拥有:

buildData()

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

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

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); } } TableView<TranslatedWord>等。TableColumn<TranslatedWord, String>成为dataObservableList<TranslatedWord>方法的代码类似

buildData()

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

此代码中还有许多其他错误:正如我之前所说,您在FXML中创建了 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); } TableView,但是您在控制器中创建了新的并且操作那些。因此,即使您解决了实际问题所解决的问题,您也可能会发现在您解决这些问题之前,它不会以您想要的方式工作。但摆脱编译错误和警告将是一个开始......