JTable hide and show columns - java

I want to add some columns to a table (Swing JTable). Some of them will have a default size (e.g. 250), others will be hidden (so their size will be 0). I use this code:
model = new DefaultTableModel();
table = new JTable(model);
setAutoResizeMode(AUTO_RESIZE_OFF);
for (int i = 1; i < COLUMN_NAMES.length; i++) {
model.addColumn(COLUMN_NAMES[i]);
if (show[i]) show(index);
else hide(index);
}
........
private void hide(int index) {
TableColumn column = getColumnModel().getColumn(index);
column.setMinWidth(0);
column.setMaxWidth(0);
column.setWidth(0);
column.setPreferredWidth(0);
doLayout();
}
private void show(int index) {
final int width = 250;
column.setMinWidth(15);
column.setMaxWidth(width);
column.setWidth(width);
column.setPreferredWidth(width);
doLayout();
}
the problem is when the table is displayed, all the columns are showed (none is hidden) and their size is not 250 but they have all the same size.
How can I get the wanted effect?

I think you have named your methods incorrectly, when you want to hide a column you will set
column.setMinWidth(0);
column.setMaxWidth(0);
column.setPreferredWidth(0);
but in your code you are doing this when you want to show a column which is exactly opposite.
Also there is no need to call this "setWidth" method on a TableColumn, read TableColumn#setWidth(int).

JTable#removeColumn remove Column only from JTable view, more in this example

instead of re-inventing the wheel you might consider to use JXTable (in the SwingX project) which supports hidden columns, comlete with a ui-control to allow users hiding/showing them dynamically - and a bunch of other useful thingies :).

try this something like this for example:
myTableModel = new DefaultTableModel();
myTableModel.setColumnIdentifiers(new Object[]{"ID", "Name"});
JTable myTable = new JTable(myTableModel);
// remember to save the references
TableColumn myTableColumn0 = guiLoteryNumbersTable.getColumnModel().getColumn(0);
TableColumn myTableColumn1 = guiLoteryNumbersTable.getColumnModel().getColumn(1);
//...
// remove temporary the column ("hide")
myTable.getColumnModel().removeColumn(myTableColumn1);
// then you restore that column when you need it ("show")
myTable.getColumnModel().addColumn(myTableColumn1);
That's the best way I know to hide a column.

HashMap<String,TableColumn> hashMap_columns = new HashMap<String,TableColumn>();
DefaultTableColumnModel defaultTableColumnModel = (DefaultTableColumnModel)jtable.getColumnModel();
Enumeration<TableColumn> enumeration = defaultTableColumnModel.getColumns();
while (enumeration.hasMoreElements())
{
TableColumn tableColumn = enumeration.nextElement();
hashMap_columns.put((String)tableColumn.getIdentifier(),tableColumn);
}
public void setColumnVisible(String identifier, boolean setVisible)
{
TableColumn tableColumn = hashMap_columns.get(identifier);
if (setVisible)
{
// using a sorted map removes the need to check column index/position
SortedMap<Integer,TableColumn> sortedMap = new TreeMap<Integer,TableColumn>();
// retreive all visible columns
Enumeration<TableColumn> enumeration = defaultTableColumnModel.getColumns();
while (enumeration.hasMoreElements())
{
TableColumn column = enumeration.nextElement();
sortedMap.put(column.getModelIndex(),column);
}
// add the column of interest to the sorted map
sortedMap.put(tableColumn.getModelIndex(),tableColumn);
// remove all visible columns
for (TableColumn column: sortedMap.values())
{
defaultTableColumnModel.removeColumn(column);
}
// add all previously visible columns as well as the column of interest
for (TableColumn column: sortedMap.values())
{
defaultTableColumnModel.addColumn(column);
}
}
else
{
defaultTableColumnModel.removeColumn(tableColumn);
}
}

public class TableColumnHider {
private final JTable table;
private final TableColumnModel tcm;
private final Map hiddenColumns;
public TableColumnHider(JTable table) {
this.table = table;
tcm = table.getColumnModel();
hiddenColumns = new HashMap();
}
public void hide(String columnName, String keySig) {
int index = tcm.getColumnIndex(columnName);
TableColumn column = tcm.getColumn(index);
hiddenColumns.put(columnName, column);
hiddenColumns.put(keySig + columnName, new Integer(index));
tcm.removeColumn(column);
}
public void show(String columnName, String keySig) {
Object o = hiddenColumns.remove(columnName);
if (o == null) {
return;
}
tcm.addColumn((TableColumn) o);
o = hiddenColumns.remove(keySig + columnName);
if (o == null) {
return;
}
int column = ((Integer) o).intValue();
int lastColumn = tcm.getColumnCount() - 1;
if (column < lastColumn) {
tcm.moveColumn(lastColumn, column);
}
}
}

