我已经简化了下面的代码在更新的表视图。
由于某些原因,我没有像人们所期望的那样使用JavaFx的属性,也许这种行为与此有关。来自JTable和observer模式,我想尝试如何在javafx中实现这一点。然而,我的表格数据都很好,但当我试图改变背景颜色时,更多的行出现在表格范围之外。我已经检查了可观察列表的大小,结果与预期一致。
我无法真正看到或理解datas.set是如何产生这种行为的,这是我在代码中错过的东西,还是Javafx tableview的预期行为。
基本上使用的逻辑是,我从另一个类接收更新(我在这里用线程模拟),然后我将用更新的数据更新可观察列表的相应行。
谢谢。
package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
Pane root = new Pane();
root.getChildren().add(new TableModel().getTable());
Scene scene = new Scene(root,400,800);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
package application;
import java.util.Random;
import javafx.application.Platform;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.util.Callback;
public class TableModel{
private TableView<TableData> table = new TableView<>();
private ObservableList<TableData> datas;
@SuppressWarnings("unchecked")
public TableModel() {
datas = FXCollections.observableArrayList();
final TableColumn<TableData, Integer> cId = new TableColumn<>("ID");
cId.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<TableData, Integer>, ObservableValue<Integer>>() {
@Override
public ObservableValue<Integer> call(CellDataFeatures<TableData, Integer> param) {
return new SimpleObjectProperty<Integer>(param.getValue().getId());
}
});
cId.setCellFactory(e -> new TableCell<TableData, Integer>() {
@Override
public void updateItem(Integer item, boolean empty) {
// Always invoke super constructor.
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(String.valueOf(item));
if (getIndex() == 0) {
this.setStyle("-fx-background-color: green;");
}else {
this.setStyle("-fx-background-color: red;");
}
}
}
});
table.getColumns().addAll(cId);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.setItems(datas);
table.setPrefSize(150, 450);
datas.add(0, new TableData(0));
datas.add(1, new TableData(0));
datas.add(2, new TableData(0));
datas.add(3, new TableData(0));
datas.add(4, new TableData(0));
new Thread(()->{
while(true) {
Random rand = new Random(10);
update(rand.nextInt());
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}).start(); ;
}
public TableView<TableData> getTable() {
return table;
}
public void update(int num) {
TableData data = new TableData(num);
Platform.runLater(() -> {
datas.set(0, data);
});
}
private class TableData {
private SimpleIntegerProperty cId = new SimpleIntegerProperty();
public TableData(Integer conid) {
this.cId.setValue(conid);
}
public Integer getId() {
return cId.get();
}
}
}
输出数据。集合(0,数据)
输出不带
datas.set(0,数据);
您的代码有4个问题:
final TableColumn<TableData, Integer> cId = new TableColumn<>("ID");
cId.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<TableData, Integer>, ObservableValue<Integer>>() {
@Override
public ObservableValue<Integer> call(CellDataFeatures<TableData, Integer> param) {
return new SimpleObjectProperty<Integer>(param.getValue().getId());
}
});
这样可以防止属性的更改自动触发更新。例如。
table.getItems().get(0).cId.set(5);
不会导致表的更新。要修复此问题,请返回属性本身,而不是在执行cellValueFactory
时用属性值初始化的新创建的属性。
final TableColumn<TableData, Number> cId = new TableColumn<>("ID");
cId.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<TableData, Number>, ObservableValue<Number>>() {
@Override
public ObservableValue<Number> call(TableColumn.CellDataFeatures<TableData, Number> param) {
return param.getValue().cId;
}
});
@Override
public void updateItem(Integer item, boolean empty) {
// Always invoke super constructor.
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(String.valueOf(item));
if (getIndex() == 0) {
this.setStyle("-fx-background-color: green;");
}else {
this.setStyle("-fx-background-color: red;");
}
}
}
这种实现是不正确的,因为单元格在填充值后可能会变空。您应该确保恢复“空”外观,以防单元格变空。这需要您清除样式属性:
@Override
protected void updateItem(Number item, boolean empty) {
// Always invoke supertype's implementation
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setStyle(null);
} else {
setText(item.toString());
if (getIndex() == 0) {
this.setStyle("-fx-background-color: green;");
} else {
this.setStyle("-fx-background-color: red;");
}
}
}
new Thread(()->{
while(true) {
Random rand = new Random(10);
update(rand.nextInt());
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}).start();
即使GUI关闭,阻止程序终止,该线程仍将保持活动状态。您可以通过使用守护进程线程轻松修复此问题。
此外,使用种子初始化的随机Random
将返回确定性结果。由于在循环的每次迭代中使用相同的种子重新初始化Random
,因此值rand。nextInt()
返回值始终相同。您需要将随机
的初始化移到循环之外。
Thread thread = new Thread(() -> {
Random rand = new Random(10);
while (true) {
update(rand.nextInt());
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
});
thread.setDaemon(true);
thread.start();
问题内容: 我在网上看到了一些向TableView添加行的示例,例如使用Oracle文档中的Person类。 但是我的列数是可变的,所以我不能绑定到Person(或任何其他)bean业务对象。 Oracle示例继续显示如何将列绑定到属性名称,但为此,它仅显示如何添加列,而不显示行。 我的问题是,有人可以给我指出一个Hello,World示例,它向JavaFX 8 TableView动态添加任意列和
如何使用JavaFX TableView实现嵌套的行(而不是列)?还是在TableView中合并行?
我在禁用TableView中的行时遇到问题。我有一个包含三列的TableView。名称列、值列和复选框列。如果用户选中复选框,则应使用与选中行中的值相同的值禁用所有行。我尝试使用ReactFX2框架在禁用的属性和单元格之间创建绑定,但没有成功。有没有一个简单的方法来处理我的问题。这是我的代码: trafficvolume.class controller.class 我想禁用所有与所选行具有相同f
我已经用FXML定义了一个tableview。它类似于以下内容: Action列将在每一行中包含带有文本“Delete”的按钮。我有两个问题: 如何将此删除按钮添加到JavaFX中的每一行最后一个单元格? 如何获取已单击“删除”按钮的行的索引?(以便删除该行或进行其他事件处理工作)
当您将一个项目添加到一个ObservableList中(该列表显示在TableView中)时,如何在添加重复项目时更新行? 例如,考虑一个包含三个列的TableView:项目、数量和价格。这可以通过以下代码来实现: 在其当前形式中,您可以得到如下表: 项目 --------- 数量 ----- 价格。 炒面----- 1 ----------- 4.20。 泰国-------- 1 -------
所以我遇到了这个方法,它能够按值对HashMaps进行排序。 我想在比较器上使用方法,但是我似乎找不到合适的地方放它。