2015-09-27 99 views
0

我創建了一個TableView中的數據庫顯示的數據如下 - enter image description hereJavaFX的動態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(); 
    } 
} 

的問題是,它顯示爲線tableview.setItems(data);錯誤。我不知道這個錯誤的原因。如果我將行private TableView<?> tableview;編輯爲private TableView tableview;,那麼它不會顯示行tableview.setItems(data);的任何錯誤。然後,應用程序運行良好。但是當我點擊Show Tables按鈕時,它不會將數據顯示到TableView中,但它將數據顯示到控制檯中。

還有很多所示的警告如下 - enter image description here

enter image description here

我應該忽略這些錯誤?我如何解決我的問題?

+0

請確保您通過[通用方法類型推斷當目標類型具有通配符時](http://stackoverflow.com/a/ 27880168/1759128) – ItachiUchiha

回答

2

不,不要忽視警告。警告是因爲您正在使用原始類型作爲「通用」類型,即參數化的類型。如果你這樣做,你最終可能會遇到編譯器沒有捕獲到的類型不匹配。使用正確聲明的類型並使它們正確將使您的程序更健壯。例如,

TableView是一種通用類型:它被聲明爲TableView<T>。這裏T是一個類型參數:你可以(寬鬆地說)把T看作一個變量,它表示表中每行的東西的類型。當您創建實際TableView時,您必須指定特定TableView將要保持的類型。在你的例子中,每行代表一個ObservableList。現在,ObservableList也是通用類型:它被聲明爲ObservableList<E>,其中E表示列表中每個元素的類型。在你的情況下,在buildData()方法中,你爲每一行創建一個ObservableList<String>。因此,你的表型爲ObservableList<String>,所以你應該

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

items屬於TableView<T>取代

@FXML 
private TableView<?> tableView ; 

被表示爲ObservableList<T>。因爲對於你的表,TObservableList<String>,你需要你的項目是ObservableList<ObservableList<String>>(閱讀它作爲「一個可觀察的字符串列表」)。所以,你應該更換

private ObservableList<ObservableList> data; 

private ObservableList<ObservableList<String>> data ; 

這些改變應該從tableView.setItems(data);刪除編譯錯誤。

您還應該修復TableColumn的聲明。 TableColumn定義爲TableColumn<S,T>。這裏S是表格的類型(即表中表格中每一行的類型:與TableView定義中的T相同),而T是列中單元格中每個值的類型。在一個單元格,在所有列的每個值,爲String,所以在buildData()你應該有:

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

(注意,因爲這些都是要添加到您的表中的列,這不是真的清楚你爲什麼也有在你的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<TranslatedWord>TableColumn<TranslatedWord, String>,等你data成爲ObservableList<TranslatedWord>,和你的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中創建TableViewTableColumn s,但是你在控制器中創建新的控制器並操作它們。因此,即使您修復了實際問到的問題,在您解決這些問題之前,您也許會發現它無法按照您的方式工作。但擺脫編譯錯誤和警告將是一個開始...

+0

非常感謝James_D!這次你是救世主!我試過你推薦的方法,對我來說似乎更簡單。 :D –

+0

有關我推薦的方法的完整示例,請參閱http://stackoverflow.com/questions/25651641/javafx-mysql-connection-example-please(對不起,無法抗拒;)。) –