This example is an enhancement of the last example. We will show how to highlight matching text in the filtered rows of a JTable. This filter will be applied via RowFilter (as we saw in the last example). We will extend the JLabel which will override its paintComponent() method to fill 2d rectangles at the matched text locations. We will also create a custom TableCellRenderer which will use our extended JLabel.
Extending JLabel
public class LabelHighlighted extends JLabel {
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) {
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);
}
}
The TableCellRenderer
public class RendererHighlighted extends DefaultTableCellRenderer {
private JTextField searchField;
public RendererHighlighted(JTextField searchField) {
this.searchField = searchField;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean selected, boolean hasFocus,
int row, int column) {
Component c = super.getTableCellRendererComponent(table, value,
selected, hasFocus, row, column);
JLabel original = (JLabel) c;
LabelHighlighted label = new LabelHighlighted();
label.setFont(original.getFont());
label.setText(original.getText());
label.setBackground(original.getBackground());
label.setForeground(original.getForeground());
label.setHorizontalTextPosition(original.getHorizontalTextPosition());
label.highlightText(searchField.getText());
return label;
}
}
Creating the RowFilter
Same as the last example:
public class RowFilterUtil {
public static JTextField createRowFilter(JTable table) {
RowSorter<? extends TableModel> rs = table.getRowSorter();
if (rs == null) {
table.setAutoCreateRowSorter(true);
rs = table.getRowSorter();
}
TableRowSorter<? extends TableModel> rowSorter =
(rs instanceof TableRowSorter) ? (TableRowSorter<? extends TableModel>) rs : null;
if (rowSorter == null) {
throw new RuntimeException("Cannot find appropriate rowSorter: " + rs);
}
final JTextField tf = new JTextField(15);
tf.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
update(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
update(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
update(e);
}
private void update(DocumentEvent e) {
String text = tf.getText();
if (text.trim().length() == 0) {
rowSorter.setRowFilter(null);
} else {
rowSorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
}
}
});
return tf;
}
}
The main class
public class ExampleMain {
public static void main(String[] args) {
JFrame frame = createFrame();
TableModel tableModel = createTableModel();
JTable table = new JTable(tableModel);
JTextField filterField = RowFilterUtil.createRowFilter(table);
RendererHighlighted renderer = new RendererHighlighted(filterField);
table.setDefaultRenderer(Object.class, renderer);
JPanel jp = new JPanel();
jp.add(filterField);
frame.add(jp, BorderLayout.NORTH);
JScrollPane pane = new JScrollPane(table);
pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
frame.add(pane, BorderLayout.CENTER);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static TableModel createTableModel() {
Vector<String> columns = new Vector<>(Arrays.asList("Name", "Address", "Age"));
Vector<Vector<Object>> rows = new Vector<>();
DataFactory dataFactory = new DataFactory();
for (int i = 1; i <= 30; i++) {
Vector<Object> v = new Vector<>();
v.add(dataFactory.getName());
v.add(dataFactory.getAddress() + ", " + dataFactory.getCity());
v.add(dataFactory.getNumberBetween(18, 80));
rows.add(v);
}
DefaultTableModel dtm = new DefaultTableModel(rows, columns);
return dtm;
}
public static JFrame createFrame() {
JFrame frame = new JFrame("JTable Row filter example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(600, 450));
return frame;
}
}
Output
Example ProjectDependencies and Technologies Used: - datafactory 0.8: Library to generate data for testing.
- JDK 1.8
- Maven 3.3.9
|
|