JTable und der RowHeader

RLott

Grünschnabel
Hallo zusammen,

ich habe ein Problem mit einer fixen Column (RowHeader) im Table, welche die Zeilennummer anzeigt. Derzeit filtere ich über das Model mit dem RowFilter - wird die Suche ausgelöst, werden die Zeilennummern im ListModel nicht ausgeblendet (siehe nachfolgende Source).

Bsp.: Ich suche nach SUN - so müsste sich nur noch die Zeilennummer 1 stehen bleiben, es sind aber 8 sichtbar... Weiß jemand, wie man das mit dem RowSorter unter einen Hut bekommt ?

Danke schon mal vorab für die Bemühungen,
Gruß
Reiner

Klasse: FilterTable

Code:
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
import java.util.regex.*;

public class FilterTable {

	public static void main(String args[])
	{
		Runnable runner = new Runnable()
		{

			public void run()
			{
				JFrame frame = new JFrame("Sorting JTable");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				Object rows[][] = {{"AMZN", "Amazon", 41.28}, {"EBAY", "eBay", 41.57}, {"GOOG", "Google", 388.33}, {"MSFT", "Microsoft", 26.56},
						{"NOK", "Nokia Corp", 17.13}, {"ORCL", "Oracle Corp.", 12.52}, {"SUNW", "Sun Microsystems", 3.86},
						{"TWX", "Time Warner", 17.66}, {"VOD", "Vodafone Group", 26.02}, {"YHOO", "Yahoo!", 37.69}};
				Object columns[] = {"Symbol", "Name", "Price"};
				TableModel model = new DefaultTableModel(rows, columns)
				{

					public Class getColumnClass(int column)
					{
						Class returnValue;
						if ((column >= 0) && (column < getColumnCount()))
						{
							returnValue = getValueAt(0, column).getClass();
						} else
						{
							returnValue = Object.class;
						}
						return returnValue;
					}
				};
				
				JTable table = new JTable(model);
				final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
				table.setRowSorter(sorter);
				JScrollPane pane = new JScrollPane(table);
				frame.add(pane, BorderLayout.CENTER);
				
				// Zeilennummerierung
				DefaultListModel modelRowHeader = new DefaultListModel();
				JList lstRowHeader = new JList(modelRowHeader);
				pane.setRowHeaderView(lstRowHeader);
				lstRowHeader.setFixedCellWidth(40);
				lstRowHeader.setVisible(true);
				int cntRow = 0;
				for (int i = 0; i < rows.length; i++)
				{
					modelRowHeader.addElement(cntRow++);
				}
				
				JPanel panel = new JPanel(new BorderLayout());
				JLabel label = new JLabel("Filter");
				panel.add(label, BorderLayout.WEST);
				final JTextField filterText = new JTextField("");
				panel.add(filterText, BorderLayout.CENTER);
				frame.add(panel, BorderLayout.NORTH);
				JButton button = new JButton("Filter");
				button.addActionListener(new ActionListener()
				{

					public void actionPerformed(ActionEvent e)
					{
						String text = filterText.getText();
						if (text.length() == 0)
						{
							sorter.setRowFilter(null);
						} else
						{
							try
							{
								sorter.setRowFilter(RowFilter.regexFilter(text));
							} catch (PatternSyntaxException pse)
							{
								System.err.println("Bad regex pattern");
							}
						}
					}
				});
				frame.add(button, BorderLayout.SOUTH);
				frame.setSize(300, 250);
				frame.setVisible(true);
			}
		};
		EventQueue.invokeLater(runner);
	}
}
 

RLott

Grünschnabel
Hallo Thomas,

bei dem NumberTable ist genau das gleiche Problem - sofern man den TableRowSorter einsetzt - die Zeilennummerierung wird nicht auf das gefilterte reduziert... Wie bekommt man das in den Griff ?

Gruß
Reiner
 

Thomas Darimont

Erfahrenes Mitglied
Hallo,

wie wärs denn damit?

Minimal Version:
Java:
package de.tutorials.training;

