gpt4 book ai didi

JavaFX 将组件添加到列表中,动态更改其内容

转载 作者:行者123 更新时间:2023-11-30 02:20:59 25 4
gpt4 key购买 nike

使用 Fxml,我的主屏幕上有一个 ListView。

然后我制作了一个单独的 Fxml。这称为卡片,显示金融股票信息(股票代码和当前价格,带有 2 个标签)

如何创建该卡的多个实例,以便每个实例都有不同的股票名称和价格,并且可以更新价格?

public ListView searchList;
public Button searchButton;

@FXML
public void handleSearchButton(ActionEvent event) throws IOException {
loadFxml();
}

public void loadFxml () throws IOException {
Pane newLoadedPane = FXMLLoader.load(getClass().getResource("card.fxml"));
searchList.getItems().add(newLoadedPane);
}

目前,该代码会将卡片的硬编码版本添加到 ListView。我相信它们都是一样的,所以如果我更新文本,它们都会更新。

最佳答案

要创建由 FXML 定义的 UI 组件的多个实例,您只需多次加载 FXML 文件即可。如果您希望每个数据都有不同的数据,请在 Controller 中定义方法来更改数据。那么你基本上可以这样做

for (int i = 0 ; i < numberOfStocks ; i++) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("card.fxml"));
Pane stockView = loader.load();
StockController controller = loader.getController();
controller.setXXX(...);
// ...
}

我强烈不建议填充 ListView使用 UI 节点,如问题中的代码所示。 UI 元素是创建起来相当昂贵的对象(它们有数百个属性,并且受 CSS 支持,可能需要解析等)。您所表示的数据非常简单:一个字符串和一个代表股票代码和价格的 double 值。一个ListView设计得非常高效,因为它只为可见数据创建 UI 元素,并在用户滚动浏览这些元素时重用这些元素。所以你的ListView应仅使用其支持列表中的数据,而不是 UI 元素。

因此创建一个简单的类来表示股票:

public class Stock {

private final String symbol ; // doesn't change

private final DoubleProperty price = new SimpleDoubleProperty() ; // mutable and observable

public Stock(String symbol, double price) {
this.symbol = symbol ;
setPrice(price);
}

public DoubleProperty priceProperty() {
return price ;
}

public final double getPrice() {
return priceProperty().get();
}

public final void setPrice(double price) {
priceProperty().set(price);
}

public String getSymbol() {
return symbol ;
}
}

这个Stock使用的类JavaFX properties这将使以后更容易绑定(bind)到它们(这样,如果价格发生变化,UI 可以自动更新)。

现在您可以定义一个简单的 FXML:

<!-- imports etc -->

<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.StockController"/>
<Label fx:id="symbolLabel"/>
<Label fx:id="priceLabel" />
</VBox>

及其 Controller ,可以实现标签与其显示的库存的绑定(bind):

public class StockController {

private Stock stock ;

@FXML
private Label symbolLabel ;

@FXML
private Label priceLabel ;

public void setStock(Stock stock) {
this.stock = stock ;
priceLabel.textProperty().unbind();
if (stock == null) {
symbolLabel.setText(null);
priceLabel.setText(null);
} else {
symbolLabel.setText(stock.getSymbol());
priceLabel.textProperty().bind(stock.priceProperty().asString("Price: $%.2f"));
}
}
}

现在您可以创建 ListView<Stock>并使用其 cell factory使用 FXML 显示每只股票:

public class MainController {

@FXML
private ListView<Stock> searchList ;

public void initialize() {
searchList.setCellFactory(lv -> new StockListCell());
}

}
public class StockListCell extends ListCell<Stock> {

private final Pane stockView ;
private final StockController stockController ;

public StockListCell() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("card.fxml"));
stockView = loader.load();
stockController = loader.getController();
setGraphic(stockView);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} catch (IOException exc) {
// IOException here is fatal:
throw new UncheckedIOException(exc);
}
}

@Override
protected void updateItem(Stock item, boolean empty) {
super.updateItem(item, empty);
stockController.setStock(item);
}
}

请注意 ListView不会创造很多StockListCell s(每个可见单元格只有一个),因此在构造函数中执行相当繁重的工作(例如加载 FXML)是可以的。 updateItem(...)相比之下,方法可能会被非常频繁地调用(例如,当用户滚动时),并且应该做最少的工作。在这里,我们只是更新了 UI 显示的库存,这实际上只是更改了几个标签的文本。

最后,您可以简单地使用 Stock 填充 ListView 。正如您所期望的:

for (int i = 0 ; i < numberOfStocks ; i++) {
String symbol = "Stock "+i ;
double price = 1000*Math.random();
Stock stock = new Stock(symbol, price) ;
searchList.getItems().add(stock);
}

关于JavaFX 将组件添加到列表中,动态更改其内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46829316/

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