JavaFX动态TableView未显示数据库中的数据 [英] JavaFX dynamic TableView is not showing data from the database

查看:141
本文介绍了JavaFX动态TableView未显示数据库中的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've created a TableView using Scene Builder as follows-

这是FXML代码 -

Here is the FXML code-

<?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类中,如下所示 -

I tried to connect with the database and tried to show data from the database to tableview. I tried to implement this things into Controller Class as follows-

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

The problem is, it is showing error for the line tableview.setItems(data);. I don't know the reason for this error. If I edit the line private TableView<?> tableview; to private TableView tableview; then it doesn't shows any error for the line tableview.setItems(data);. Then the app runs well. But when I click on the button Show Tables, it doesn't show the data into the TableView, but it shows the data into console.

还显示了很多警告如下 -

There also shown lots of warnings as follows-

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

Should I ignore these errors? How do I fix my problem?

推荐答案

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

No, do not ignore the warnings. The warnings are because you are using raw types for types that are "generic", i.e. parametrized. If you do this, you can end up with type mismatches that are not caught by the compiler. Using properly declared types and getting them correct will make your programs more robust.

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

TableView, for example, is a generic type: it is declared as TableView<T>. Here T is a type parameter: you can (loosely speaking) think of T as a variable that represents the type of the thing in each row of the table. When you create an actual TableView, you have to specify what type that particular TableView is going to hold. In your example each row is represented by an ObservableList. Now, ObservableList is also a generic type: it is declared as ObservableList<E>, where E represents the type of each element of the list. In your case, in the buildData() method, you create an ObservableList<String> for each row. Therefore, your table type is ObservableList<String>, and so you should replace

@FXML
private TableView<?> tableView ;

with

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

属于<$ c的 $ c> TableView< T> 表示为 ObservableList< T> 。因为,对于你的表, T ObservableList< String> ,你需要你的物品是 ObservableList< ObservableList< String>> (将其读作可观察的字符串列表的可观察列表)。所以你应该替换

The items belonging to a TableView<T> are represented as an ObservableList<T>. Since, for your table, T is ObservableList<String>, you need your items to be an ObservableList<ObservableList<String>> (read this as "an observable list of observable lists of strings"). So you should replace

private ObservableList<ObservableList> data;

with

private ObservableList<ObservableList<String>> data ;

这些更改应该从 tableView.setItems(data)中删除编译错误;

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

You should also fix the declarations of the TableColumns. TableColumn is defined as TableColumn<S,T>. Here S is the type of the table (i.e. the type of each item representing a row in the table: it's the same as T in the TableView definition), and T is the type of each value in a cell in the column. Each value in a cell, in all of your columns, is String, so in buildData() you should have:

TableColumn<ObservableList<String>, String> col = new TableColumn<>(rs.getMetaData().getColumnName(i+1));

(请注意,由于这些是您要添加到表中的列,因此您不清楚为何会这样做也有你的FXML中定义的列;这是你问的问题的偏离主题。)

(Note that since these are the columns you are adding to your table, it's not really clear why you also have columns defined in your FXML; that is kind of off-topic for the question you are asking though.)

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

All of this gets quite complex when you are using general lists as the data type for your table. Since in this you know how many columns are in your database, and what those columns represent, I very strongly encourage to make the table more specific by defining a class to represent the data in each row. I don't know what your application is, so I'll make a (probably incorrect) guess that it is doing some translation. So I would do

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> 等。您的数据成为 ObservableList< TranslatedWord> ,而您的 buildData()方法的代码类似于

Now you make a TableView<TranslatedWord> and TableColumn<TranslatedWord, String>, etc. Your data becomes an ObservableList<TranslatedWord>, and your buildData() method has code like

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

        }

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

Once you get used to this structure, you will find this a much easier style to maintain, as the types specify what they represent.

此代码中还有许多其他错误:正如我之前所说,你正在创建FXML中的 TableView TableColumn ,然后你在控制器中创建新的并操纵它们。因此,即使你修复了你实际问过的问题,你也可能会发现在修复这些问题之前它不会按照你想要的方式工作。但摆脱编译错误和警告将是一个开始......

You also have lots of other things wrong in this code: as I said earlier you are creating the TableView and TableColumns in FXML, but then you are creating new ones in the controller and manipulating those. Consequently, even if you fix the problems you actually asked about, you'll probably find it won't work the way you want until you fix those issues too. But getting rid of the compile errors and warnings is going to be a start...

这篇关于JavaFX动态TableView未显示数据库中的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