gpt4 book ai didi

java - ObservableArrayList 中的内容已加载(可能)但未显示

转载 作者:行者123 更新时间:2023-12-01 11:34:55 24 4
gpt4 key购买 nike

我创建了一个小程序,该程序应该从数据库加载数据并将其显示在 JavaFX 应用程序的 TableView 元素中。

问题是,当我启动应用程序时,我看到的只是空行。不同行的数据不会显示。但我确信它们会以某种方式处理,因为显示的空行数与从数据库加载的行数相匹配。

此外,我的用于调试的 System.out.prints 从数据库打印出正确的数据,因此我确定问题不在 DBLoader 类中。

大部分内容是我从 this 获取的指导。到目前为止,我所做的工作受到本教程前两部分的启发。

编辑:是的,我已添加 DatabaseOverviewControll.java 作为 DatabaseOverview.fxml 的 Controller 类。我已添加 itemNumberColumn、descriptionColumn 和 PriceColumn 作为其各自 TableColumn 元素的 fx:id。

我的 PrototypeApp 类扩展了应用程序,并且是可运行的类:

package prototype;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import prototype.util.DBLoader;
import javafx.collections.*;
import prototype.view.DatabaseOverviewController;

import prototype.model.Row;

public class PrototypeApp extends Application {

private Stage primaryStage;
private BorderPane rootLayout;

private ObservableList<Row> databaseData = FXCollections
.observableArrayList();

/**
* The constructor. Creates an dbLoader object and loads the database data
* from that dbLoader into the ObservableArrayList databaseData;
*/
public PrototypeApp() {
//DBLoader dbLoader = new DBLoader();

// databaseData = dbLoader.getData(); //This is used by me, but for the
// sake of testability I added some mock data instead.

// Some mock data for Stack Overflow users.
databaseData.add(new Row("abc", "efg", "hij"));
databaseData.add(new Row("abc2", "efg2", "hij2"));
databaseData.add(new Row("abc3", "efg3", "hij3"));
databaseData.add(new Row("abc4", "efg4", "hij4"));

// For debugging.
for (Row row : databaseData) {
System.out.println(row.getItemNumber() + "\t" + row.getDescription() + "\t" + row.getPrice());
}
}

public ObservableList<Row> getDatabaseData() {
return databaseData;
}

@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Prototype");

initRootLayout();

showDatabaseOverview();
}

