jksung
asked on
Java SWING JTable - is there a way to dynamically freeze a specific number of columns in the table so they cannot be moved?
By default, the columns of a JTable can be rearranged by dragging the column to new locations from the UI. However, I would like to freeze some of the beginning columns so that cannot be moved. To do so, I am using the two table method using the code below, basically one table has sorting disabled and will act as the frozen columns, and the second table with sorting enabled will be act as the normal columns, and I will declare the window to add to the display panel with a constructor such as:
frame.getContentPane().add (new FrozenTablePane(table, 2)); //2 is the number of columns to freeze.
This works, however I would like to dynamically change the number of frozen columns from the UI, for example, in the code below, in the test console created from
createTestFrame();
by entering the number of columns to freeze, then clicking on the "Set Frozen Columns" button, this would change the number of columns that are frozen in the table. Is it possible to do this? I have not been able to come up with a solution. The code for the two files FrozenTablePane.java and ExampleTableModel.java (the sample table data) are below:
<<<FrozenTablePane.java>>>
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent ;
import java.awt.event.ActionListe ner;
import java.util.HashSet;
import javax.swing.DefaultCellEdi tor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.WindowConstant s;
import javax.swing.table.Abstract TableModel ;
import javax.swing.table.DefaultT ableModel;
import javax.swing.table.JTableHe ader;
import javax.swing.table.TableCol umn;
import javax.swing.table.TableMod el;
public class FrozenTablePane extends JScrollPane {
public FrozenTablePane(JTable table, int colsToFreeze) {
super(table);
TableModel model = table.getModel();
// create a frozen model
TableModel frozenModel = new DefaultTableModel(model.ge tRowCount( ),
colsToFreeze);
// populate the frozen model
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < colsToFreeze; j++) {
String value = (String) model.getValueAt(i, j);
frozenModel.setValueAt(val ue, i, j);
}
}
// create frozen table
JTable frozenTable = new JTable(frozenModel);
// remove the frozen columns from the original table
for (int j = 0; j < colsToFreeze; j++) {
table.removeColumn(table.g etColumnMo del().getC olumn(0));
}
table.setAutoResizeMode(JT able.AUTO_ RESIZE_OFF );
// format the frozen table
JTableHeader header = table.getTableHeader();
frozenTable.setBackground( header.get Background ());
frozenTable.setAutoResizeM ode(JTable .AUTO_RESI ZE_OFF);
frozenTable.setEnabled(fal se);
// set frozen table as row header view
JViewport viewport = new JViewport();
viewport.setView(frozenTab le);
viewport.setPreferredSize( frozenTabl e.getPrefe rredSize() );
setRowHeaderView(viewport) ;
setCorner(JScrollPane.UPPE R_LEFT_COR NER, frozenTable.getTableHeader ());
}
/**
* The main() is used in application.
*
* @param args
* command line arguments
*/
public static void main(final String[] args) {
// Create parent frame for ReportApplianceUI
JFrame frame = new JFrame("FrozenTablePane");
//Create the JTable using the ExampleTableModel implementing
//the AbstractTableModel abstract class
JTable table = new JTable(new ExampleTableModel());
//Set the column sorting functionality on
table.setAutoCreateRowSort er(true);
//Uncomment the next line if you want to turn the grid lines off
// table.setShowGrid(false);
//Change the colour of the table - yellow for gridlines
//blue for background
table.setGridColor(Color.Y ELLOW);
table.setBackground(Color. CYAN);
//String array to populate the combobox options
String[] countries = {"Australia", "Brazil", "Canada", "China"
,"France", "Japan", "Norway", "Russia", "South Korea"
, "Tunisia", "USA"};
JComboBox countryCombo = new JComboBox(countries);
//Set the default editor for the Country column to be the combobox
TableColumn countryColumn = table.getColumnModel().get Column(2);
countryColumn.setCellEdito r(new DefaultCellEditor(countryC ombo));
//set the Event column to be larger than the rest and the Place column
//to be smaller
TableColumn eventColumn = table.getColumnModel().get Column(3);
eventColumn.setPreferredWi dth(150);
TableColumn placeColumn = table.getColumnModel().get Column(4);
placeColumn.setPreferredWi dth(5);
//frame.getContentPane().a dd(table);
frame.getContentPane().add (new FrozenTablePane(table, 2));
frame.setPreferredSize(new Dimension(800, 500));
frame.setDefaultCloseOpera tion(Windo wConstants .DISPOSE_O N_CLOSE);
frame.pack();
frame.setVisible(true);
//create and display the test console
createTestFrame();
}
private static void createTestFrame() {
JFrame mButtonFrame = new JFrame();
mButtonFrame.setLayout(new GridBagLayout());
JButton mButton = new JButton("Set Frozen Columns");
mButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEven t e) {
System.out.println("Change the number of frozen columns here.");
}
});
mButtonFrame.add(mButton);
JTextField mTextField = new JTextField();
mTextField.setPreferredSiz e(mButton. getPreferr edSize());
mButtonFrame.add(mTextFiel d);
mButtonFrame.pack();
mButtonFrame.setVisible(tr ue);
}
}
<<<ExampleTableModel.java> >>
import javax.swing.table.Abstract TableModel ;
class ExampleTableModel extends AbstractTableModel {
// Two arrays used for the table data
String[] columnNames = { "First Name", "Surname", "Country", "Event",
"Place", "Time", "World Record" };
Object[][] data = {
{ "César Cielo", "Filho", "Brazil", "50m freestyle", 1,
"21.30", false },
{ "Amaury", "Leveaux", "France", "50m freestyle", 2, "21.45",
false },
{ "Alain", "Bernard", "France", "50m freestyle", 3, "21.49",
false },
{ "Alain", "Bernard", "France", "100m freestyle", 1, "47.21",
false },
{ "Eamon", "Sullivan", "Australia", "100m freestyle", 2,
"47.32", false },
{ "Jason", "Lezak", "USA", "100m freestyle", 3, "47.67", false },
{ "César Cielo", "Filho", "Brazil", "100m freestyle", 3,
"47.67", false },
{ "Michael", "Phelps", "USA", "200m freestyle", 1, "1:42.96",
true },
{ "Park", "Tae-Hwan", "South Korea", "200m freestyle", 2,
"1:44.85", false },
{ "Peter", "Vanderkaay", "USA", "200m freestyle", 3, "1:45.14",
false },
{ "Park", "Tae-Hwan", "South Korea", "400m freestyle", 1,
"3:41.86", false },
{ "Zhang", "Lin", "China", "400m freestyle", 2, "3:42.44",
false },
{ "Larsen", "Jensen", "USA", "400m freestyle", 3, "3:42.78",
false },
{ "Oussama", "Mellouli", "Tunisia", "1500m freestyle", 1,
"14:40.84", false },
{ "Grant", "Hackett", "Australia", "1500m freestyle", 2,
"14:41.53", false },
{ "Ryan", "Cochrane", "Canada", "1500m freestyle", 3,
"14:42.69", false },
{ "Aaron", "Peirsol", "USA", "100m backstroke", 1, "52.54",
true },
{ "Matt", "Grevers", "USA", "100m backstroke", 2, "53.11",
false },
{ "Arkady", "Vyatchanin", "Russia", "100m backstroke", 3,
"53.18", false },
{ "Hayden", "Stoeckel", "Australia", "100m freestyle", 3,
"53.18", false },
{ "Ryan", "Lochte", "USA", "200m backstroke", 1, "1:53.94",
true },
{ "Aaron", "Peirsol", "USA", "200m backstroke", 2, "1:54.33",
false },
{ "Arkady", "Vyatchanin", "Russia", "200m backstroke", 3,
"1:54.93", false },
{ "Kosuke", "Kitajima", "Japan", "100m breaststroke", 1,
"58.91", true },
{ "Alexander", "Dale Oen", "Norway", "100m breaststroke", 2,
"59.20", false },
{ "Hugues", "Duboscq", "France", "100m breaststroke", 3,
"59.37", false } };
@Override
public int getRowCount() {
return data.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int row, int column) {
return data[row][column];
}
// Used by the JTable object to set the column names
@Override
public String getColumnName(int column) {
return columnNames[column];
}
// Used by the JTable object to render different
// functionality based on the data type
@Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
@Override
public boolean isCellEditable(int row, int column) {
if (column == 0 || column == 1) {
return false;
} else {
return true;
}
}
}
frame.getContentPane().add
This works, however I would like to dynamically change the number of frozen columns from the UI, for example, in the code below, in the test console created from
createTestFrame();
by entering the number of columns to freeze, then clicking on the "Set Frozen Columns" button, this would change the number of columns that are frozen in the table. Is it possible to do this? I have not been able to come up with a solution. The code for the two files FrozenTablePane.java and ExampleTableModel.java (the sample table data) are below:
<<<FrozenTablePane.java>>>
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent
import java.awt.event.ActionListe
import java.util.HashSet;
import javax.swing.DefaultCellEdi
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.WindowConstant
import javax.swing.table.Abstract
import javax.swing.table.DefaultT
import javax.swing.table.JTableHe
import javax.swing.table.TableCol
import javax.swing.table.TableMod
public class FrozenTablePane extends JScrollPane {
public FrozenTablePane(JTable table, int colsToFreeze) {
super(table);
TableModel model = table.getModel();
// create a frozen model
TableModel frozenModel = new DefaultTableModel(model.ge
colsToFreeze);
// populate the frozen model
for (int i = 0; i < model.getRowCount(); i++) {
for (int j = 0; j < colsToFreeze; j++) {
String value = (String) model.getValueAt(i, j);
frozenModel.setValueAt(val
}
}
// create frozen table
JTable frozenTable = new JTable(frozenModel);
// remove the frozen columns from the original table
for (int j = 0; j < colsToFreeze; j++) {
table.removeColumn(table.g
}
table.setAutoResizeMode(JT
// format the frozen table
JTableHeader header = table.getTableHeader();
frozenTable.setBackground(
frozenTable.setAutoResizeM
frozenTable.setEnabled(fal
// set frozen table as row header view
JViewport viewport = new JViewport();
viewport.setView(frozenTab
viewport.setPreferredSize(
setRowHeaderView(viewport)
setCorner(JScrollPane.UPPE
}
/**
* The main() is used in application.
*
* @param args
* command line arguments
*/
public static void main(final String[] args) {
// Create parent frame for ReportApplianceUI
JFrame frame = new JFrame("FrozenTablePane");
//Create the JTable using the ExampleTableModel implementing
//the AbstractTableModel abstract class
JTable table = new JTable(new ExampleTableModel());
//Set the column sorting functionality on
table.setAutoCreateRowSort
//Uncomment the next line if you want to turn the grid lines off
// table.setShowGrid(false);
//Change the colour of the table - yellow for gridlines
//blue for background
table.setGridColor(Color.Y
table.setBackground(Color.
//String array to populate the combobox options
String[] countries = {"Australia", "Brazil", "Canada", "China"
,"France", "Japan", "Norway", "Russia", "South Korea"
, "Tunisia", "USA"};
JComboBox countryCombo = new JComboBox(countries);
//Set the default editor for the Country column to be the combobox
TableColumn countryColumn = table.getColumnModel().get
countryColumn.setCellEdito
//set the Event column to be larger than the rest and the Place column
//to be smaller
TableColumn eventColumn = table.getColumnModel().get
eventColumn.setPreferredWi
TableColumn placeColumn = table.getColumnModel().get
placeColumn.setPreferredWi
//frame.getContentPane().a
frame.getContentPane().add
frame.setPreferredSize(new
frame.setDefaultCloseOpera
frame.pack();
frame.setVisible(true);
//create and display the test console
createTestFrame();
}
private static void createTestFrame() {
JFrame mButtonFrame = new JFrame();
mButtonFrame.setLayout(new
JButton mButton = new JButton("Set Frozen Columns");
mButton.addActionListener(
public void actionPerformed(ActionEven
System.out.println("Change
}
});
mButtonFrame.add(mButton);
JTextField mTextField = new JTextField();
mTextField.setPreferredSiz
mButtonFrame.add(mTextFiel
mButtonFrame.pack();
mButtonFrame.setVisible(tr
}
}
<<<ExampleTableModel.java>
import javax.swing.table.Abstract
class ExampleTableModel extends AbstractTableModel {
// Two arrays used for the table data
String[] columnNames = { "First Name", "Surname", "Country", "Event",
"Place", "Time", "World Record" };
Object[][] data = {
{ "César Cielo", "Filho", "Brazil", "50m freestyle", 1,
"21.30", false },
{ "Amaury", "Leveaux", "France", "50m freestyle", 2, "21.45",
false },
{ "Alain", "Bernard", "France", "50m freestyle", 3, "21.49",
false },
{ "Alain", "Bernard", "France", "100m freestyle", 1, "47.21",
false },
{ "Eamon", "Sullivan", "Australia", "100m freestyle", 2,
"47.32", false },
{ "Jason", "Lezak", "USA", "100m freestyle", 3, "47.67", false },
{ "César Cielo", "Filho", "Brazil", "100m freestyle", 3,
"47.67", false },
{ "Michael", "Phelps", "USA", "200m freestyle", 1, "1:42.96",
true },
{ "Park", "Tae-Hwan", "South Korea", "200m freestyle", 2,
"1:44.85", false },
{ "Peter", "Vanderkaay", "USA", "200m freestyle", 3, "1:45.14",
false },
{ "Park", "Tae-Hwan", "South Korea", "400m freestyle", 1,
"3:41.86", false },
{ "Zhang", "Lin", "China", "400m freestyle", 2, "3:42.44",
false },
{ "Larsen", "Jensen", "USA", "400m freestyle", 3, "3:42.78",
false },
{ "Oussama", "Mellouli", "Tunisia", "1500m freestyle", 1,
"14:40.84", false },
{ "Grant", "Hackett", "Australia", "1500m freestyle", 2,
"14:41.53", false },
{ "Ryan", "Cochrane", "Canada", "1500m freestyle", 3,
"14:42.69", false },
{ "Aaron", "Peirsol", "USA", "100m backstroke", 1, "52.54",
true },
{ "Matt", "Grevers", "USA", "100m backstroke", 2, "53.11",
false },
{ "Arkady", "Vyatchanin", "Russia", "100m backstroke", 3,
"53.18", false },
{ "Hayden", "Stoeckel", "Australia", "100m freestyle", 3,
"53.18", false },
{ "Ryan", "Lochte", "USA", "200m backstroke", 1, "1:53.94",
true },
{ "Aaron", "Peirsol", "USA", "200m backstroke", 2, "1:54.33",
false },
{ "Arkady", "Vyatchanin", "Russia", "200m backstroke", 3,
"1:54.93", false },
{ "Kosuke", "Kitajima", "Japan", "100m breaststroke", 1,
"58.91", true },
{ "Alexander", "Dale Oen", "Norway", "100m breaststroke", 2,
"59.20", false },
{ "Hugues", "Duboscq", "France", "100m breaststroke", 3,
"59.37", false } };
@Override
public int getRowCount() {
return data.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int row, int column) {
return data[row][column];
}
// Used by the JTable object to set the column names
@Override
public String getColumnName(int column) {
return columnNames[column];
}
// Used by the JTable object to render different
// functionality based on the data type
@Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
@Override
public boolean isCellEditable(int row, int column) {
if (column == 0 || column == 1) {
return false;
} else {
return true;
}
}
}
ASKER
Thank you for your code, that was very informative for me!
However, I forgot to mention that in the case where there are many columns, when I scroll sideways through the columns, the frozen columns should not move, only the non-frozen columns can be scrolled through. I cannot think of a way to do this other than using the two table model.
However, I forgot to mention that in the case where there are many columns, when I scroll sideways through the columns, the frozen columns should not move, only the non-frozen columns can be scrolled through. I cannot think of a way to do this other than using the two table model.
when I scroll sideways through the columns, the frozen columns should not move, only the non-frozen columns can be scrolled through.Have a look at FixedColumnTable. I think it does what you want.
[Edit] It indeed does what you want. And in a very neat way.
Download the FixedColumnTable.java file.
And then this (slightly adapted) code does what you want:
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class FixedTableColumns extends JFrame {
private int NUMBER_OF_FROZEN_COLUMNS = 2;
private int columnValue = -1;
private int columnNewValue = -1;
public FixedTableColumns(String title) {
super(title);
getContentPane().setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(getTable());
getContentPane().add(scrollPane, BorderLayout.CENTER);
FixedColumnTable fct = new FixedColumnTable(2, scrollPane);
}
private JTable getTable() {
String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian", "Other", "Other 2", "Other 3"};
Object[][] data = {
{"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false), "test value", "test value", "test value"},
{"John", "Doe", "Rowing", new Integer(3), new Boolean(true), "test value", "test value", "test value"},
{"Sue", "Black", "Knitting", new Integer(2), new Boolean(false), "test value", "test value", "test value"},
{"Jane", "White", "Speed reading", new Integer(20), new Boolean(true), "test value", "test value", "test value"},
{"Joe", "Brown", "Pool", new Integer(10), new Boolean(false), "test value", "test value", "test value"}
};
JTable table = new JTable(data, columnNames);
table.setFillsViewportHeight(true);
table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnAdded(TableColumnModelEvent e) {
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
}
@Override
public void columnMoved(TableColumnModelEvent e) {
if (columnValue == -1) {
columnValue = e.getFromIndex();
}
columnNewValue = e.getToIndex();
}
@Override
public void columnMarginChanged(ChangeEvent e) {
}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
}
});
table.getTableHeader().addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if ( columnValue != -1 &&
(columnValue < NUMBER_OF_FROZEN_COLUMNS || columnNewValue < NUMBER_OF_FROZEN_COLUMNS)
) {
table.moveColumn(columnNewValue, columnValue);
}
columnValue = -1;
columnNewValue = -1;
}
});
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getColumnModel().getColumn(0).setPreferredWidth(75);
table.getColumnModel().getColumn(1).setPreferredWidth(75);
return table;
}
public static void main(String[] args) {
final JFrame frame = new FixedTableColumns("Unmovable columns example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeTo(null); // center
frame.setVisible(true);
}
}
ASKER
Thank you!
One last thing, I am able to dynamically change the number of frozen columns by disposing of the entire frame, and recreating it, such as:
import javax.swing.*;
import javax.swing.event.ChangeEv ent;
import javax.swing.event.ListSele ctionEvent ;
import javax.swing.event.TableCol umnModelEv ent;
import javax.swing.event.TableCol umnModelLi stener;
import javax.swing.table.TableCol umn;
import javax.swing.table.TableCol umnModel;
import java.awt.*;
import java.awt.event.ActionEvent ;
import java.awt.event.ActionListe ner;
import java.awt.event.MouseAdapte r;
import java.awt.event.MouseEvent;
public class FixedTableColumns extends JFrame {
private int NUMBER_OF_FROZEN_COLUMNS = 0;
private static int NUMBER_OF_UNMOVABLE_COLUMN S = 2;
private int columnValue = -1;
private int columnNewValue = -1;
private FixedColumnTable fct;
private JTable table;
private static FixedTableColumns frame;
public FixedTableColumns(String title, int numUnmoveable) {
super(title);
getContentPane().setLayout (new BorderLayout());
JScrollPane scrollPane = new JScrollPane(getTable());
getContentPane().add(scrol lPane, BorderLayout.CENTER);
NUMBER_OF_UNMOVABLE_COLUMN S = numUnmoveable;
fct = new FixedColumnTable(NUMBER_OF _UNMOVABLE _COLUMNS, scrollPane);
}
private JTable getTable() {
String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian", "Other", "Other 2", "Other 3"};
Object[][] data = {
{"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false), "test value", "test value", "test value"},
{"John", "Doe", "Rowing", new Integer(3), new Boolean(true), "test value", "test value", "test value"},
{"Sue", "Black", "Knitting", new Integer(2), new Boolean(false), "test value", "test value", "test value"},
{"Jane", "White", "Speed reading", new Integer(20), new Boolean(true), "test value", "test value", "test value"},
{"Joe", "Brown", "Pool", new Integer(10), new Boolean(false), "test value", "test value", "test value"}
};
//JTable table = new JTable(data, columnNames);
table = new JTable(data, columnNames);
table.setFillsViewportHeig ht(true);
table.getColumnModel().add ColumnMode lListener( new TableColumnModelListener() {
@Override
public void columnAdded(TableColumnMod elEvent e) {
}
@Override
public void columnRemoved(TableColumnM odelEvent e) {
}
@Override
public void columnMoved(TableColumnMod elEvent e) {
if (columnValue == -1) {
columnValue = e.getFromIndex();
}
columnNewValue = e.getToIndex();
}
@Override
public void columnMarginChanged(Change Event e) {
}
@Override
public void columnSelectionChanged(Lis tSelection Event e) {
}
});
table.getTableHeader().add MouseListe ner(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if ( columnValue != -1 &&
(columnValue < NUMBER_OF_FROZEN_COLUMNS || columnNewValue < NUMBER_OF_FROZEN_COLUMNS)
) {
table.moveColumn(columnNew Value, columnValue);
}
columnValue = -1;
columnNewValue = -1;
}
});
table.setAutoResizeMode(JT able.AUTO_ RESIZE_OFF );
table.getColumnModel().get Column(0). setPreferr edWidth(75 );
table.getColumnModel().get Column(1). setPreferr edWidth(75 );
return table;
}
private static void createTestFrame() {
JFrame mButtonFrame = new JFrame();
mButtonFrame.setLayout(new GridBagLayout());
final JTextField mTextField = new JTextField();
JButton mButton = new JButton("Set Frozen Columns");
mButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEven t e) {
System.out.println("Change the number of frozen columns here. " + mTextField.getText());
int numUnmoveable = Integer.parseInt(mTextFiel d.getText( ));
//dispose of the frame and recreate it with the new number of unmoveable columns
frame.dispose();
frame = new FixedTableColumns("Unmovab le columns example", numUnmoveable);
frame.setDefaultCloseOpera tion(JFram e.EXIT_ON_ CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeT o(null); // center
frame.setVisible(true);
}
});
mTextField.setPreferredSiz e(mButton. getPreferr edSize());
mButtonFrame.add(mButton);
mButtonFrame.add(mTextFiel d);
mButtonFrame.pack();
mButtonFrame.setVisible(tr ue);
}
public static void main(String[] args) {
frame = new FixedTableColumns("Unmovab le columns example", 2);
frame.setDefaultCloseOpera tion(JFram e.EXIT_ON_ CLOSE);
frame.setSize(400, 300);
frame.setLocationRelativeT o(null); // center
frame.setVisible(true);
//create the test widget, which will dispose of the frame and recreate it with the new number of unmoveable columns in the listener
createTestFrame();
}
}
Would this be possible without disposing of the entire frame, such as by recreating only the FixedColumnTable in the frame, and somehow updating the frame to show the new FixedColumnTable instead of disposing of the frame first?
I tried something like
public void actionPerformed(ActionEven t e) {
System.out.println("Change the number of frozen columns here. " + mTextField.getText());
int numUnmoveable = Integer.parseInt(mTextFiel d.getText( ));
//dispose of the frame and recreate it with the new number of unmoveable columns
//frame.dispose();
//frame = new FixedTableColumns("Unmovab le columns example", numUnmoveable);
//frame.setDefaultCloseOpe ration(JFr ame.EXIT_O N_CLOSE);
//frame.setSize(400, 300);
//frame.setLocationRelativ eTo(null); // center
//frame.setVisible(true);
System.out.println("Compon ent Count: " + frame.getContentPane().get ComponentC ount());
frame.getContentPane().rem oveAll();
JScrollPane scrollPane = new JScrollPane(frame.getTable ());
frame.getContentPane().add (scrollPan e, BorderLayout.CENTER);
frame.fct = new FixedColumnTable(NUMBER_OF _UNMOVABLE _COLUMNS, scrollPane);
frame.validate();
frame.repaint();
}
but it does not update the frame.
One last thing, I am able to dynamically change the number of frozen columns by disposing of the entire frame, and recreating it, such as:
import javax.swing.*;
import javax.swing.event.ChangeEv
import javax.swing.event.ListSele
import javax.swing.event.TableCol
import javax.swing.event.TableCol
import javax.swing.table.TableCol
import javax.swing.table.TableCol
import java.awt.*;
import java.awt.event.ActionEvent
import java.awt.event.ActionListe
import java.awt.event.MouseAdapte
import java.awt.event.MouseEvent;
public class FixedTableColumns extends JFrame {
private int NUMBER_OF_FROZEN_COLUMNS = 0;
private static int NUMBER_OF_UNMOVABLE_COLUMN
private int columnValue = -1;
private int columnNewValue = -1;
private FixedColumnTable fct;
private JTable table;
private static FixedTableColumns frame;
public FixedTableColumns(String title, int numUnmoveable) {
super(title);
getContentPane().setLayout
JScrollPane scrollPane = new JScrollPane(getTable());
getContentPane().add(scrol
NUMBER_OF_UNMOVABLE_COLUMN
fct = new FixedColumnTable(NUMBER_OF
}
private JTable getTable() {
String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian", "Other", "Other 2", "Other 3"};
Object[][] data = {
{"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false), "test value", "test value", "test value"},
{"John", "Doe", "Rowing", new Integer(3), new Boolean(true), "test value", "test value", "test value"},
{"Sue", "Black", "Knitting", new Integer(2), new Boolean(false), "test value", "test value", "test value"},
{"Jane", "White", "Speed reading", new Integer(20), new Boolean(true), "test value", "test value", "test value"},
{"Joe", "Brown", "Pool", new Integer(10), new Boolean(false), "test value", "test value", "test value"}
};
//JTable table = new JTable(data, columnNames);
table = new JTable(data, columnNames);
table.setFillsViewportHeig
table.getColumnModel().add
@Override
public void columnAdded(TableColumnMod
}
@Override
public void columnRemoved(TableColumnM
}
@Override
public void columnMoved(TableColumnMod
if (columnValue == -1) {
columnValue = e.getFromIndex();
}
columnNewValue = e.getToIndex();
}
@Override
public void columnMarginChanged(Change
}
@Override
public void columnSelectionChanged(Lis
}
});
table.getTableHeader().add
@Override
public void mouseReleased(MouseEvent e) {
if ( columnValue != -1 &&
(columnValue < NUMBER_OF_FROZEN_COLUMNS || columnNewValue < NUMBER_OF_FROZEN_COLUMNS)
) {
table.moveColumn(columnNew
}
columnValue = -1;
columnNewValue = -1;
}
});
table.setAutoResizeMode(JT
table.getColumnModel().get
table.getColumnModel().get
return table;
}
private static void createTestFrame() {
JFrame mButtonFrame = new JFrame();
mButtonFrame.setLayout(new
final JTextField mTextField = new JTextField();
JButton mButton = new JButton("Set Frozen Columns");
mButton.addActionListener(
public void actionPerformed(ActionEven
System.out.println("Change
int numUnmoveable = Integer.parseInt(mTextFiel
//dispose of the frame and recreate it with the new number of unmoveable columns
frame.dispose();
frame = new FixedTableColumns("Unmovab
frame.setDefaultCloseOpera
frame.setSize(400, 300);
frame.setLocationRelativeT
frame.setVisible(true);
}
});
mTextField.setPreferredSiz
mButtonFrame.add(mButton);
mButtonFrame.add(mTextFiel
mButtonFrame.pack();
mButtonFrame.setVisible(tr
}
public static void main(String[] args) {
frame = new FixedTableColumns("Unmovab
frame.setDefaultCloseOpera
frame.setSize(400, 300);
frame.setLocationRelativeT
frame.setVisible(true);
//create the test widget, which will dispose of the frame and recreate it with the new number of unmoveable columns in the listener
createTestFrame();
}
}
Would this be possible without disposing of the entire frame, such as by recreating only the FixedColumnTable in the frame, and somehow updating the frame to show the new FixedColumnTable instead of disposing of the frame first?
I tried something like
public void actionPerformed(ActionEven
System.out.println("Change
int numUnmoveable = Integer.parseInt(mTextFiel
//dispose of the frame and recreate it with the new number of unmoveable columns
//frame.dispose();
//frame = new FixedTableColumns("Unmovab
//frame.setDefaultCloseOpe
//frame.setSize(400, 300);
//frame.setLocationRelativ
//frame.setVisible(true);
System.out.println("Compon
frame.getContentPane().rem
JScrollPane scrollPane = new JScrollPane(frame.getTable
frame.getContentPane().add
frame.fct = new FixedColumnTable(NUMBER_OF
frame.validate();
frame.repaint();
}
but it does not update the frame.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Yep, the code works great, thank you so much!
You're welcome.
Thanx 4 axxepting.
Thanx 4 axxepting.
Open in new window
By changing the value of
Open in new window
you can choose how much columns you want to be unmovable.So in this example the columns "First name" and "Last name" can't be moved.
The other three can.
However, you can't eg. move the 3rd column to the 1st or the 2nd place since that would mean a move of the 1st or 2nd column which is impossible.