我有一个List
,其中包含某种类型的JPA Entity
个对象。他们的reference
字符串值显示在JList
中供用户查看。
我希望我的用户能够在UI中选择过滤器作为JCheckBoxes,例如“仅来自客户端 x ”或“仅限于 x ”且动态过滤实体列表。
我原本想要保留static List completeList;
和static List filteredList;
的副本,然后每次在UI中选择新的过滤器时运行单独的过滤器方法来更新filteredList
工作正常,直到您必须取消选择单个过滤器并保留其他过滤器(此时它们全部崩溃)。
我认为每种情况都会在某个时刻崩溃,通常是在尝试从一个菜单中选择多个过滤器时。
我的思维模式示例,它检查所有过滤器以确定新JList中需要的内容;
public static void filterList(){
List filteredList = new ArrayList<Job>(StoredDataClass.completeList);
if(clientSmithsCheckBox.isSelected()){
for(Job job : filteredList){
if(!job.getClient.equals(clientSmithsCheckBox.getText())){
filteredList.remove(job);
}
}
}
....... // Check other filters here etc.
if(clientBobAndCoCheckBox.isSelected()){
for(Job job : filteredList){
if(!job.getClient.equals(clientBobAndCoCheckBox.getText())){
filteredList.remove(job);
}
}
}
即使选择了clientBobAndCoCheckBox,也不会在最终列表中显示具有该客户端的作业,因为我们已将其全部删除,因为已经选择了另一个客户端。现在,我们可以添加到列表中,但是我们会遇到类似的问题,即添加不应该存在的东西等。
这显然是可行的,因为这种类型的过滤系统是常见的做法(例如,excel)。虽然这更像是一个设计问题,但我该如何实现呢?
答案 0 :(得分:2)
这是一个关于如何组织逻辑的简短(和原始!)示例。它位于SwingX的上下文中(它支持JList的排序/过滤方式与JTable相同),因为我很懒 - 但您可以轻松地将它应用到您自己的环境中。
将您的标准视为可以打开或关闭的过滤器集合,然后将它们与OR组合(如果选择了一个或多个),如果没有选择则关闭。唯一的“技巧”是评估其中一个复选框的所有复选框的状态:
final JXList list = new JXList(new DefaultComboBoxModel(Locale.getAvailableLocales()));
list.setAutoCreateRowSorter(true);
final List<RowFilter> filters = new ArrayList<>();
filters.add(new MyRowFilter("de"));
filters.add(new MyRowFilter("ar"));
final List<JCheckBox> boxes = new ArrayList<>();
ActionListener l = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<RowFilter<Object, Object>> orCandidates = new ArrayList<>();
for (int i = 0; i < boxes.size(); i++) {
if (boxes.get(i).isSelected())
orCandidates.add(filters.get(i));
}
RowFilter<Object, Object> or = orCandidates.isEmpty() ? null :
RowFilter.orFilter(orCandidates);
list.setRowFilter(or);
}
};
JCheckBox first = new JCheckBox("de");
first.addActionListener(l);
boxes.add(first);
JCheckBox second = new JCheckBox("ar");
second.addActionListener(l);
boxes.add(second);
JComponent content = new JPanel();
content.add(new JScrollPane(list));
for (JCheckBox box : boxes) {
content.add(box);
}
showInFrame(content, "filters");
// just for completeness, the custom RowFilter
public static class MyRowFilter extends RowFilter {
private String text;
public MyRowFilter(String text) {
this.text = text;
}
@Override
public boolean include(Entry entry) {
Locale locale = (Locale) entry.getValue(0);
return locale.getLanguage().contains(text);
}
}