package sample;
public class Item {
private String name;
private String state;
public Item() {}
public Item(String name, String state) {
this.name = name;
this.state = state;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
package sample;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
public class ItemWrapper {
private ObjectProperty<Item> itemProperty = new SimpleObjectProperty<>();
private Item item;
public ItemWrapper(Item item) {
setItem(item);
}
public Item getItem() {
return itemProperty.get();
}
public void setItem(Item item) {
this.item = item;
itemProperty.set(item);
}
public ObjectProperty<Item> itemProperty(){
return itemProperty;
}
}
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Item View");
primaryStage.setScene(new Scene(root, 200, 100));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="108.0" prefWidth="225.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Label layoutX="14.0" layoutY="14.0" text="show item" />
<ComboBox fx:id="cbxItemsSelector" layoutX="14.0" layoutY="31.0" prefWidth="150.0" />
<Button fx:id="btnChangeState" layoutX="14.0" layoutY="65.0" mnemonicParsing="false" onAction="#changeItemState" prefHeight="25.0" prefWidth="85.0" text="change state" />
</children>
</AnchorPane>
controller.java
package sample;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.util.Callback;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Controller {
@FXML
private ComboBox<ItemWrapper> cbxItemsSelector;
private ObservableList<ItemWrapper> items;
public void initialize(){
loadItems();
customizeSelectorCellView();
}
private void loadItems() {
List<Item> itemsList = new ArrayList<>();
itemsList.add(new Item("first item","initialized"));
itemsList.add(new Item("second item","initialized"));
List<ItemWrapper> itemWrappers = itemsList.stream().map(ItemWrapper::new).collect(Collectors.toList());
items = FXCollections.observableList(itemWrappers,wrapper -> new Observable[]{wrapper.itemProperty()});
cbxItemsSelector.setItems(items);
}
private void customizeSelectorCellView(){
cbxItemsSelector.setButtonCell(new ListCell<ItemWrapper>() {
@Override
protected void updateItem(ItemWrapper itemWrapper, boolean empty) {
super.updateItem(itemWrapper, empty);
if (empty) {
setText("");
} else {
setText(itemWrapper.getItem().getName());
}
}
});
cbxItemsSelector.setCellFactory(
new Callback<ListView<ItemWrapper>, ListCell<ItemWrapper>>() {
@Override
public ListCell<ItemWrapper> call(ListView<ItemWrapper> p) {
ListCell cell = new ListCell<ItemWrapper>() {
@Override
protected void updateItem(ItemWrapper itemWrapper, boolean empty) {
//System.out.println("update item");
super.updateItem(itemWrapper, empty);
if (empty) {
setText("");
} else {
Item item = itemWrapper.getItem();
setText(String.format("name: %s\n state: %s\n",item.getName(),item.getState()));
}
}
};return cell;
}
}
);
}
@FXML
public void changeItemState(){
ItemWrapper selectedItemWrapper = cbxItemsSelector.getSelectionModel().getSelectedItem();
if (selectedItemWrapper == null) return;
Item item = selectedItemWrapper.getItem();
item.setState("started");
}
}
问题是组合框在某些项的状态更新后看不到应用的更改。问题的原因是我只更改对象(即项)字段,而不通过setitem
方法设置新项。因此,场的变化似乎是不可观察的。我还知道,如果将ItemWrapper
类中的SimpleObjectProperty
替换为两个StringProperty
(用于名称和状态字段),它就可以工作了。但我不想做字段复制。如果在item
类中有100个字段呢?
我有两个问题:
1)如何使ComboBox在Iteem
类的任何字段中看到其他外部的更改而不重复字段(而不创建额外的字段属性)?也许我应该使用一些特殊的绑定?
2)是否有一种方法可以在保持域Iteem
类不被修改的同时去掉包装类?
据我所知,PropertyChangeListener
需要创建和注册。下面是:https://docs.oracle.com/javase/tutorial/uiswing/events/PropertyChangeListener.html
我希望我帮了忙。
祝你有愉快的一天。:)
我试图理解可观察对象是如何执行的,但似乎无法让这个简单的代码正常工作。 不应该是你好。订阅()执行?
我需要帮助,以获得一个指定的项目列表,并将它们添加到组合框。 我的观察列表包含从数据库接收的值(在特定的只有3列的表中),我想在组合框中只显示一个列值。选择组合框时,其他值在2个文本字段中收费。 代码如下。 导入Accettazioni模型: 重要信息控制器: 现在,逻辑似乎工作正常,但是我的组合框不包含值nomeProperty()。 我该如何解决? 预先感谢
问题内容: 我只是阅读了watch()方法的Mozilla文档。它看起来非常有用。 但是,我找不到与Safari类似的东西。既不是Internet Explorer。 您如何管理跨浏览器的可移植性? 问题答案: 我不久前为此创建了一个小object.watch垫片。它适用于IE8,Safari,Chrome,Firefox,Opera等。
我有一个Observable类,它在字符串变化时通知observer。在观察者的update方法中,更新的字符串可以打印到控制台。但是GUI没有相应的更新。为什么?
问题内容: 给定汽车清单(),我可以这样做: 有没有办法我可以从一个到一个序列? 像没有参数的东西 问题答案: 您可以这样映射到: 请注意,flatMapping可能不会保留源可观察的顺序。如果订单对您很重要,请使用。
问题内容: 我一直在阅读Observer模式,以保持UI处于最新状态,但仍然看不到它的用途。即使在我的特定对象中通知了我的MainActivity然后运行update();方法我仍然无法使用Pet对象来获取更新值,因为该对象是在Oncreate中创建的…而我只是无法创建新对象,因为那时变量会有所不同..这是我的实施,它似乎不起作用。 观察者/ MainActivity 可观察/宠物 问题答案: 首