带有复选框的 vaadin8.1.0 网格有问题
vaadin8.1.0 Grid with Checkbox had an Issue
我正在使用 vaadin 8.1.0 网格。我需要将复选框作为列和列 header 插入。当我单击 header 列中的复选框时,应选中所有列的复选框。那工作正常。但问题是,如果我有 100 行,当我选中 header 复选框时,只有一些列复选框被选中,即只有显示的行。当我向下滚动时,未选中剩余的行复选框。这是我的代码:
List<Person> people = new ArrayList();
for (int i = 0; i < 1000; i++) {
people.add(i, new Person("Galileo Galilei", 1564));
}
CheckBox CheckBox1 = new CheckBox("All");
CheckBox1.setValue(false);
Grid<Person> grid = new Grid<>();
grid.setItems( people);
grid.addColumn(Person::getName).setCaption("Name");
grid.addColumn(Person::getYear).setCaption("Year of birth").setId("1");
grid.addComponentColumn(Person -> {
CheckBox chk=new CheckBox("Chk 2");
CheckBox1.addValueChangeListener(e->
chk.setValue(CheckBox1.getValue())
);
return chk;
}).setCaption("ch2").setId("CH2");
grid.getHeaderRow(0).getCell("CH2").setComponent( CheckBox1);
嗯,出于性能原因,并非所有复选框都从一开始就呈现,正如您在下面的 GIF 中看到的那样(右侧,项目以紫色闪烁),只有当前可见的那些。当您滚动时,新项目将替换旧项目,并为它们绘制复选框。然而,它们的初始状态不会被选中,因此最简单的解决方案是将其初始状态设置为 master 复选框 之一:CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());
.
结果:
此外,查看代码您可能有轻微泄漏。由于每次滚动较大的部分时都会绘制复选框,因此每次都会调用 grid.addComponentColumn
中的代码,并且值更改侦听器将不断地添加到列表中......因为它们永远不会未注册。看看下面的图片,经过一些滚动,我最终得到了 9000 多个:
为了解决这个问题,您可以在取消选中复选框时取消注册侦听器:
grid.addComponentColumn(Person -> {
CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());
// save the registration info to unregister at a later time
Registration listenerRegistration = CheckBox1.addValueChangeListener(e -> chk.setValue(CheckBox1.getValue()));
// when the checkbox is detached, remove the listener
chk.addDetachListener(event -> listenerRegistration.remove());
return chk;
}).setCaption("ch2").setId("CH2");
现在列表只包含那些尚未分离的人:
您还可以通过布尔字段 "selected" 扩展数据模型或将其包装到新的 class 中并添加 "selected" 字段。然后 set/unset 将 ValueChangeListener 中的那个字段添加到 CheckBox。
这还将负责选择所有网格条目,而不仅仅是呈现的条目。您只需更改所有数据模型实例中的 "selected"。
另一种方法是使用 ImageRenderer。那么你就不必与任何听众打交道了。
这假设您的模型有一个属性来保存 checked/selected 的值。
ThemeResource resourceChecked = new ThemeResource("selected.gif");
ThemeResource resourceUnchecked = new ThemeResource("deselected.gif");
grid.addColumn(person -> person.getSelected() ? resourceChecked : resourceUnchecked,
new ImageRenderer<>(event -> {
Person person = event.getItem();
person.setSelected(!person.getSelected());
grid.getDataProvider().refreshItem(person);
grid.markAsDirty();
}));
我正在使用 vaadin 8.1.0 网格。我需要将复选框作为列和列 header 插入。当我单击 header 列中的复选框时,应选中所有列的复选框。那工作正常。但问题是,如果我有 100 行,当我选中 header 复选框时,只有一些列复选框被选中,即只有显示的行。当我向下滚动时,未选中剩余的行复选框。这是我的代码:
List<Person> people = new ArrayList();
for (int i = 0; i < 1000; i++) {
people.add(i, new Person("Galileo Galilei", 1564));
}
CheckBox CheckBox1 = new CheckBox("All");
CheckBox1.setValue(false);
Grid<Person> grid = new Grid<>();
grid.setItems( people);
grid.addColumn(Person::getName).setCaption("Name");
grid.addColumn(Person::getYear).setCaption("Year of birth").setId("1");
grid.addComponentColumn(Person -> {
CheckBox chk=new CheckBox("Chk 2");
CheckBox1.addValueChangeListener(e->
chk.setValue(CheckBox1.getValue())
);
return chk;
}).setCaption("ch2").setId("CH2");
grid.getHeaderRow(0).getCell("CH2").setComponent( CheckBox1);
嗯,出于性能原因,并非所有复选框都从一开始就呈现,正如您在下面的 GIF 中看到的那样(右侧,项目以紫色闪烁),只有当前可见的那些。当您滚动时,新项目将替换旧项目,并为它们绘制复选框。然而,它们的初始状态不会被选中,因此最简单的解决方案是将其初始状态设置为 master 复选框 之一:CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());
.
结果:
此外,查看代码您可能有轻微泄漏。由于每次滚动较大的部分时都会绘制复选框,因此每次都会调用 grid.addComponentColumn
中的代码,并且值更改侦听器将不断地添加到列表中......因为它们永远不会未注册。看看下面的图片,经过一些滚动,我最终得到了 9000 多个:
为了解决这个问题,您可以在取消选中复选框时取消注册侦听器:
grid.addComponentColumn(Person -> {
CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());
// save the registration info to unregister at a later time
Registration listenerRegistration = CheckBox1.addValueChangeListener(e -> chk.setValue(CheckBox1.getValue()));
// when the checkbox is detached, remove the listener
chk.addDetachListener(event -> listenerRegistration.remove());
return chk;
}).setCaption("ch2").setId("CH2");
现在列表只包含那些尚未分离的人:
您还可以通过布尔字段 "selected" 扩展数据模型或将其包装到新的 class 中并添加 "selected" 字段。然后 set/unset 将 ValueChangeListener 中的那个字段添加到 CheckBox。
这还将负责选择所有网格条目,而不仅仅是呈现的条目。您只需更改所有数据模型实例中的 "selected"。
另一种方法是使用 ImageRenderer。那么你就不必与任何听众打交道了。
这假设您的模型有一个属性来保存 checked/selected 的值。
ThemeResource resourceChecked = new ThemeResource("selected.gif");
ThemeResource resourceUnchecked = new ThemeResource("deselected.gif");
grid.addColumn(person -> person.getSelected() ? resourceChecked : resourceUnchecked,
new ImageRenderer<>(event -> {
Person person = event.getItem();
person.setSelected(!person.getSelected());
grid.getDataProvider().refreshItem(person);
grid.markAsDirty();
}));