我正在使用javafx tableview和observableList,我试图防止List包含重复的项目。在做了一些搜索之后,我发现一个observableSet可以通过覆盖这些方法来完成这项工作:equals()和hashcode()。
但是javaFX tableview不能保存可观察集的问题:
tableView.setItems(FXCollections.observableSet(new hashSet<T>());
我还计划计算tableview中a列的some,所以我需要
// After change in element T the total will change
ObservableList<T> listItems = FXCollections.observableArrayList(
T -> new Observable[]{T.doSomeCalculeProperty});
我真的对正确的方法感到困惑。所以,我需要你的提示
您可以创建一个<code>ObservableSet</code>,然后向其中添加一个侦听器,该侦听器将更新用作表项列表的<code>ObservableList</code>。只要不直接对表的项进行修改(仅对集合进行修改,您可以通过使用表的不可修改列表强制执行),那么表将始终包含与集合完全相同的项。
要跟踪列表中所有项目的属性值的总和,您需要向列表注册侦听器,并在其更改时重新计算总数。如果属性本身可能发生变化,您可以在创建列表时使用提取器,以便如果任何列表元素的属性发生变化,列表将触发更新通知。
此示例将所有这些拼凑在一起。与按钮关联的修改方法都在 ObservableSet
上运行。请注意,如果尝试添加与现有项相等的项,则不会发生任何更改(因为添加到集合不会执行任何操作,因此不会向列表触发任何更新)。
您可以使用增量和减量按钮选择和修改现有项目,您将看到更新反映在总数中。
import java.util.HashSet;
import java.util.Objects;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.ObservableSet;
import javafx.collections.SetChangeListener.Change;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class UniqueItemTableViewWithTotal extends Application {
// creates a table view which always contains the same items as the provided set
private TableView<Item> createTableView(ObservableSet<Item> items, IntegerProperty total) {
TableView<Item> table = new TableView<>();
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// Want the table's items list to fire updates if the value of any item changes
// This allows observing the list for tracking the total of all values
ObservableList<Item> itemList = FXCollections.observableArrayList(
item -> new Observable[] {item.valueProperty()});
// register a listener with the set and update the list if the set changes
// this ensures the list will always contain the same elements as the list,
items.addListener((Change<? extends Item> c) -> {
if (c.wasAdded()) {
itemList.add(c.getElementAdded());
}
if (c.wasRemoved()) {
itemList.remove(c.getElementRemoved());
}
});
// usual column setup
TableColumn<Item, String> nameCol = new TableColumn<>("Item");
nameCol.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
TableColumn<Item, Integer> valueCol = new TableColumn<>("Value");
valueCol.setCellValueFactory(cellData -> cellData.getValue().valueProperty().asObject());
table.getColumns().add(nameCol);
table.getColumns().add(valueCol);
// use an unmodifiable list for the table to prevent any direct updates to the
// table's list (updates must go through the set)
table.setItems(FXCollections.unmodifiableObservableList(itemList));
// update total if the items list changes:
itemList.addListener((ListChangeListener.Change<? extends Item> c) ->
total.set(itemList.stream()
.collect(Collectors.summingInt(Item::getValue))));
// add any existing elements:
itemList.addAll(items);
return table ;
}
@Override
public void start(Stage primaryStage) {
ObservableSet<Item> items = FXCollections.observableSet(new HashSet<>());
IntegerProperty total = new SimpleIntegerProperty();
TableView<Item> table = createTableView(items, total);
for (int i = 1; i <=5 ; i++) {
items.add(new Item("Item "+i, 1+(int)(Math.random()*20)));
}
// label to display the total of all values:
Label totalLabel = new Label();
totalLabel.textProperty().bind(total.asString("Total: %d"));
totalLabel.setStyle("-fx-font-size:24; -fx-padding:10;");
// text fields for new item:
TextField itemField = new TextField();
TextField valueField = new TextField();
// restrict value field to valid integers:
valueField.setTextFormatter(new TextFormatter<Integer>(c ->
c.getControlNewText().matches("-?\\d*") ? c : null));
// button to add new item:
Button addButton = new Button("Add");
addButton.setOnAction(e -> {
Item item = new Item(itemField.getText(), Integer.parseInt(valueField.getText()));
items.add(item);
itemField.clear();
valueField.clear();
});
addButton.disableProperty().bind(itemField.textProperty().isEmpty()
.or(valueField.textProperty().isEmpty()));
ObservableList<Item> selection = table.getSelectionModel().getSelectedItems();
// button to remove selected item(s):
Button removeButton = new Button("Delete");
removeButton.setOnAction(e ->
items.removeIf(new HashSet<Item>(selection)::contains));
removeButton.disableProperty().bind(Bindings.isEmpty(selection));
// button to increment selected item(s):
Button incButton = new Button("Increment");
incButton.setOnAction(e -> selection.forEach(Item::increment));
incButton.disableProperty().bind(Bindings.isEmpty(selection));
// button to decrement selected item(s):
Button decButton = new Button("Decrement");
decButton.setOnAction(e -> selection.forEach(Item::decrement));
decButton.disableProperty().bind(Bindings.isEmpty(selection));
HBox controls = new HBox(5, itemField, valueField, addButton, removeButton, incButton, decButton);
controls.setAlignment(Pos.CENTER);
controls.setPadding(new Insets(5));
BorderPane root = new BorderPane(table);
root.setTop(totalLabel);
root.setBottom(controls);
Scene scene = new Scene(root, 800, 800);
primaryStage.setScene(scene);
primaryStage.show();
}
// model item:
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
public void increment() {
setValue(getValue()+1);
}
public void decrement() {
setValue(getValue()-1);
}
@Override
public int hashCode() {
return Objects.hash(getName(), getValue());
}
@Override
public boolean equals(Object o) {
if (o.getClass() != Item.class) {
return false ;
}
Item other = (Item) o ;
return Objects.equals(getName(), other.getName())
&& getValue() == other.getValue() ;
}
}
public static void main(String[] args) {
launch(args);
}
}
我在tableview中使用的一列有问题<本栏最初用于显示我拥有的一种数据类型: 我想更改此列中显示的数据,因此我更改了FXML文件中的列名,并编写了以下内容: 我的ResearchData类编码如下: (我只保留了rang、luse和lSysteme,但我有很多其他变量都是这样写的)。 当我启动程序时,在tableview中,除Systeme列外,所有列都正确显示,我收到了以下错误消息: 我可以
问题内容: 我想创建一个表来存储设备设置。该表具有三行:id,parameter_name和parameter_value。 该表是通过执行以下查询语句创建的: 然后通过执行以下方法存储行: 创建数据库后,将存储默认值: 但是,方法insertRow()的问题在于它无法防止重复输入。 有谁知道在这种情况下如何防止重复输入? 问题答案: 您可以使用列约束。 UNIQUE约束导致在指定列上创建唯一索引
我正在设计一个主要通过键盘控制的Android应用程序。 在此应用程序中,有两个彼此相邻的列表视图。但是,当焦点在列表视图之间更改时,新列表视图中的选择将更改为最接近旧列表视图中所选内容的项目 - 我不希望所选项目更改,直到用户随后在键盘上按 UP 或 DOWN 键。 例子: 列表A未聚焦,选择了项目3。列表B当前具有焦点,并且在该列表视图中,项目B当前被选择。 目前,如果用户按下键盘上的“左”,
我有这个MySQL表 我在这里的目标是防止数据库为给定项目创建重复的。例如,具有的项目具有,但如果我再次输入,它将阻止它输入。但是,如果并且给定的,那么它应该不会有任何问题地插入它。我的问题是,如何防止每个项目重复?
我有一个带有的javafx应用程序。只有第一列()是可编辑的,它包含用于编辑的。现在,完成了它应该做的事情,但是,当我开始编辑单元格,然后在没有提交编辑的情况下将其滚动到视图之外时,会出现一些奇怪的bug。我很肯定这是因为重用单元格的方式。然而,我还没有找到任何方法来干预它,例如禁止重用当前正在编辑的单元格。你能帮我做那个吗。 列的值如下所示: 如果这是混淆的,我为提供的项是(从0到n-1),在不
我想防止重复的值进入数据库表从一个使用PHP的表单。 具有名为clients的表的数据库: 一个名为form的简单表单。html 名为frm_脚本的表单处理脚本。php 到目前为止,我的frm_脚本。php文件,上面的作品和一个独特的记录显示客户添加。然而,对于重复记录,它抛出“错误查询数据库”。 如何更新以下frm_script.php脚本? 如果在输入名/姓组合时发现重复行,则应显示消息“Cl