首页 > 解决方案 > 在 JList 中过滤和突出显示时出现问题

问题描述

我一直在寻找如何用 a 过滤JTextFieldJList突出显示相同的表达式写在文本字段和列表的每个元素中,我一直在网上冲浪,我在此页面中找到了一个示例。

https://www.logicbig.com/tutorials/java-swing/list-filter-highlighting.html

即使我尝试制作相同的代码,但我的版本过滤正常,但它没有突出任何内容,我在这里发布我的代码,它或多或少与页面相同,但改变了我的类。

标签突出显示

package ui.admin.citas.filtering;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

public class LabelHighlighted extends JLabel {
    /**
    * 
    */
    private static final long serialVersionUID = 1L;

    private List<Rectangle2D> rectangles = new ArrayList<>();
    private Color colorHighlight = Color.YELLOW;

    public void reset() {
        rectangles.clear();
        repaint();
    }

    public void highlightText(String textToHighlight) {
        if (textToHighlight == null) {
            return;
        }
        reset();

        final String textToMatch = textToHighlight.toLowerCase().trim();
        if (textToMatch.length() == 0) {
            return;
        }
        textToHighlight = textToHighlight.trim();

        final String labelText = getText().toLowerCase();
        if (labelText.contains(textToMatch)) {
            FontMetrics fm = getFontMetrics(getFont());
            float w = -1;
            final float h = fm.getHeight() - 1;
            int i = 0;
            while (true) {
                i = labelText.indexOf(textToMatch, i);
                if (i == -1) {
                    break;
                }
                if (w == -1) {
                    String matchingText = getText().substring(i, i + textToHighlight.length());
                    w = fm.stringWidth(matchingText);
                }
                String preText = getText().substring(0, i);
                float x = fm.stringWidth(preText);
                rectangles.add(new Rectangle2D.Float(x, 1, w, h));
                i = i + textToMatch.length();
            }
            repaint();
        }
        
    }

    @Override
    protected void paintComponent(Graphics g) {
        if (isOpaque()) {
            g.setColor(getBackground());
            g.fillRect(0, 0, getWidth(), getHeight());
        }
        if (rectangles.size() > 0) {
            Graphics2D g2d = (Graphics2D) g;
            Color c = g2d.getColor();
            for (Rectangle2D rectangle : rectangles) {
                g2d.setColor(colorHighlight);
                g2d.fill(rectangle);
                g2d.setColor(Color.LIGHT_GRAY);
                g2d.draw(rectangle);
            }
            g2d.setColor(c);
        }
        super.paintComponent(g);
    }
}

这里是装饰器

package ui.admin.citas.filtering;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiPredicate;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class JListFilterDecorator {

     private JTextField filterField;

      public static <T> JListFilterDecorator decorate(JList<T> list, BiPredicate<T, String> userFilter) {
          if (!(list.getModel() instanceof DefaultListModel)) {
              throw new IllegalArgumentException("List model must be an instance of DefaultListModel");
          }
          
          
          DefaultListModel<T> model = (DefaultListModel<T>) list.getModel();
          List<T> items = getItems(model);
          JTextField textField = new JTextField();
          textField.getDocument().addDocumentListener(new DocumentListener() {
              @Override
              public void insertUpdate(DocumentEvent e) {
                  filter();
              }

              @Override
              public void removeUpdate(DocumentEvent e) {
                  filter();
              }

              @Override
              public void changedUpdate(DocumentEvent e) {
                  filter();
              }

              private void filter() {
                  model.clear();
                  String s = textField.getText();
                  
                  for (T item : items) {
                      if(userFilter.test(item, s)){
                          model.addElement(item);
                          
                      }
                  }
                  
              }
          });
          
          JListFilterDecorator decorator = new JListFilterDecorator();
          decorator.filterField = textField;
          return decorator;
      }

      private static <T> List<T> getItems(DefaultListModel<T> model) {
          List<T> list = new ArrayList<>();
          for (int i = 0; i < model.size(); i++) {
              list.add(model.elementAt(i));
          }
          return list;
      }

      public JTextField getFilterField() {
          return filterField;
      }

}

这里我在窗口的构造函数中创建文本字段


        JListFilterDecorator decoratorPacientes = JListFilterDecorator.decorate(listPacientes, VentanaCitasBase::filterPaciente);
        
        JTextField toAddPac = decoratorPacientes.getFilterField();
        toAddPac.setText("Busque aquí...");
        toAddPac.setForeground(Color.LIGHT_GRAY);
        toAddPac.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                toAddPac.setText("");
                toAddPac.setForeground(Color.BLACK);
            }
            @Override
            public void focusLost(FocusEvent e) {
                toAddPac.setText("Busque aquí...");
                toAddPac.setForeground(Color.LIGHT_GRAY);
            }
        });
        getPanelSearch().add(toAddPac);
        listPacientes.setCellRenderer(createListPacientesRenderer(toAddPac));
        

最后也是在窗口中创建渲染器的方法

private ListCellRenderer<? super PacienteDTO> createListPacientesRenderer(JTextField filterField) {
        return new DefaultListCellRenderer() {
            /**
            * 
            */
            private static final long serialVersionUID = 1L;
        
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {
                Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

                if (c instanceof JLabel) {
                    PacienteDTO emp = (PacienteDTO) value;
                    JLabel original = (JLabel) c;
                    LabelHighlighted label = new LabelHighlighted();
                    label.setText(emp.toString());
                    label.setBackground(original.getBackground());
                    label.setForeground(original.getForeground());
                    label.setOpaque(original.isOpaque());
                    label.setHorizontalTextPosition(original.getHorizontalTextPosition());
                    label.highlightText(filterField.getText());
                    return label;
                }
                return c;
            }
        };
    }

标签: javaswingjlist

解决方案


推荐阅读