我使用Scene Builder创建了一个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。我尝试将这些内容实现到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中,但会将数据显示到控制台中。
我应该忽略这些错误吗?我如何解决我的问题?
答案 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>
成为data
,ObservableList<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
,但是您在控制器中创建了新的并且操作那些。因此,即使您解决了实际问题所解决的问题,您也可能会发现在您解决这些问题之前,它不会以您想要的方式工作。但摆脱编译错误和警告将是一个开始......