如何修改自定义java.util.Stack子类实现与JavaFX ListView/TableView的绑定
JavaFX自定义栈与ListView/TableView绑定的改造方案
你当前的ComplexNumberStack继承自JDK原生java.util.Stack,本身不具备变更通知能力,无法直接和JavaFX的列表控件实现数据绑定。我们需要通过引入JavaFX的可观察集合作为底层存储,让栈的所有修改操作自动触发变更事件,实现观察者模式的效果。
改造核心要点
- 放弃继承JDK原生
Stack类:JDK的Stack是基于Vector的遗留类,性能差且不可观察,改为内部持有ObservableList<ComplexNumber>作为底层存储,对外保留标准栈操作接口+自定义的getOperand方法 - 所有修改操作直接作用于可观察集合:push、pop、批量操作的逻辑都基于内部
ObservableList实现,修改时会自动触发变更通知,不需要手动实现观察者监听逻辑 - 对外暴露只读可观察视图:避免外部直接修改内部数据破坏栈的后进先出结构,绑定控件时直接使用这个只读视图即可
改造后完整代码
import javafx.collections.FXCollections; import javafx.collections.ObservableList; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.EmptyStackException; import java.util.Iterator; import java.util.List; public class ComplexNumberStack { private static ComplexNumberStack instance = null; // 底层用ObservableList存储,支持变更通知 private final ObservableList<ComplexNumber> internalList = FXCollections.observableArrayList(); private ComplexNumberStack() {} /** This method provide the unique instance of ComplexNumberStack. */ public static ComplexNumberStack getInstance() { if (instance == null) instance = new ComplexNumberStack(); return instance; } // 保留标准栈的对外接口 public ComplexNumber push(ComplexNumber item) { internalList.add(item); return item; } public ComplexNumber pop() { if (internalList.isEmpty()) { throw new EmptyStackException(); } return internalList.remove(internalList.size() - 1); } public ComplexNumber peek() { if (internalList.isEmpty()) { throw new EmptyStackException(); } return internalList.get(internalList.size() - 1); } public boolean isEmpty() { return internalList.isEmpty(); } public int size() { return internalList.size(); } /** * 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(); } // 对外暴露只读可观察列表,用于绑定控件 public ObservableList<ComplexNumber> getObservableStack() { return FXCollections.unmodifiableObservableList(internalList); } }
绑定控件示例
绑定到ListView
ListView<ComplexNumber> stackListView = new ListView<>(); // 直接绑定只读可观察集合即可,栈变更时列表自动更新 stackListView.setItems(ComplexNumberStack.getInstance().getObservableStack());
绑定到TableView
和绑定普通ObservableList逻辑完全一致,只需要给TableColumn设置对应的cellValueFactory读取ComplexNumber的属性即可。
注意:如果你的栈修改操作是在JavaFX应用线程之外执行的,需要用
Platform.runLater()包裹修改逻辑,避免JavaFX界面更新抛出线程异常。
内容的提问来源于stack exchange,提问作者pairooo
相关产品推荐
相关产品推荐

