我最近正在使用javaFx,并希望通过绑定堆栈更新实现观察者模式,使用javaFx中的ListView或TableView。但是,我不知道要对我的ComplexNumberStack类做什么更改。
public class ComplexNumberStack extends Stack<ComplexNumber>{
private static ComplexNumberStack instance = null;
/**
* This method provide an instance of a ComplexNumberStack.
*/
public static ComplexNumberStack getInstance() {
if (instance == null)
instance = new ComplexNumberStack();
return instance;
}
/**
* This method provides a secure implementation of massive pop of operandNumber operands from the stack
*
* @param operandNumber specifies the number of operands to be taken from the stack
* @return an iterator of complexNumber taken
*/
public Iterator<ComplexNumber> getOperand(int operandNumber) {
List<ComplexNumber> operands = new ArrayList<>();
for (int i = 0; i < operandNumber; i++) {
try {
operands.add(pop());
} catch (EmptyStackException e) {
Collections.reverse(operands);
operands.forEach(this::push);
throw new InvalidParameterException("There aren't enough operands into the stack");
}
}
return operands.iterator();
}
}
此示例在堆栈实现周围添加了一个包装类,它提供了一个ObservableList,可以是:
为了使其工作,必须在包装类而不是底层类上调用突变操作(例如push/pop)。
还有更有效的实现方法(例如,不要子类stack,而是实现deque
接口,并直接使用ObservableList作为存储)。
然而,这是我想出的仍然保留您的底层类,它可能是好的或容易适应您的目的。
public record ComplexNumber(double real, double imaginary) {}
底层堆栈实现与问题中的类没有变化。
import java.security.InvalidParameterException;
import java.util.*;
public class ComplexNumberStack extends Stack<ComplexNumber> {
private static ComplexNumberStack instance = null;
/**
* This method provide an instance of a ComplexNumberStack.
*/
public static ComplexNumberStack getInstance() {
if (instance == null)
instance = new ComplexNumberStack();
return instance;
}
/**
* This method provides a secure implementation of massive pop of operandNumber operands from the stack
*
* @param operandNumber specifies the number of operands to be taken from the stack
* @return an iterator of complexNumber taken
*/
public Iterator<ComplexNumber> getOperand(int operandNumber) {
List<ComplexNumber> operands = new ArrayList<>();
for (int i = 0; i < operandNumber; i++) {
try {
operands.add(pop());
} catch (EmptyStackException e) {
Collections.reverse(operands);
operands.forEach(this::push);
throw new InvalidParameterException("There aren't enough operands into the stack");
}
}
return operands.iterator();
}
}
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.EmptyStackException;
public class ObservedComplexNumberStack {
private final ObservableList<ComplexNumber> observableList;
public ObservedComplexNumberStack(ComplexNumberStack complexNumberStack) {
observableList = FXCollections.observableList(complexNumberStack);
}
public ComplexNumber pop() {
if (observableList.size() == 0) {
throw new EmptyStackException();
}
return observableList.remove(observableList.size() - 1);
}
public ComplexNumber push(ComplexNumber number) {
observableList.add(number);
return number;
}
public ObservableList<ComplexNumber> getObservableList() {
return FXCollections.unmodifiableObservableList(observableList);
}
}
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.concurrent.ThreadLocalRandom;
public class StackApplication extends Application {
@Override
public void start(Stage stage) {
ObservedComplexNumberStack stack = new ObservedComplexNumberStack(
ComplexNumberStack.getInstance()
);
ListView<ComplexNumber> listView = new ListView<>(stack.getObservableList());
listView.setPrefSize(80, 150);
listView.setCellFactory(param -> new ListCell<>() {
@Override
protected void updateItem(ComplexNumber item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
return;
}
setText(String.format("%.2f + %.2fi", item.real(), item.imaginary()));
}
});
Button push = new Button("Push");
push.setOnAction(e -> {
stack.push(randomNum());
scrollToLastItem(listView);
});
Button pop = new Button("Pop");
pop.setOnAction(e -> {
stack.pop();
scrollToLastItem(listView);
});
pop.disableProperty().bind(Bindings.isEmpty(listView.getItems()));
HBox controls = new HBox(10, push, pop);
VBox layout = new VBox(10, controls, listView);
layout.setPadding(new Insets(10));
Scene scene = new Scene(layout);
stage.setScene(scene);
stage.show();
}
private void scrollToLastItem(ListView<ComplexNumber> listView) {
if (listView.getItems().size() > 0) {
listView.scrollTo(listView.getItems().size() - 1);
}
}
private ComplexNumber randomNum() {
ThreadLocalRandom r = ThreadLocalRandom.current();
return new ComplexNumber(r.nextDouble(9), r.nextDouble(9));
}
public static void main(String[] args) {
launch();
}
}
嗯..这看起来有点脆弱--外部代码可以在不通知列表的情况下更改堆栈(尤其是,因为是一个单人,潜在的合作者遍布世界各地
是的,这是真的,它的买家要小心:-)
另一种建议的解决方案是直接在支持的observableList上使用操作实现Deque,但我现在不打算写这个(要做好这件事需要做更多的工作)。
这个答案中的解决方案使用FXCollections列表包装器,顺便说一句,它本身就是解决这个问题的另一个简单解决方案:
FXCollections.observableList(ComplexNumberStack.getInstance());
不过,它也有一些缺点:
如果您对JavaFX框架实现包装器的工作方式感兴趣,可以查看ObservableListWrapper的代码。
如果您愿意,您可以将ObservableListWrapper的一个版本复制到您自己的包中(您不想直接依赖于com.sun代码),然后对其进行子类化并对其进行修改以添加额外的push/pop操作(正如kleopatra在注释中建议的那样)。
我想在JavaFX中显示内容。下面是我用来将内容设置到表列中的代码。我遇到的问题是,它只显示一行。循环只迭代了5次:每次它都会获取的第一个值。 如果忽略行,则循环将迭代中的所有内容。
我在将dsata绑定到tabl时遇到了一些麻烦;JavaFX中的E 我有我的模型controtor.java 公共课指挥{
现在,我正在尝试让ListView具有一些可绑定的CustomCells。我将XAML中的单元格定义为DataTemplate下的ViewCell和ListView.ItemTemplate下的ViewCell。 为了简单起见,让我们假设我在单元格中表示了两个字符串。ViewCell看起来如下所示: 编辑1: 我尝试编写一个模仿一些示例的文件,但这还不够。没有一段代码解释该文件是XAML中表示Vi
主要内容:绑定选项,双向绑定,高级别绑定,低级别绑定,UI控件和域模型之间的绑定JavaFX绑定同步两个值:当依赖变量更改时,其他变量更改。 要将属性绑定到另一个属性,请调用bind()方法,该方法在一个方向绑定值。 例如,当属性A绑定到属性B时,属性B的更改将更新属性A,但不可以反过来。 绑定选项 JavaFX提供了许多绑定选项,以便在域对象和GUI控件中的属性之间进行同步。 我们可以在JavaFX的Properties API中使用以下三种绑定策略: Java Bean上
我有一个“列和”列的道路。车道数显示一个整数,即道路的车。添加新道路时,我有另一个 ,在其中设置车道的属性。我的类是: 我正在尝试创建一个类,我想在其中绑定一个属性与
我正在创建一个asp.net页面,允许用户跨多个数据库搜索。 如果找到匹配项,我希望在主ListView中返回数据库名称。然后,我想在相应的数据库名称下,在嵌套的ListView中显示与搜索条件匹配的所有公司。 e. g.搜索:公司 后果 数据库1名称 数据库2名称 数据库3名称 如何引用和填充嵌套的ListView?