Accessing a JTextField in JTableHeader
Asked Answered
A

2

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

Ambulate answered 26/9, 2012 at 9:5 Comment(5)
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...Blunger
Thx MadProrammer! Ill will take a futher look at JTableHeaders. I was started with it, but i was not sure if i needed that.Ambulate
This some little tricks you can do, like "borrowing" the header from the table and using it as part of your implementation.Blunger
@Ambulate don't to create an CellEditor for JTableHeader, replace that with easiest way to create a proper arrays of JTextFieldCrystallize
if you mean something like JYTable - 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)Vere
D
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();
  }
}
Dromond answered 26/10, 2012 at 14:51 Comment(0)
M
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.
Masaccio answered 26/9, 2012 at 20:39 Comment(7)
+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 :-)Vere
@kleopatra: You are never stupid! I appreciate your comments; more above.Masaccio
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?Ambulate
@Vere Your JYTable with the header is just what i looking for!Ambulate
@Vere Just sended you a mail, via your website. Hope can you answer it fast :)Ambulate
@Ambulate - thanks, but it's not mine, just did the work :-) Best to contact the address on their webpageVere
@Ambulate btw, didn't get anything, try fastegal at swingempire dot deVere

© 2022 - 2024 — McMap. All rights reserved.