sco*_*ttb 8 java listview javafx-2
我在JavaFX 2模式对话框窗口中有一个ListView控件.
此ListView显示DXAlias实例,其列表单元由单元工厂制造.工厂对象所做的主要工作是检查ListView的UserData属性数据,并将其与ListCell对应的项进行比较.如果它们相同,则ListCell的内容将呈现为红色,否则为黑色.我这样做是为了指示ListView中的哪些项目当前被选为"默认".这是我的ListCell工厂类,所以你可以看到我的意思:
private class AliasListCellFactory implements
Callback<ListView<DXSynonym>, ListCell<DXSynonym>> {
@Override
public ListCell<DXSynonym> call(ListView<DXSynonym> p) {
return new ListCell<DXSynonym>() {
@Override
protected void updateItem(DXSynonym item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
DXSynonym dx = (DXSynonym) lsvAlias.getUserData();
if (dx != null && dx == item) {
this.setStyle("-fx-text-fill: crimson;");
} else { this.setStyle("-fx-text-fill: black;"); }
this.setText(item.getDxName());
} else { this.setText(Census.FORMAT_TEXT_NULL); }
}};
}
Run Code Online (Sandbox Code Playgroud)
我有一个名为"handleAliasDefault()"的按钮处理程序,它通过获取所选的DXAlias实例并将其存储到ListView:lsvAlias.setUserData(选定的DXAlias),使ListView中的选定项成为新的默认值.这是处理程序代码:
// Handler for Button[fx:id="btnAliasDefault"] onAction
@FXML
void handleAliasDefault(ActionEvent event) {
int sel = lsvAlias.getSelectionModel().getSelectedIndex();
if (sel >= 0 && sel < lsvAlias.getItems().size()) {
lsvAlias.setUserData(lsvAlias.getItems().get(sel));
}
}
Run Code Online (Sandbox Code Playgroud)
因为响应单击"设置默认值"按钮所做的更改是更改ListView的UserData()而不对后备ObservableList进行任何更改,所以列表未正确指示新的默认值.
有没有办法强制ListView重新呈现其ListCells?Android用户就此问题提出了数千万的问题,但似乎没有JavaFX的幸福.我可能不得不对支持数组进行"无意义的改变"以强制重绘.
我看到有人要求JavaFX 2.1:Javafx ListView刷新
Eld*_*ell 13
不确定这是否适用于JavaFX 2.2,但它确实在JavaFX 8中有用,并且花了一些时间才弄明白.您需要创建自己ListViewSkin的refresh方法并添加如下方法:
public void refresh() {
super.flow.recreateCells();
}
Run Code Online (Sandbox Code Playgroud)
这将调用updateItem而无需替换整个Observable集合.
此外,要使用新的Skin,您需要实例化它并initialize在控制器的方法上设置它,以防您使用FXML:
MySkin<Subscription> skin = new MySkin<>(this.listView); // Injected by FXML
this.listView.setSkin(skin);
...
((MySkin) listView.getSkin()).refresh(); // This is how you use it
Run Code Online (Sandbox Code Playgroud)
我在调试手风琴的行为后发现了这一点.每次展开时,此控件都会刷新它包含的ListView.
And*_*rey 12
对于最终在此页面上的任何其他身体:
这样做的正确方法是为您的可观察列表提供一个"提取器"回调.这将通知列表(和ListView)任何属性更改.
要显示的自定义类:
public class Custom {
StringProperty name = new SimpleStringProperty();
IntegerProperty id = new SimpleIntegerProperty();
public static Callback<Custom, Observable[]> extractor() {
return new Callback<Custom, Observable[]>() {
@Override
public Observable[] call(Custom param) {
return new Observable[]{param.id, param.name};
}
};
}
@Override
public String toString() {
return String.format("%s: %s", name.get(), id.get());
}
}
Run Code Online (Sandbox Code Playgroud)
而你的主要代码体:
ListView<Custom> myListView;
//...init the ListView appropriately
ObservableList<Custom> items = FXCollections.observableArrayList(Custom.extractor());
myListView.setItems(items);
Custom item = new Custom();
items.add(item);
item.name.set("Mickey Mouse");
// ^ Should update your ListView!!!
Run Code Online (Sandbox Code Playgroud)
请参阅(和类似方法):https: //docs.oracle.com/javafx/2/api/javafx/collections/FXCollections.html#observableArrayList(javafx.util.Callback)
我不确定我是否遗漏了什么,但起初我尝试了 scottb 的解决方案,但后来我发现有一个已经实现的 refresh() 方法,它对我有用。
ListView<T> list;
list.refresh();
Run Code Online (Sandbox Code Playgroud)
现在,我可以通过在我的按钮处理程序中使用名为forceListRefreshOn()的以下方法重新绘制ListView并正确指示所选的默认值:
@FXML
void handleAliasDefault(ActionEvent event) {
int sel = lsvAlias.getSelectionModel().getSelectedIndex();
if (sel >= 0 && sel < lsvAlias.getItems().size()) {
lsvAlias.setUserData(lsvAlias.getItems().get(sel));
this.<DXSynonym>forceListRefreshOn(lsvAlias);
}
}
Run Code Online (Sandbox Code Playgroud)
帮助器方法只是从ListView中交换出ObservableList,然后将其交换回来,可能是强制ListView更新其ListCells:
private <T> void forceListRefreshOn(ListView<T> lsv) {
ObservableList<T> items = lsv.<T>getItems();
lsv.<T>setItems(null);
lsv.<T>setItems(items);
}
Run Code Online (Sandbox Code Playgroud)