JavaFX ListView Отображение одного столбца из двух столбцов наблюдаемого списка - PullRequest
0 голосов
/ 15 октября 2018

Я получил несколько замечательных советов от @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();
    }
}    

Я понятия не имею, как работает лямбда, но я попаду туда.Отладка Я вижу, что divisionListRow заполняется.Но я ожидаю, что данные divsResult.getString(2) появятся.ТКС

1 Ответ

0 голосов
/ 15 октября 2018

Три вещи, которые я вижу ...

Объявите ваш ListView как ListView<EmployeeDivision>.Это устанавливает его тип на EmployeeDivision.

. setCellFactory не должен быть в цикле загрузки данных while (divsResult.next()).Его нужно объявлять только один раз, а не каждый раз, когда строка загружается из БД в ObservableList.

. Вам нужно сделать menuList1.setItems(divisionListRow).setItems() - это то, что связывает ваши данные с ListView.

Вот MVCE, который выдает ListView, который выглядит следующим образом:

enter image description here

Когда вы щелкаете по состоянию, оно выводит идентификатор подразделения на консоль.

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

}
...