2

I have made a TableHeader renderer that will create a JTextfield under the Label of the header in a JTable. The problem i got now, i never get focus/access to this JTextfield in the header.

I found out that a TableHeader renderer only draws the component and dont do the rest, like focus and stuff.

I have tryed to make a array of JTextfield that will set on the header, so i can access them on code base. Unlucky that didnt workout, i was wondering if its possible to get access to this JTextField in the header and what is the best way to do this.

Tableheader renderer:

public class TextFieldTableHeaderRenderer extends AbstractCellEditor implements TableCellRenderer {

private MyPanel component;

public TextFieldTableHeaderRenderer(){
}

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    component = new MyPanel(column);
    ((MyPanel)component).setLabelText(value.toString());
    return component;
}

@Override
public Object getCellEditorValue() {
    return ((MyPanel)component).getTextField(); 
}

MyPanel:

public class MyPanel extends JPanel {  

private javax.swing.JLabel label;
private javax.swing.JTextField textField;

public MyPanel(int column) {   
    super();   
    setLayout(new java.awt.BorderLayout());   
    label = new javax.swing.JLabel();   
    textField = new javax.swing.JTextField();  


    setBorder(javax.swing.BorderFactory.createEtchedBorder());

    label.setHorizontalAlignment(SwingConstants.CENTER);

    //textField.setText("Column "+column);

    add(textField, java.awt.BorderLayout.PAGE_END);

    add(label, java.awt.BorderLayout.CENTER);   
}   

public void setLabelText( String text ){
    label.setText(text);
}

public void setTextFieldText(String text){
    getTextField().setText(text);
}

public javax.swing.JTextField getTextField() {   
    return textField;   
}

/**
 * @param textField the textField to set
 */
public void setTextField(javax.swing.JTextField textField) {
    this.textField = textField;
}

Install on header:

for( int i=0; i < this.getxColumnModel().getColumnCount(); i++){
            this.getxColumnModel().getColumn(i, true).setHeaderRenderer( new TextFieldTableHeaderRenderer() );
        }

I have try to use the "EditableHeader" example from the i-net, but it makes a new JTextfield when clicking on the header.

I like to see that the user get focus on the JTextfield, enters a text and then it will filter the column.

Filtering wont be a problem, cause i have made that already.

Hopefully im clear to you guys/girls and love to hear you solution

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
d0n
  • 21
  • 1
  • 2
  • 1
    If you want to make this work, you're going to have commit more work to it. You can't use the renderer in this fashion (it's what they call "stamped" on). You're going have to provide your `JTableHeader` that is capable of adding the features you need... – MadProgrammer Sep 26 '12 at 09:23
  • Thx MadProrammer! Ill will take a futher look at JTableHeaders. I was started with it, but i was not sure if i needed that. – d0n Sep 26 '12 at 10:22
  • This some little tricks you can do, like "borrowing" the header from the table and using it as part of your implementation. – MadProgrammer Sep 26 '12 at 10:30
  • @d0n don't to create an CellEditor for JTableHeader, replace that with easiest way to create a proper arrays of JTextField – mKorbel Sep 27 '12 at 06:39
  • if you mean [something like JYTable](http://www.javasoft.de/syntheticaaddons/screenshots/table/) - it's a lot of hard not entirely trivial work (I should know as I wrote it :-). So you might consider going commercial (the referenced or alternatives, f.i. JIDE) – kleopatra Sep 27 '12 at 09:32

2 Answers2

4

Here's a simple approach for making editable headers:

EDIT: oops - I meant to post this in another thread. I guess I'll keep it here anyway.

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;

public class JTableEditableHeaderDemo implements Runnable
{
  private JTable table;
  private JTableHeader header;
  private JPopupMenu renamePopup;
  private JTextField text;
  private TableColumn column;

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new JTableEditableHeaderDemo());
  }

  public JTableEditableHeaderDemo()
  {
    table = new JTable(10, 5);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    table.setPreferredScrollableViewportSize(table.getPreferredSize());

    header = table.getTableHeader();
    header.addMouseListener(new MouseAdapter(){
      @Override
      public void mouseClicked(MouseEvent event)
      {
        if (event.getClickCount() == 2)
        {
          editColumnAt(event.getPoint());
        }
      }
    });

    text = new JTextField();
    text.setBorder(null);
    text.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e)
      {
        renameColumn();
      }
    });

    renamePopup = new JPopupMenu();
    renamePopup.setBorder(new MatteBorder(0, 1, 1, 1, Color.DARK_GRAY));
    renamePopup.add(text);
  }

  public void run()
  {
    JFrame f = new JFrame("Double-click header to edit");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(new JScrollPane(table));
    f.pack();
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }

  private void editColumnAt(Point p)
  {
    int columnIndex = header.columnAtPoint(p);

    if (columnIndex != -1)
    {
      column = header.getColumnModel().getColumn(columnIndex);
      Rectangle columnRectangle = header.getHeaderRect(columnIndex);

      text.setText(column.getHeaderValue().toString());
      renamePopup.setPreferredSize(
          new Dimension(columnRectangle.width, columnRectangle.height - 1));
      renamePopup.show(header, columnRectangle.x, 0);

      text.requestFocusInWindow();
      text.selectAll();
    }
  }

  private void renameColumn()
  {
    column.setHeaderValue(text.getText());
    renamePopup.setVisible(false);
    header.repaint();
  }
}
splungebob
  • 5,357
  • 2
  • 22
  • 45
3

TableColumn supports setting a TableCellRenderer via setHeaderRenderer(), as shown in this example; it has no provision for setHeaderEditor(), which would be required for editing. Alternatives might include these:

  • Write a custom JTableHeader.
  • Add a row of text fields in an adjacent, conformal layout.
  • Use a particular row in the TableModel, as suggested in FixedRowExample.
  • Consider a commercial alternative; several are listed here.
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 1
    +1 good summary of the options. Another route - as JIDE - might be to add editor functionality to the header. None of them trivial (or me being stupid :-) – kleopatra Sep 27 '12 at 09:37
  • @kleopatra: You are _never_ stupid! I appreciate your comments; more above. – trashgod Sep 27 '12 at 15:25
  • Yeah, i like to add a editor to the header, cause it doesnt exists. But dont know were to begin :). Any tips were to look? – d0n Sep 28 '12 at 07:15
  • @kleopatra Your JYTable with the header is just what i looking for! – d0n Sep 28 '12 at 07:26
  • @kleopatra Just sended you a mail, via your website. Hope can you answer it fast :) – d0n Sep 28 '12 at 08:14
  • @d0n - thanks, but it's not mine, just did the work :-) Best to contact the address on their webpage – kleopatra Sep 28 '12 at 09:41
  • @d0n btw, didn't get anything, try fastegal at swingempire dot de – kleopatra Sep 28 '12 at 09:52