import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class FilterableJTableExample extends JFrame {

  JTable table;
  JTextField txtFilter;


  public FilterableJTableExample() {
    super("FilterableJTableExample with Custom RowHeader");
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    Object[][] rowData = new Object[][] { { "a1", "b1", "c1" }, { "a2", "b2", "c2" }, { "a3", "b3", "c3" } };
    Object[] columnNames = new Object[] { "", "a", "b", "c" };
    DefaultTableModel model = new DefaultTableModel(rowData, columnNames) {
      @Override
      public Object getValueAt(int row, int column) {
        if (column == 0) {
          return row;
        } else {
          return super.getValueAt(row, column - 1);
        }
      }


      @Override
      public void setValueAt(Object aValue, int row, int column) {
        if (column > 0) {
          super.setValueAt(aValue, row, column - 1);
        }
      }
    };

    table = new JTable(model) {
      public boolean isCellEditable(int row, int column) {
        if (column == 0) {
          return false;
        } else {
          return super.isCellEditable(row, column);
        }
      }
    };

    TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model) {
      @Override
      public boolean isSortable(int column) {
        return column != 0;
      }
    };
    table.setRowSorter(sorter);

    txtFilter = createFilterField(sorter);

    add(txtFilter, BorderLayout.NORTH);
    add(new JScrollPane(table), BorderLayout.CENTER);

    pack();
    setVisible(true);
  }


  protected JTextField createFilterField(final TableRowSorter<TableModel> sorter) {
    final JTextField txtFilter = new JTextField(20);

    txtFilter.addKeyListener(new KeyAdapter() {
      @Override
      public void keyReleased(KeyEvent e) {
        if (txtFilter.getText().trim().length() > 0) {
          sorter.setRowFilter(RowFilter.regexFilter(txtFilter.getText(), 1 /*
                                                                            * column index(ices) to
                                                                            * filter
                                                                            */));
        } else {
          sorter.setRowFilter(null);
        }
      }
    });
    return txtFilter;
  }


  public static void main(String[] args) {
    new FilterableJTableExample();
  }
}

Eigener CellRenderer
Java:
package de.tutorials.training;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class FilterableJTableExample extends JFrame {

  JTable table;
  JTextField txtFilter;


  public FilterableJTableExample() {
    super("FilterableJTableExample with Custom RowHeader");
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    Object[][] rowData = new Object[][] { { "a1", "b1", "c1" }, { "a2", "b2", "c2" }, { "a3", "b3", "c3" } };
    Object[] columnNames = new Object[] { "#", "a", "b", "c" };
    DefaultTableModel model = new DefaultTableModel(rowData, columnNames) {
      @Override
      public Object getValueAt(int row, int column) {
        if (column == 0) {
          return row;
        } else {
          return super.getValueAt(row, column - 1);
        }
      }
    };

    final TableCellRenderer rowHeaderRenderer = createRowHeaderRenderer();

    table = new JTable(model) {
      public boolean isCellEditable(int row, int column) {
        if (column == 0) {
          return false;
        } else {
          return super.isCellEditable(row, column);
        }
      };


      public TableCellRenderer getCellRenderer(int row, int column) {
        if (column == 0) {
          return rowHeaderRenderer;
        } else {
          return super.getCellRenderer(row, column);
        }
      }
    };

    final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
    table.setRowSorter(sorter);

    txtFilter = createFilterField(sorter);
    
    add(txtFilter, BorderLayout.NORTH);
    add(new JScrollPane(table), BorderLayout.CENTER);

    pack();
    setVisible(true);
  }




  protected JTextField createFilterField(final TableRowSorter<TableModel> sorter) {
    final JTextField txtFilter = new JTextField(20);
    
    txtFilter.addKeyListener(new KeyAdapter() {
      @Override
      public void keyReleased(KeyEvent e) {
        if (txtFilter.getText().trim().length() > 0) {
          sorter.setRowFilter(RowFilter.regexFilter(txtFilter.getText(), 1 /*
                                                                            * which column index(ices) to filter
                                                                            */));
        } else {
          sorter.setRowFilter(null);
        }
      }
    });
    return txtFilter;
  }
  
  


  private TableCellRenderer createRowHeaderRenderer() {
    return new TableCellRenderer() {

      JLabel rowHeaderLabel = new JLabel();
      
      @Override
      public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
        boolean hasFocus, int row, int column) {
        rowHeaderLabel.setText(String.valueOf(value));
        return rowHeaderLabel;
      }
    };
  }


  public static void main(String[] args) {
    new FilterableJTableExample();
  }
}

