Editable JTableHeader [duplicate]
Asked Answered
C

2

6

Possible Duplicate:
Accessing a JTextField in JTableHeader

How to make JTableHeader as editable. F.e. i make ColumnHeader as JTextField. What must i do to make JTextField editable. See the example:

import java.awt.*;
import javax.swing.*;

import javax.swing.table.*;

import java.awt.event.*;

public class Test extends JFrame {

String[][] cellValues = { { "v00", "v01", "v02" }, { "v10", "v11", "v12" },
        { "v20", "v21", "v22" }, { "v30", "v31", "v32" },
        { "v40", "v41", "v42" }, { "v50", "v51", "v52" } };
String[] columnNames = { "v00", "v01", "v02" };

javax.swing.JTable jTable1 = new javax.swing.JTable(cellValues, columnNames);

public Test() {
    try {
        jbInit();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void jbInit() throws Exception {
    this.getContentPane().add(new JScrollPane(jTable1), null);
    for (int i = 0; i < 3; i++)
        jTable1.getColumnModel().getColumn(i)
                .setHeaderRenderer(new Renderer());
}

public static void main(String[] args) {
    Test frame = new Test();
    frame.addWindowListener(new java.awt.event.WindowAdapter() {
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
    });
    frame.pack();
    frame.setVisible(true);
}

}

class Renderer extends JPanel implements TableCellRenderer {

JLabel label = new JLabel(" ");
JTextField field = new JTextField("%");

public Renderer() {
    super(new BorderLayout());
    add(label, BorderLayout.NORTH);
    add(field, BorderLayout.CENTER);
    setBorder(BorderFactory.createEtchedBorder());
}

public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column) {
    label.setText(value.toString());
    return (JComponent) this;
}

public String toString() {
    return label.toString();
}

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

}
Chainsmoke answered 26/10, 2012 at 1:55 Comment(2)
Also see Accessing a JTextField in JTableHeaderSaleratus
As well as these helpful caveats.Mustachio
F
9

Here's a simple approach for making editable headers (no custom renderers or UIs required):

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();
  }
}
Fishy answered 26/10, 2012 at 14:58 Comment(2)
It only works with JTextFields. If I try to do the same thing with combobox, then the drop-down list doesn't get properly rendered.Robledo
@Benas, That's because you're trying to put a JComboBox on a JPopupMenu, which is a separate problem altogether. I'd suggest searching the forums for that answer, or starting a separate question.Fishy
D
2

There is a complete solution under the following link, looks quite good at the first sight!
How do I create a JTable with editable headers?

Djokjakarta answered 26/10, 2012 at 2:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.