0

I have created a JTreeTable where the TreeCellRenderer is a JTable. This allows me to have different TableColumnModels for each row. Siblings of the JTree share a TableColumnModel. It works great. I can select a row and show a different set of columns without actually changing the the data in the other rows even at different levels.

I have a problem though where when select a different row the JTable is changing my TableColumns width and setting it to the preferred size. So the effect is that dragging the width of one column and then selecting a different row set it back to the preferred size.

I have tried a number of things to fix this, including adding a TableColumnModelListener and when I change the width I set the preferred size of the column. This doesn't work because the JTable is setting the preferred size to 15 after I change it.

I have traced the code back to what is causing this. It is the JTable.doLayout() method causing my grief. That method is calling the private method setWidthsFromPreferredWidths(...). This method is what is setting my TableColumn widths.

I tried overriding the doLayout() method since it is public but I could not make the call to super.doLayout() when I am already overriding the method. Not calling that causes some very weird UI issues as you could imagine. I also tried casting this to the superclass of JTable which is JComponent but I end up with a stack overflow error. This does not feel like the right solution here anyway.

What I think is happening is that because my JTable is inside of a panel as the renderer of a tree cell instead of inside of a scrollpane, that something is going wrong with the layout.I don't know for sure though. Below is the code inside of the private method I referenced above:

private void setWidthsFromPreferredWidths(final boolean inverse) {
    int totalWidth     = getWidth();
    int totalPreferred = getPreferredSize().width;
    int target = !inverse ? totalWidth : totalPreferred;

    final TableColumnModel cm = columnModel;
    Resizable3 r = new Resizable3() {
        public int  getElementCount()      { return cm.getColumnCount(); }
        public int  getLowerBoundAt(int i) { return cm.getColumn(i).getMinWidth(); }
        public int  getUpperBoundAt(int i) { return cm.getColumn(i).getMaxWidth(); }
        public int  getMidPointAt(int i)  {
            if (!inverse) {
                return cm.getColumn(i).getPreferredWidth();
            }
            else {
                return cm.getColumn(i).getWidth();
            }
        }
        public void setSizeAt(int s, int i) {
            if (!inverse) {
                cm.getColumn(i).setWidth(s);
            }
            else {
                cm.getColumn(i).setPreferredWidth(s);
            }
        }
    };

    adjustSizes(target, r, inverse);
}

Looking at the code, I think what's happening is that the getWidth() method is causing the JTable to want to resize the columns to the preferredsize because it thinks it doesn't have enough room. I tried just copy pasting this method locally but since there are private methods involved and it kept getting deeper and deeper I stopped that. The intention was to try to debug why it is choose to adjust the width. If I can address the root cause, that may be the best solution for this.

The JTree itself is inside of JScrollPane. The JTableHeader is set to the ViewPortColumnHeaderView. Below are 2 images where I am selecting different rows. Ignore the header alignment, I already have a solution for that just did not implement it entirely yet.

JTreeTable-Level1 JTreeTable-Level2

Any thoughts on the problem would be greatly appreciated. Also happy to post any code you think might be useful if you think it will help.

Mark
  • 911
  • 13
  • 30

1 Answers1

0

So after a lot of modifications and investigation, It was due not having a scrollpane for the tables. I didn't do that originally because it put a funky border around it and setting border to null did not work. What I had to do was set an empty border.

Mark
  • 911
  • 13
  • 30