Gruß Tom
 

RLott

Grünschnabel
Hi Thomas,

ok, Du hast die Infos mit ins Model geworfen , was sich Table und RowHeader teilen...

Genau das wollte ich nicht... Ziel ist es einfach nur,
extrem markante Infos immer zu sehen, quasi wie in Excel, dort kannst Du ja auch Spalten fixieren und den Content nocht links oder rechts scrollen...

Gruß
Reiner
 

Thomas Darimont

Erfahrenes Mitglied
Hallo,

dann versuchs mal damit:
Java:
package de.tutorials.training;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class FilterableJTableExample extends JFrame {

  JTable table;
  JTextField txtFilter;


  public FilterableJTableExample() {
    super("FilterableJTableExample with Custom RowHeader");
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    Object[][] rowData = new Object[][] { { "a1", "b1", "c1" }, { "a2", "b2", "c2" }, { "a3", "b3", "c3" } };
    Object[] columnNames = new Object[] {"a", "b", "c" };
    final DefaultTableModel model = new DefaultTableModel(rowData, columnNames);

    table = new JTable(model);
  
    TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model) {
      @Override
      public boolean isSortable(int column) {
        return column != 0;
      }
    };
    table.setRowSorter(sorter);
    
    DefaultTableModel headerModel = new DefaultTableModel(){
      public String getColumnName(int column) {  return "";    }
      public int getColumnCount() { return 1;  }
      public int getRowCount() { return table.getRowCount();  }
      public Object getValueAt(int row, int column) { return row;  }
      public TableModelListener[] getTableModelListeners() { return model.getTableModelListeners();}
    };
    
    JTable rowHeaders = new  JTable(headerModel){
      public boolean isCellEditable(int row, int column) {
        return false;
      }
    };
    
    rowHeaders.setRowSorter(sorter);
    rowHeaders.setSelectionModel(table.getSelectionModel());
    txtFilter = createFilterField(sorter);

    add(txtFilter, BorderLayout.NORTH);
    JScrollPane scrollPane = new JScrollPane(table);
    scrollPane.setRowHeaderView(rowHeaders);
    scrollPane.getRowHeader().setPreferredSize(new Dimension(35,0));
    add(scrollPane, BorderLayout.CENTER);
    

    pack();
    setVisible(true);
  }


  protected JTextField createFilterField(final TableRowSorter<TableModel> sorter) {
    final JTextField txtFilter = new JTextField(20);

    txtFilter.addKeyListener(new KeyAdapter() {
      @Override
      public void keyReleased(KeyEvent e) {
        if (txtFilter.getText().trim().length() > 0) {
          sorter.setRowFilter(RowFilter.regexFilter(txtFilter.getText(), 0 /*
                                                                            * column index(ices) to
                                                                            * filter
                                                                            */));
        } else {
          sorter.setRowFilter(null);
        }
      }
    });
    return txtFilter;
  }


  public static void main(String[] args) {
    new FilterableJTableExample();
  }
}

Gruß Tom
 

condor99

Grünschnabel
Hallo,

so etwas in der Art suche ich . Allerdings möchte ich über jedem Header ein Suchfeld haben. Ich dacht ich mach das über den Renderer aber leider kann man das Textfeld dann nicht benutzen (scheint so als ob es nicht editierbar ist). Bin ich da auf dem Holzweg? Wie geht es sonst?

table.png

Danke