gpt4 book ai didi

java - 如何根据行项的属性设置 TableCell 的样式?

转载 作者:行者123 更新时间:2023-12-02 11:05:20 25 4
gpt4 key购买 nike

我的应用程序有一个 TableView,其中填充了对图像文件的引用列表。

数据从数据库加载,仅提供有关如何定位图像文件本身的信息(因此它指示图像的子文件夹和文件名)。

在我的 TableView 中,如果物理文件不存在,我想将“文件名”列的文本设置为红色。我已经实现了 CellFactory,有时它“有点”有效。 updateItem() 方法被重写以检查相关文件是否存在,但它并不总是正确的:某些行将使用红色文本样式,其他行则不会,即使它们指向相同的文件。

此外,滚动列表时,值可能会偶尔发生变化。

很难描述,所以我在下面创建了一个 MCVE。

Main.java

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.File;

public class Main extends Application {

private ObservableList<DataItem> dataItems;

public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage primaryStage) {

initData();

// Main interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));

// Setup the TableView
TableView<DataItem> tableView = new TableView<>();
TableColumn<DataItem, ImageCategory> colCategory = new TableColumn<>("Category");
TableColumn<DataItem, String> colFilename = new TableColumn<>("Filename");

// Initialize the column data
colCategory.setCellValueFactory(cellData -> cellData.getValue().categoryProperty());
colFilename.setCellValueFactory(cellData -> cellData.getValue().filenameProperty());
tableView.getColumns().add(colCategory);
tableView.getColumns().add(colFilename);

// Style text based on file exists
colFilename.setCellFactory(filenameCell -> new TableCell<DataItem, String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);

if (item == null || empty) {
setText(null);
setStyle("");
} else {

// Check if file exists
DataItem thisItem = getTableView().getItems().get(getIndex());
File imageFile = new File("C:\\Users\\XXX\\Desktop\\"
+ thisItem.getCategory().getCategoryName() + "\\"
+ item);
if (!imageFile.exists()) {
setStyle("-fx-text-fill: red");
}
setText(item);
}

}
});

tableView.setItems(dataItems);
root.getChildren().add(tableView);

primaryStage.setScene(new Scene(root));
primaryStage.setWidth(300);
primaryStage.setHeight(200);
primaryStage.show();
}

private void initData() {

dataItems = FXCollections.observableArrayList();

for (int i = 0; i < 15; i++) {
dataItems.add(new DataItem(
new ImageCategory(1, "Application Icon"),
"icon.png"));
}
for (int i = 0; i < 15; i++) {
dataItems.add(new DataItem(
new ImageCategory(1, "Logo"),
"logo.png"));
}
}
}

DataItem.java

import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;

class DataItem {

private SimpleObjectProperty<ImageCategory> category = new SimpleObjectProperty<>();
private SimpleStringProperty filename = new SimpleStringProperty();

public DataItem(ImageCategory category, String filename) {
this.category.set(category);
this.filename.set(filename);
}

public ImageCategory getCategory() {
return category.get();
}

public SimpleObjectProperty<ImageCategory> categoryProperty() {
return category;
}

public String getFilename() {
return filename.get();
}

public SimpleStringProperty filenameProperty() {
return filename;
}
}

ImageCategory.java

import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;

class ImageCategory {
private SimpleIntegerProperty categoryId = new SimpleIntegerProperty();
private SimpleStringProperty categoryName = new SimpleStringProperty();

public ImageCategory(int categoryId, String categoryName) {
this.categoryId.set(categoryId);
this.categoryName.set(categoryName);
}

public int getCategoryId() {
return categoryId.get();
}

public SimpleIntegerProperty categoryIdProperty() {
return categoryId;
}

public String getCategoryName() {
return categoryName.get();
}

public SimpleStringProperty categoryNameProperty() {
return categoryName;
}

@Override
public String toString() {
return getCategoryName();
}
}

显然,您需要一个示例文件来测试这一点。这是运行结果的屏幕截图。请注意,Logo/logo.png 确实存在:

Screenshot of display issue

您会看到第一个“logo.png”的样式正确,为纯文本,但后续条目似乎表明该文件不存在。调整窗口大小或滚动列表有时也会导致样式文本从一行更改为另一行;这是相当随机的。

如何准确测试该行代表的文件是否确实存在?

附带问题:在我的生产应用程序中,滚动非常慢且延迟,因为通过网络共享驱动器检查文件是否存在很慢。有没有办法在这些项目第一次加载时设置样式,而不是每次渲染单元格时设置样式?

最佳答案

关于单元格样式不当:

如果该项目更改为现有项目,则无需更改样式。这意味着,如果您从不存在的文件更改为现有文件,您的单元格文本将保持红色。您需要妥善处理此案:

@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);

if (item == null || empty) {
setText(null);
setStyle("");
} else {

// Check if file exists
DataItem thisItem = getTableView().getItems().get(getIndex());
File imageFile = new File("C:\\Users\\XXX\\Desktop\\"
+ thisItem.getCategory().getCategoryName() + "\\"
+ item);
if (!imageFile.exists()) {
setStyle("-fx-text-fill: red");
} else {
// modification here ----------------------------------------------
setStyle("");
}
setText(item);
}

}

至于滚动问题:

updateItem 在 JavaFX 应用程序线程上运行。在此线程上执行长时间运行的操作(例如与远程目录通信)会使 UI 无响应。通过将信息存储在项目类本身中或添加一些包含数据的结构,例如,您可以轻松避免多次检查。一张 map

与远程目录的通信仍应在单独的线程上完成。您可以对安排在某个任务上的Task 进行文件状态(EXISTENTNON_EXISTENT/UNKNOWN)的分配。 ExecutorService...

关于java - 如何根据行项的属性设置 TableCell 的样式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51011382/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com