如何解决有没有办法在 JavaFX 中使 ListView 元素加粗?
所以我是 JavaFX 的新手,我正在制作我的第一个应用程序。我想有一个选项,在选择它并单击按钮后,将我的 ListView 中的元素设为粗体。不幸的是,我找不到任何解决我的问题的方法,而且我没有想法。如果您能告诉我如何在 .java 或 .fxml 文件中执行此操作,我将不胜感激,因为我现在不使用 CSS 文件。
解决方法
实现这样的功能需要做一些事情:
- 适合您的
ListView
的数据模型
- 用于您的
CellFactory
的自定义ListView
,将修改其中包含的项目的样式 - 一种更新 Person 模型以将个人标记为“重要”的方法
在此答案的底部有一个完整的示例应用程序(带有注释),但让我们将其分解并解决上述问题。
数据模型:
如果您使用简单的 String
作为 ListView
的类型(即:ListView<String>
),您需要更改它以提供自定义对象。对于此示例,我们将创建一个新的 Person
类。
class Person {
private final StringProperty name = new SimpleStringProperty();
private final BooleanProperty important = new SimpleBooleanProperty(false);
public Person(String name) {
this.name.set(name);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public boolean isImportant() {
return important.get();
}
public BooleanProperty importantProperty() {
return important;
}
public void setImportant(boolean important) {
this.important.set(important);
}
}
现在,您需要相应地定义您的 ListView
:
ListView<Person> listView = new ListView<>();
自定义 CellFactory:
CellFactory
是 ListView
的一部分,它处理呈现 ListView
中每一行的实际内容。为了根据特定 Person
的属性更改单元格的外观,我们必须提供我们自己的实现(JavaFX 的标准实现将简单地呈现每个单元格以包含项目的 toString()
方法) .
listView.setCellFactory(cell -> new ListCell<Person>(){
@Override
protected void updateItem(Person person,boolean empty) {
super.updateItem(person,empty);
// First,we are only going to update the cell if there is actually an item to display there.
if (!empty && person != null) {
// Set the text of the cell to the Person's name
setText(person.getName());
// If the Person has the "important" flag,we can make the text bold here
if (person.isImportant()) {
setStyle("-fx-font-weight: bold");
} else {
// Remove any styles from the cell,because this Person isn't important
setStyle(null);
}
} else {
// If there is no item to display in this cell,set the text to null
setText(null);
}
}
});
更新“重要”属性:
您的 MenuItem
的操作应更新所选人员的 important
属性。这相当简单:
mnuSetImportant.setOnAction(event -> {
Person selectedPerson = listView.getSelectionModel().getSelectedItem();
if (selectedPerson != null) {
selectedPerson.setImportant(!selectedPerson.isImportant());
}
});
请注意,在这种情况下,我已将操作设置为切换此人的重要状态。您可以轻松地将属性设置为 true
,但如果不添加单独的菜单选项,您将无法再次将其设置为 false
。
然而,在此之后,您会注意到单元格不会使用新样式更新自身。这是因为 ListView
不会“侦听”每个 Person
的属性更改。因此,在下面的示例中,我们向 extractor()
类添加了一个静态 Person
方法,该方法允许其属性触发对 ListView
的更新。
就是这样!下面是一个完整的应用程序,您可以亲自试用以查看它的实际效果:
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ListViewItemProperties extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// **********************************************************************************************
// Create a basic layout
// **********************************************************************************************
BorderPane root = new BorderPane();
// **********************************************************************************************
// Create the menu bar and Menu items
// **********************************************************************************************
MenuBar menuBar = new MenuBar();
Menu mnuMore = new Menu("More");
MenuItem mnuSetImportant = new MenuItem("Set important");
// **********************************************************************************************
// Create the ListView
// **********************************************************************************************
ListView<Person> listView = new ListView<>();
// **********************************************************************************************
// Set the action for the "Set important" menu item to update the property of the selected
// Person in the ListView,if applicable
// **********************************************************************************************
mnuSetImportant.setOnAction(event -> {
// **********************************************************************************************
// Get reference to the currently selected Person
// **********************************************************************************************
Person selectedPerson = listView.getSelectionModel().getSelectedItem();
if (selectedPerson != null) {
// **********************************************************************************************
// If a person has been selected,toggle their "important" property
// **********************************************************************************************
selectedPerson.setImportant(!selectedPerson.isImportant());
}
});
// **********************************************************************************************
// Assemble the menus
// **********************************************************************************************
mnuMore.getItems().add(mnuSetImportant);
menuBar.getMenus().add(mnuMore);
// **********************************************************************************************
// Create some sample Persons and add them to the ListView. This will also configure the list with
// the extractor we created in the Person class in order to trigger updates to the ListView when any
// of the Person's properties change.
// **********************************************************************************************
ObservableList<Person> people = FXCollections.observableArrayList(Person.extractor());
people.addAll(
new Person("Dad"),new Person("Sis"),new Person("Babe"));
listView.setItems(people);
// **********************************************************************************************
// Here we will create our own CellFactory so we can set the style of the text based on the
// important property of each Person
// **********************************************************************************************
listView.setCellFactory(cell -> new ListCell<Person>() {
@Override
protected void updateItem(Person person,boolean empty) {
super.updateItem(person,empty);
// First,we are only going to update the cell if there is actually an item to display there.
if (!empty && person != null) {
// Set the text of the cell to the Person's name
setText(person.getName());
// If the Person has the "important" flag,we can make the text bold here
if (person.isImportant()) {
setStyle("-fx-font-weight: bold");
} else {
// Remove any styles from the cell,because this Person isn't important
setStyle(null);
}
} else {
// If there is no item to display in this cell,set the text to null
setText(null);
}
}
});
// **********************************************************************************************
// Assemble the Scene
// **********************************************************************************************
root.setTop(menuBar);
root.setCenter(listView);
// **********************************************************************************************
// Set the Scene for the stage
// **********************************************************************************************
primaryStage.setScene(new Scene(root));
// **********************************************************************************************
// Configure the Stage
// **********************************************************************************************
primaryStage.setTitle("Test Application");
primaryStage.show();
}
}
class Person {
// Name of this person
private final StringProperty name = new SimpleStringProperty();
// Boolean property to track whether this person has been flagged as "important"
private final BooleanProperty important = new SimpleBooleanProperty(false);
public Person(String name) {
this.name.set(name);
}
/**
* Callback to trigger updates whenever a property of a Person is changed. This allows our ListView
* to refresh the cell when the "important" property changes.
*/
public static Callback<Person,Observable[]> extractor() {
// **********************************************************************************************
// Return the callback which fires change events whenever either name or important properties
// are updated. A ListView normally only listens for changes to its Items list but ignores
// changes to the item's internal properties.
// **********************************************************************************************
return (Person p) -> new Observable[]{
p.name,p.important
};
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
public boolean isImportant() {
return important.get();
}
public void setImportant(boolean important) {
this.important.set(important);
}
public BooleanProperty importantProperty() {
return important;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。