/**
* Initializes the root layout.
*/
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(PrototypeApp.class
.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();

// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* Shows the database overview inside the root layout.
*/

public void showDatabaseOverview() {
try {
// Load database overview
FXMLLoader loader = new FXMLLoader();
loader.setLocation(PrototypeApp.class
.getResource("view/DatabaseOverview.fxml"));
AnchorPane databaseOverview = (AnchorPane) loader.load();

// Set the database overview into the center of root layout.
rootLayout.setCenter(databaseOverview);

// Give the controller access to the prototype app.
DatabaseOverviewController controller = loader.getController();
controller.setPrototypeApp(this);

} catch (IOException e) {
e.printStackTrace();
}
}

/**
* Returns the main stage.
*
* @return
*/

public Stage getPrimaryStage() {
return primaryStage;
}

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

这是我的 DatabaseOverviewController 类:

package prototype.view;

import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import prototype.PrototypeApp;
import prototype.model.Row;

public class DatabaseOverviewController {

@FXML
private TableView<Row> databaseTable;
@FXML
private TableColumn<Row, String> itemNumberColumn;
@FXML
private TableColumn<Row, String> descriptionColumn;
@FXML
private TableColumn<Row, String> priceColumn;

@FXML
private Label itemNumberLabel;

@FXML
private Label descriptionLabel;

@FXML
private Label priceLabel;

// Reference to the prototype application
private PrototypeApp prototypeApp;

/**
* The constructor The constructor is called before the initialize() method.
*/
public DatabaseOverviewController() {
}

/**
* Initializes a controller class. This method is automatically called after
* the fxml file has been loaded.
*/
@FXML
private void intialize() {
// Initialize the database table with the three columns.
itemNumberColumn.setCellValueFactory(cellData -> cellData.getValue()
.itemNumberProperty());
descriptionColumn.setCellValueFactory(cellData -> cellData.getValue()
.descriptionProperty());
priceColumn.setCellValueFactory(cellData -> cellData.getValue()
.priceProperty());
}

/**
* A method called by the prototype application to give a reference back to
* itself.
*
* @param prototypeApp
*/
public void setPrototypeApp(PrototypeApp prototypeApp) {
this.prototypeApp = prototypeApp;

// Adds observable list data to the table
databaseTable.setItems(prototypeApp.getDatabaseData());
}
}

这是我的行类,它代表 SQL 表中的一行:

package prototype.model;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/*
* Model class for a SQL row.
*
* @author Jonatan Stenbacka
*/

public class Row {

private final StringProperty itemNumber;
private final StringProperty description;
private final StringProperty price;

/**
* Default constructor
*/
public Row() {
this(null, null, null);
}

/**
* Constructor
* @param itemNumber
* @param description
* @param price
*/
public Row (String itemNumber, String description, String price) {
this.itemNumber = new SimpleStringProperty(itemNumber);
this.description = new SimpleStringProperty(description);
this.price = new SimpleStringProperty(price);
}

public String getItemNumber() {
return itemNumber.get();
}

public void setItemNumber(String itemNumber) {
this.itemNumber.set(itemNumber);
}

public StringProperty itemNumberProperty() {
return itemNumber;
}

public String getDescription() {
return description.get();
}

public void setDescription(String description) {
this.description.set(description);
}

public StringProperty descriptionProperty() {
return description;
}

public String getPrice() {
return price.get();
}

public void setPrice(String price) {
this.price.set(price);
}

public StringProperty priceProperty() {
return price;
}
}

编辑:这是我的 FXML 文件。如果您只添加一些模拟行数据,应该足以运行程序。

DatabaseOverview.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="prototype.view.DatabaseOverviewController">
<children>
<BorderPane layoutX="191.0" layoutY="58.0" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<top>
<Label text="Tables" BorderPane.alignment="CENTER">
<font>
<Font size="24.0" />
</font>
</Label>
</top>
<bottom>
<Button mnemonicParsing="false" onAction="#handleLoadDatabase" text="Load" BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets bottom="10.0" />
</BorderPane.margin>
</Button>
</bottom>
<center>
<TableView fx:id="databaseTable" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<columns>
<TableColumn fx:id="itemNumberColumn" prefWidth="200.0" text="Item Number" />
<TableColumn fx:id="descriptionColumn" prefWidth="200.0" text="Description" />
<TableColumn fx:id="priceColumn" prefWidth="200.0" text="Price" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</center>
</BorderPane>
</children>
</AnchorPane>

RootLayout.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>


<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>

最佳答案

DatabaseOverviewController 中有一个简单的拼写错误:你有intialize()作为方法名称,而不是 initialize() 。自 FXMLLoader使用反射来搜索名为 initialize 的方法,如果找不到,则不执行任何操作,您的方法将无法被静默调用。修复拼写错误即可解决问题。

对于它的值(value),这就是我的计算方法,因为它真的很难看到。正如您所做的那样,我观察到表中存在正确的行数(您可以选择它们),但没有显示任何内容。这几乎总是通过没有设置 cellValueFactory 来调用。 (或者设置不正确,如果您使用PropertyValueFactory,则可能会发生这种情况,但当您使用此处展示的带有 lambda 的良好方法时,这种情况很少发生)。

initialize()方法似乎正确设置了这些,我添加了日志记录,首先到 Row.itemNumberProperty() ,然后当我观察到该方法没有被调用时(它应该由该列中的每个 TableCell 调用),到 initialize()方法本身。当我观察initialize()时方法没有被调用,我发现了拼写错误。

不确定这里传达的一般信息是什么(如果有的话)?也许最好使用旧的(JavaFX 2.1 之前的)风格方法,让 Controller 实现 Initializable ,以便编译器捕获错误的方法名称。我想如果要调用的后 FXML 加载方法有一个特定的注释( @PostLoading 或其他),那就更好了。

关于java - ObservableArrayList 中的内容已加载(可能)但未显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30101161/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com