JavaFX ListView从两列可观察列表中显示单列

时间:2018-10-15 01:36:40

标签: listview javafx observable

我从@Fabian得到了一些很好的建议,但是我在ListView中看不到任何数据:

public class MenuController implements Initializable {
@FXML
ListView menuList1;

@Override
public void initialize(URL url, ResourceBundle rb) {
    ObservableList<EmployeeDivision> divisionListRow = FXCollections.observableArrayList();
    try {
        Connection conn;
        conn = Connect_db.getConnection();
        String query = "SELECT ID,Division FROM tbl_ref_employee_divisions";
        PreparedStatement prestate = conn.prepareStatement(query);
        ResultSet divsResult = prestate.executeQuery();
        while (divsResult.next()) {
            divisionListRow.add(new EmployeeDivision(divsResult.getInt(1), divsResult.getString(2)));
        menuList1.setCellFactory(lv -> new ListCell<EmployeeDivision>() {
            @Override
            protected void updateItem(EmployeeDivision item, boolean empty) {
                super.updateItem(item, empty);
                setText(empty || item == null ? "" : item.getName());
            }
        });
    }
        prestate.close();
        divsResult.close();
        conn.close();

    } catch (SQLException ex) {
        ex.printStackTrace();
    }
}    

我不知道lambda的工作原理。但是我会到达那里。 调试我可以看到divisionListRow正在填充。但是我希望数据divsResult.getString(2)会出现。 tks

1 个答案:

答案 0 :(得分:1)

我可以看到的三件事...

将您的ListView声明为ListView<EmployeeDivision>。将其类型设置为EmployeeDivision

setCellFactory不应位于while (divsResult.next())数据加载循环中。仅需要声明一次,而不是每次将一行从DB装入ObservableList时都声明一次。

您需要执行menuList1.setItems(divisionListRow)setItems()是将您的数据与ListView关联的事物。

这是一个产生如下内容的ListView的MVCE:

note on MDN

单击状态时,它将部门ID输出到控制台。

MVCE使用SQLite数据库。可以使用此SQL创建MVCE的表和数据。

CREATE TABLE Employee_Divisions (
    ID       INTEGER,
    Division VARCHAR
);

INSERT INTO Employee_Divisions
VALUES
(1, 'Queensland'),
(2, 'New South Wales'),
(3, 'Victoria'),
(4, 'South Australia'),
(5, 'Northern Territory'),
(6, 'Western Australia'),
(7, 'Tasmania');

这是代码。

package test42;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.Observable;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.sqlite.SQLiteConfig;

public class Test42 extends Application {

    private static final String dbName = "TestDB.db";
    private static final String dbURL = "jdbc:sqlite:" + dbName;
    private static final String dbDriver = "org.sqlite.JDBC";


    private Parent createContent() {

        //*************************************************************************************
        //Declare an ObservableList for the ListView
        ObservableList<EmployeeDivisions> olEmployeeDivisions = FXCollections.observableArrayList(empdiv -> new Observable[] {});

        //*************************************************************************************
        //Get the data from the DB and add it to the ObservableList.
        String sql = "SELECT * FROM Employee_Divisions;";
        ArrayList<ArrayList<Object>> resultSet = doDatabaseSelect(sql);

        olEmployeeDivisions.clear();

        for ( ArrayList<Object> resultRow : resultSet ) {
            EmployeeDivisions newEmployeeDivision = new EmployeeDivisions();
            newEmployeeDivision.addList(resultRow);
            olEmployeeDivisions.add(newEmployeeDivision);
        }

        //*************************************************************************************
        //Declare the ListView
        ListView<EmployeeDivisions> lvEmployeeDivisions = new ListView<>();

        //Set its data to the ObservableList
        lvEmployeeDivisions.setItems(olEmployeeDivisions);

        //Set its cell factory to only show the division name
        lvEmployeeDivisions.setCellFactory(lv -> new ListCell<EmployeeDivisions>() {
            @Override
            protected void updateItem(EmployeeDivisions item, boolean empty) {
                super.updateItem(item, empty);
                setText(empty || item == null ? "" : item.getDivisionName());
            }
        });

        //Ouput the division ID when a division name is clicked
        lvEmployeeDivisions.setOnMouseClicked((MouseEvent event) -> {
            EmployeeDivisions selectedItem = lvEmployeeDivisions.getSelectionModel().getSelectedItem();
            if (selectedItem != null) {
                System.out.println("Division ID = " + selectedItem.getDivisionId());
            }
        });

        //*************************************************************************************
        //Create a BorderPane and add the ListView
        BorderPane content = new BorderPane(lvEmployeeDivisions);

        return content;

    }

