Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unable to set column width after jtable becomes visible

I've read Oracle's API hundreds of times, read countless articles, both here and elsewhere, and i still cannot resize columns after the jtable becomes visible.

As you can deduce, i'm also trying to set the visibilty of the columns using jcheckboxes. Using addColumn and removeColumn, as other articles have noted, does not return columns to their original positions. I've previously used an additional class to hold column information eg the column itself, its identifier and original index. This became messy as well the problem of adding/removing data after a column's visibility has been changed. I noticed the data was not in its correct column. As a result, ive opted for setting the column's minWidth, preferredWidth and maxWidth.

Now to my problem, the below code does not adjust the column's width when setColumnVisible is set to true. In the words of julius summner miller, why is it so?

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

import java.util.*;

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

class run
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                Viewer viewer = new Viewer();

                JFrame jframe = new JFrame();
                jframe.add(viewer);
                jframe.createBufferStrategy(1); // required for dual monitor issues
                jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                jframe.setLocation(50,100);
                jframe.pack();
                jframe.setVisible(true);
            }
        });
    }
}

class Viewer extends JPanel
{
    static final long serialVersionUID = 0;

    DefaultTableModel defaultTableModel;
    JTable jtable;
    JCheckBox jcheckBox[];

    public Viewer()
    {
        this.setLayout(new BorderLayout());

        JPanel jpanel = new JPanel(new BorderLayout());

        String columnNames[] = {"a","b","c","d","e"};

        Object tableData[][] = 
        {
            {"a1","b1","c1","d1","e1"},
            {"a2","b2","c2","d2","e2"},
            {"a3","b3","c3","d3","e3"}
        };

        defaultTableModel = new DefaultTableModel(tableData,columnNames);

        jtable = new JTable(defaultTableModel);

        JScrollPane jscrollPane = new JScrollPane(jtable);

        jpanel.add(jscrollPane,BorderLayout.CENTER);

        TableColumnModel tableColumnModel = jtable.getColumnModel();

        int columnCount = tableColumnModel.getColumnCount();

        jcheckBox = new JCheckBox[columnCount];

        JPanel visibility = new JPanel(new GridLayout(1,columnCount));

        for (int column = 0; column < columnCount; column++)
        {
            TableColumn tableColumn = tableColumnModel.getColumn(column);

            String identifier = (String)tableColumn.getIdentifier();

            jcheckBox[column] = new JCheckBox(identifier,true);
            jcheckBox[column].setName(identifier);
            jcheckBox[column].addActionListener(new ColumnListener());

            visibility.add(jcheckBox[column]);
        }

        jpanel.add(visibility,BorderLayout.SOUTH);

        this.add(jpanel,BorderLayout.CENTER);
    }

    public void setColumnVisible(String identifier, boolean setVisible)
    {
        TableColumn tableColumn = jtable.getColumn(identifier);

        int minWidth = 0;
        int preferredWidth = 0;
        int maxWidth = 0;

        if (setVisible)
        {
            minWidth = 100;
            preferredWidth = 100;
            maxWidth = 100;
        }

        tableColumn.setMinWidth(minWidth);
        tableColumn.setPreferredWidth(preferredWidth);
        tableColumn.setMaxWidth(maxWidth);

        //jtable.doLayout(); does not work
        //jtable.validate(); does not work
        //jtable.getTableHeader().resizeAndRepaint(); does not work
    }

    class ColumnListener implements ActionListener
    {
        public void actionPerformed(ActionEvent actionEvent)
        {
            JCheckBox checkBox = (JCheckBox)actionEvent.getSource();

            boolean setVisible = checkBox.isSelected();

            String identifier = checkBox.getName();

            setColumnVisible(identifier,setVisible);
        }
    }
}



Addendum doLayout(), validate() resizeAndRepaint() does not work, nor does setting setAutoResizeMode to off.

Note: As some of you mayve found out, resizing does in fact work AFTER all the columns are hidden. However, it still doesnt answer my question as to why column sizes are not adjusted when invoking setMin, setPreferred and setMax.

Note: Im writing a font viewer that can display multiple font famlies, styles and sizes simultaneously. I have a jtable that display installed fonts (column1 displays the font family, column2 displays the alphabet in coresponding font and column3 displays digits(0-9) in the corresponding font.

The example code ive provided will be used to display the aboveforementioned, giving the user the option of hiding either the alphabet or digits.

I also have 6 jlist's, 3 of which contain available font families, styles and sizes, and the other 3 contain user selections. I use another jtable to display user selections (column1 selected font family, column2 font style, column3 font size, column4 alphabet, column5 digits, column6 punctuation and column7 symbols.

The user will be allowed to select which columns are visible. As ive mentioned though, when the display table is updated, the data is not where its supposed to be. ie the user chooses to hide columns, digits and symbols and then selects a new fonts, styles and size to be displayed.

like image 291
johnny Avatar asked Mar 18 '23 10:03

johnny


1 Answers

as i have pointed out, removing the table column not only adds complexity

I agree, and I gave you working code that manages this complexity. I see you didn't try the code even though it can be added to your program with a single line of code.

try adding and removing data from the table

That is not an issue. All a TableColumn does is map the data from the TableModel to the TableColumn. When you create a TableColumn, it is created with a default column value of 0. So yes, unless you manage this properly you will have a problem, which is why I gave you a link to working code.

my question as to why column sizes are not adjusted when invoking setMin, setPreferred and setMax.

The answer is that order of code execution is important. That is the preferred size must be in range of the min/max sizes, so you need to set the preferred size last:

    tableColumn.setMinWidth(minWidth);
    tableColumn.setMaxWidth(maxWidth);
    tableColumn.setPreferredWidth(preferredWidth);

Edit:

Simple example. You can call it an MCVE or a SSCCE.

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

public class Main
{
    public static void main(String[] args)
    {
        TableColumn tc = new TableColumn();
        tc.setMinWidth(1);
        tc.setMaxWidth(10);
        tc.setPreferredWidth(15);
        System.out.println( tc.getPreferredWidth() );
    }
}

If this does not verify that the API is working correctly, then I don't know what will.

like image 54
camickr Avatar answered Apr 02 '23 18:04

camickr