Related

JTable select and deselect not working

I have a problem with my JTable. Firstly I selected some entries in my table. However when I deselect some of them, the table could not understand it.
Example scenario: I select job1 and 2 for the testing after that I change my mind and de-select job2. But in the result I saw job1 job1 and job2 ( job 1 seen 2 times and even though I dis-select job 2 I saw them.) Or after selected all the jobs ( choose all button) I want to deselect all of them (Clear button) when I click clear all the table seems empty. It is good but somehow the background of the program still protect the all old selection. How can I solve this?
Try:
I created the row of my table by read csv file.
public class JobSelectionListPanel extends JPanel {
private static final long serialVersionUID = 5198916547962359735L;
private static JobSelectionListPanel INSTANCE = new JobSelectionListPanel();
public static JobSelectionListPanel getInstance() {
return INSTANCE;
}
private JTable table;
private JButton next, back, btnClear, btnNewButton, btnChooseAll;
private JobList fnnJobList = new JobList();
private JobSelectionListPanel() {
table = new JTable();
JScrollPane scrollPane = new JScrollPane(table);
table.setBorder(new CompoundBorder());
// Read all FNN jobs from file
try {
fnnJobList.readFromFile("rules.csv");
} catch (IOException e1) {
System.out.println("You are not able to read the rules.csv file");
}
// Create ArrayList of JobNames
Object[][] initialData = new Object[fnnJobList.size()][1];
int i = 0;
for (Job jobDes : fnnJobList) {
initialData[i][0] = (Object) jobDes.getJobname();
i++;
}
String[] columnNames = new String[] { "", "Your preferences" };
table.setModel(new DefaultTableModel(initialData, columnNames) {
private static final long serialVersionUID = 1L;
#SuppressWarnings("rawtypes")
Class[] columnTypes = new Class[] { Object.class, Boolean.class };
#SuppressWarnings({ "unchecked", "rawtypes" })
public Class getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
});
table.getColumnModel().getColumn(1).setPreferredWidth(80);
table.getColumnModel().getColumn(1).setMinWidth(40);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setCellSelectionEnabled(true);
I user want to choose all rows then I implemented this.
btnChooseAll = new JButton("Choose all");
btnChooseAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel chooseAllData = (DefaultTableModel) table.getModel();
if (DeviceGroups.DeviceAList.size() == 0 || DeviceGroups.DeviceBList.size() == 0
|| DeviceGroups.DeviceCList.size() == 0 || DeviceGroups.DeviceDList.size() == 0)
JOptionPane.showMessageDialog(null,
"You should choose at least 1 device for each test device to apply this test case", "Invalid OPTION",
JOptionPane.ERROR_MESSAGE);
else
for (int i = 0; i < chooseAllData.getRowCount(); i++) {
for (int j = 1; j < chooseAllData.getColumnCount(); j++) {
chooseAllData.setValueAt(true, i, j);
}
}
}
});
For clear all preferences :
btnClear = new JButton("Clear all");
// Clear button create a model of JTable and delete all the rows of table!!
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DefaultTableModel clearTableData = (DefaultTableModel) table.getModel();
for (int i = 0; i < clearTableData.getRowCount(); i++) {
for (int j = 1; j < clearTableData.getColumnCount(); j++) {
clearTableData.setValueAt(null, i, j);
}
}
}
});
I see the following problem in your code: mixing up view indexes and model indexes. This is the offending snippet:
for (int i = 0; i < table.getRowCount(); i++) {
if (table.getValueAt(i, 1) != null) {
if (((Boolean) table.getValueAt(i, 1)).booleanValue()) {
String jobName = (((DefaultTableModel) table.getModel()).getValueAt(i, 0).toString());
You are using the i variable to denote view row indices, since you are checking values in this statement: table.getValueAt(i, 1) != null.
But then a bit further you are using i to index the model:
String jobName = ((DefaultTableModel) table.getModel()).getValueAt(i, 0).toString();
If i is to be a view index, you need to convert it to a model index before indexing the model:
String jobName = ((DefaultTableModel) table.getModel()).getValueAt(table.convertRowIndexToModel(i), 0).toString();
Also, when columns would be switched around in the view (ie on screen in your GUI), the following will probably not work as intended:
table.getValueAt(i, 1) != null
You most likely mean to say, get the second column value in the model, not the view. Best rewrite then as
table.getValueAt(i, table.convertColumnIndexToView(1)) != null

Validate if jtable is empty?

I need to know how to check if there is data in a JTable something like
if(jTextField1.getText().isEmpty()):
then (if jTable1.isEmpty())
...
how I do that?
JTables are not simple components like the jtextfield, like other swing components they have an underlying Data Model, check this example from the javadoc:
TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() { return 10; }
public int getRowCount() { return 10;}
public Object getValueAt(int row, int col) { return new Integer(row*col); }
};
JTable table = new JTable(dataModel);
Like in every UI object that follows the MVC pattern, you don't use the graphical component to understand the values it has, you use the data model. In you case, save a reference to the Data Model of the JTable you created and call getRowCount to know how much data you have previously loaded.
Also, check the official docs here.
I validate if the jtable is empty with
this code.
private int calculate() {
Vector<Integer> myvector = new Vector();
TableModel mode = new DefaultTableModel();
mode = jTable2.getModel();
int n = mode.getRowCount();
for (int i = 0; i < n; i++) {
if (mode.getValueAt(i, 3) != null) {
myvector.add((Integer) mode.getValueAt(i, 3));
}
}
return myvector.size();
}
//then I validate with a button
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
int numofvalidrows;
numofvalidrows = calculate();
if (numofvalidrows == 0) //if the size of the vector is 0 then the jtable is empty
{
System.out.println("You need to add people to the jtable, because the table is empty");
} else {
// I get the values of the jtable with
for (int i = 0; i < n; i++) {
if (model.getValueAt(i, 3) != null) { //whith this "if" I print only data, not print null of the empty cells in jtable
System.out.print(model.getValueAt(i, 3))
}
}
}
}

how to avoid duplicating JTable columns in java?

i want to add a cloumn to a jtable when a radio button is being clicked. but when i click it twice two columns are being added to the table. here's my code
dtm = (DefaultTableModel) viewTable.getModel();
dtm.setRowCount(0);
TableColumnModel model=viewTable.getColumnModel();
boolean found=false;
for (int i = 0; i < viewTable.getColumnCount(); i++) {
if (model.getColumn(i).getIdentifier().equals("customer Id")) {
found=true;
break;
}
if (found==false) {
dtm.addColumn("customer Id");
}
don't know how to fix it..
This code would help you. Call the below method on actionPerformed of the check box and if it is true. Validating it based on the column header.
private static void addColumn( final JTable table, final String newColumnHeader )
{
final JTableHeader header = table.getTableHeader();
final int columnCount = header.getColumnModel().getColumnCount();
boolean addColumn = true;
for( int index = 0; index < columnCount; index ++ )
{
final Object headerValue = header.getColumnModel().getColumn(index).getHeaderValue();
if( newColumnHeader.equals( headerValue ) )
{
JOptionPane.showMessageDialog(null, "Column already exists" );
addColumn = false;
break;
}
}
if( addColumn )
{
final TableColumn newCol = new TableColumn();
newCol.setHeaderValue(newColumnHeader);
table.getColumnModel().addColumn(newCol);
}
}
It is good to disable the checkbox if it is already clicked ;) if you do not want a huge code.
This is a clumsy solution but it will work.
You can create a new boolean variable in your class and this variable represents if a column was set or not.
Like:
class MyClass{
boolean isColumnAdded
public MyClass(){
isColumnAdded = false;
}
private void radioButtonActionPerformed(java.awt.event.ActionEvent evt){
if(!isColumnAdded){
//add column
isColumnAdded = true;
}
}
}
To start with, JRadioButton has a selected property. You should be checking this state to determine if the column needs to be removed or added...
Assume that each column name is unique, you could use something like...
TableColumnModel model = viewTable.getColumnModel();
int index = -1;
try {
index = model.getColumnIndex("customer Id");
} catch (IllegalArgumentException e) {
// I know, sucks...
}
if (index < 0) {
// Add new column, if JRadioButton.isSelected
} else {
// Remove old column...
// JRadioButton.isSelected is false...
}
To find and add/remove the column.
Have a look at How to Use Buttons, Check Boxes, and Radio Buttons for some more details

Calculate the sum of a column and put it on that jtable

How can I calculate sum of price column in jTable and put sum of them at the end of the jTable. Can you give me a sample code?
public class IncomeReport extends JFrame {
private AccountFacade service = new AccountFacade();
void init() {
String[] columnNames = {"مبلغ", "محل درآمد ", "منبع"};
List list = service.incomeReportFacade();
Object[][] model = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
model[i] = (Object[]) list.get(i);
}
JTable table = new JTable(model, columnNames) {
DefaultTableCellRenderer renderRight = new DefaultTableCellRenderer();
{
// initializer block
renderRight.setHorizontalAlignment(SwingConstants.RIGHT);
}
#Override
public TableCellRenderer getCellRenderer(int arg0, int arg1) {
return renderRight;
}
};
Try something like this. Get the model, and use the DefaultTableModel#getValueAt() method.
Jtable table = new Jtable();
DefaultTableModel model = (DefaultTableModel)table.getModel();
double total = 0;
int column = 2; // example
for (int i = 0; i < model.getRowCount(); i++){
total += model.getValueAt(i, column); // getValueAt(row, column)
}
Object[] row = {"", "", total};
model.addRow(row);
If you need a total that is dynamically kept up to date then you will need to either override your TableModel to provide the sum for the final row, or will need to listener for changes to the model and update the last row with the sum.
Customizing your own TableModel would also allow you the ability to make your summary row uneditable so while this might be more work, it provides much more flexibility.

Java Swing JTable: cannot access the values in the table due to incorrect usage/creation of table model

I am just beginning to program using Java Swing. I am not very familiar with each of the many Java Swing Classes, and have ran into a stumbling block regarding the creation of a Table.
I am trying to figure out how to add a table to a Java Swing Program I am making. I have looked at docs.oracle.com to try and figure it out but I am getting an error when I try to access the values of the table. I will include my code to help show what I am currently trying to do and where the error is.
This is my code for making the table and the table model (I think the problem is that my table model is not working correctly):
/*Create the Table Entry*/
columnNames = new String[listoffields.size()+1];
columnNames[0] = "Record Number";
for(int a = 1; a < columnNames.length;a++){
columnNames[a] = listoffields.get(a-1).getTitle();
}
int count = 1;
data = new Object[numrecords][listoffields.size()+1];
for(int a = 0; a < numrecords;a++){
for(int b = 0; b < listoffields.size()+1;b++){
if(b == 0){
data[a][b] = count;
count++;
}
else{
data[a][b] = "";
}
}
}
/* create the table */
JTable table = new JTable(data,columnNames);
table.setCellSelectionEnabled(true);
table.setModel(new AbstractTableModel() {
public String getColumnName(int col) {
return columnNames[col].toString();
}
public int getRowCount() { return data.length; }
public int getColumnCount() { return columnNames.length; }
public Object getValueAt(int row, int col) {
return data[row][col];
}
public boolean isCellEditable(int row, int col) {
return (col >= 1);
}
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
});
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
/* addthe table to the JTable tableentry*/
tabelentry.setLayout(new BoxLayout(ProjectFrame.tabelentry, BoxLayout.Y_AXIS));
tabelentry.add(scrollPane);
tabelentry.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
After the table is displayed and I edit the blank values for each cell, I click a submit button that submits the cell. However, the following error is encountered:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Unknown Source)
at javax.swing.table.DefaultTableModel.getValueAt(Unknown Source)
at Client.GUIComponents.ProjectFrame$1.submit(NameOfFile.java:LineNumber)
The error is encountered when trying to submit as follows:
public void submit(){
String recordvalues = ""; //contains a String representation of what I want to submit
for(int a = 0; a < numberoffields;a++){
for(int b = 0; b < numberofrecords;b++){
if(a != 0){ //I want to skip the first column
recordvalues = recordvalues + (String) tabelentry.getModel().getValueAt(b, a) + ","; //The error is at this line in the code
}
}
}
}
I provided my code to give an example of the current problems I am encountering and what I have currently tried. To generalize my question, I am wondering how to correctly write a table model class so that I can access the values at each of the cells in the table. Any assistance would be helpful. Thanks a ton!
My immediate thought is that you're creating two different table models.
JTable table = new JTable(data,columnNames);
table.setCellSelectionEnabled(true);
table.setModel(new AbstractTableModel() {...
new JTable(data,columnNames) is actually creating it's own DefaultTableModel based on the information you are providing it. Try removing the table.setModel(new AbstractTableModel() {... code
The other, associated, problem is, I don't know how data and columnNames are declared.
Have a read through How to Use Tables for more details
Updated
The other problem, as pointed about by Hovercraft, is you adding one table to another and then accessing the wrong model.
The table creation should look more like...
tableEntry = new JTable(data,columnNames);
JScrollPane scrollPane = new JScrollPane(tableEntry );
tableEntry .setFillsViewportHeight(true);
// Don't forget to add the scroll pane to you view !!
Then you submit method should look more like...
public void submit(){
String recordvalues = ""; //contains a String representation of what I want to submit
TableModel model = tableEntry.getModel();
for(int a = 0; a < model.getColumnCount();a++){
for(int b = 0; b < model.getRowCount();b++){
if(a != 0){ //I want to skip the first column
recordvalues = recordvalues + (String) model.getValueAt(b, a) + ","; //The error is at this line in the code
}
}
}
}
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
This exception means that the column size of your table is 0, I think it's because you don't add columns into your TableModel.
Try to create several TableColumn Column = new TableColumn(); then add these columns to your table

Categories

Resources