    //*************************************************************************************
    //Data model

    private class EmployeeDivisions {

        private IntegerProperty divisionId;
        private StringProperty divisionName;

        private EmployeeDivisions() {
            this(0, "");
        }

        private EmployeeDivisions(
            int divisionId,
            String divisionName
        ) {
            this.divisionId = new SimpleIntegerProperty(divisionId);
            this.divisionName = new SimpleStringProperty(divisionName);
        }

        private int getDivisionId() {
            return divisionId.get();
        }

        private void setDivisionId(int divisionId) {
            this.divisionId.set(divisionId);
        }

        private IntegerProperty divisionIdProperty() {
            return divisionId;
        }

        private String getDivisionName() {
            return divisionName.get();
        }

        private void setDivisionName(String divisionName) {
            this.divisionName.set(divisionName);
        }

        private StringProperty divisionNameProperty() {
            return divisionName;
        }

        private void addList(ArrayList<Object> list) {

            this.divisionId.set((int) list.get(0));
            this.divisionName.set((String) list.get(1));

        }

    }

    //*************************************************************************************
    //Methods to connect to and query the database and execute DML

    public Connection connectToDB()  {

        Connection cnx = null;
        File dbPath = new File(dbName);

        if ( dbPath.exists()){

            try {
                Class.forName(dbDriver);
            } catch (ClassNotFoundException exception) {
                System.err.println("Database driver class not found");
            }

            try {

                SQLiteConfig config = new SQLiteConfig();
                config.enforceForeignKeys(true);
                cnx = DriverManager.getConnection(dbURL,config.toProperties());
                cnx.setAutoCommit(true);

            } catch (SQLException exception) {
                System.err.println("Error connecting to database " + dbName);
            }     

        } else {
            System.err.println("Database " + dbName + " not found!");
        }
        return cnx;

    }

    private ArrayList<ArrayList<Object>> doDatabaseSelect(String sql) {

        int colNum = 0;
        ArrayList<ArrayList<Object>> resultSet = new ArrayList<>();

        Connection cnx = connectToDB();
        if ( cnx == null ) return null;

        try (
                Statement stmt = cnx.createStatement();
        ) {
            try (
                    ResultSet rs = stmt.executeQuery(sql)
                ) {
                    ResultSetMetaData rsMetaData = rs.getMetaData();
                    //Add each DB row as an Object to the dbRow ArrayList ...
                    while (rs.next()) {
                        ArrayList<Object> dbRow = new ArrayList<>();
                        for ( int i=0; i<rsMetaData.getColumnCount(); i++ ) {
                            colNum = i + 1;
                            switch ( rsMetaData.getColumnTypeName(colNum).trim() ) {
                                case "VARCHAR" :
                                    String stringCol = rs.getString(colNum);
                                    dbRow.add(stringCol);
                                    break;
                                case "INTEGER" :
                                    int intCol = rs.getInt(colNum);
                                    dbRow.add(intCol);
                                    break;
                            }
                        }
                        //... then add the dbRow to the final resultSet.
                        resultSet.add(dbRow);
                    }
                //Having added all the DB rows, return the resultSet.
                return resultSet;
            }

        } catch (SQLException exception) {
            System.err.println(exception);
            return null;
        }

    }

    private void doDatabaseDML(String sql) {

        Connection cnx = connectToDB();
        if ( cnx == null ) return;

        try (
            Statement stmt = cnx.createStatement();
        ) {

            cnx.setAutoCommit(true);
            stmt.executeUpdate(sql);

        } catch (SQLException exception) {
            System.err.println(exception);
            return;
        }     

    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.setTitle("Test");
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}