В моем приложении есть 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
существует существует:
Вы видите, что первый "logo.png" оформлен правильно, какобычный текст, но последующие записи, кажется, указывают, что файл не существует.Изменение размера окна или прокрутка списка также может иногда приводить к изменению стиля текста из одной строки в другую;это довольно случайно.
Как я могу точно проверить, существует ли файл, представленный строкой?
Дополнительный вопрос: в моем производственном приложении прокрутка оченьтакже медленный и с задержкой, так как проверка наличия файла выполняется медленно на сетевом общем диске.Есть ли способ стилизовать эти элементы при их первой загрузке, а не при каждом отображении ячейки?