Set Column Width of JTable by Percentage

后端 未结 5 1887
傲寒
傲寒 2020-12-31 20:53

I need to assign a fixed width to a few columns of a JTable and then an equal width to all the other columns.

Suppose a JTable has 5 column

5条回答
  •  天涯浪人
    2020-12-31 21:30

    It think it would be easier to use (and re-use) relative component resizing if we encapsulate it in an own class. Since I also was confronted with the same issue, I would like to post my code here.

    From a client perspective I would like to do something like this

    TableColumnModel columnModel = jTable.getColumnModel();
    
    TableColumn firstColumn = columnModel.getColumn(0);
    TableColumn secondColumn = columnModel.getColumn(1);
    
    ComponentResize columnResize = new TableColumnResize();
    RelativeWidthResizer relativeWidthResizer = new RelativeWidthResizer(columnResize);
    
    relativeWidthResizer.setRelativeWidth(firstColumn, 0.8);
    relativeWidthResizer.setRelativeWidth(secondColumn, 0.2);
    
    jTable.addComponentListener(relativeWidthResizer);
    

    So I first defined the ComponentResize interface and implement a TableColumnResize

    public interface ComponentResize {
        public void setWidth(T component, int width);
    }
    
    public class TableColumnResize implements ComponentResize {
    
        public void setWidth(TableColumn component, int width) {
            component.setPreferredWidth(width);
        }
    }
    

    The ComponentResize interface decouples the way a component's size is set from the concrete APIs. E.g. a TableColumn's width can be set via setPreferredWidth(int) while a JComponent's size can be set by setPreferredWidth(Dimension)

    Than I implemented the RelativeWidthResizer that encapsulates the relative width calculation logic.

    public class RelativeWidthResizer extends ComponentAdapter {
    
        private Map relativeWidths = new HashMap();
        private ComponentResize componentResize;
    
        public RelativeWidthResizer(ComponentResize componentResize) {
            this.componentResize = componentResize;
        }
    
        public void setRelativeWidth(T component, double relativeWidth) {
            if (relativeWidth < 0.0) {
                throw new IllegalArgumentException(
                        "Relative width must be greater or equal to 0.0");
            }
    
            if (relativeWidth > 1.0) {
                throw new IllegalArgumentException(
                        "Relative width must be less or equal to 1.0");
            }
    
            double totalRelativeWidth = 0.0;
            for (Double relativeComponentWidth : relativeWidths.values()) {
                totalRelativeWidth += relativeComponentWidth.doubleValue();
            }
    
            double availableRelativeWidth = 1.0d - (totalRelativeWidth + relativeWidth);
    
            boolean totalPercentageExceeded = availableRelativeWidth < 0;
            if (totalPercentageExceeded) {
                double remainingRelativeWidth = 1.0d - totalRelativeWidth;
                String message = MessageFormat.format(
                        "Can't set component's relative width to {0}."
                                + " {1} relative width remaining", relativeWidth,
                        remainingRelativeWidth);
                throw new IllegalArgumentException(message);
            }
    
            relativeWidths.put(component, relativeWidth);
        }
    
        @Override
        public void componentResized(ComponentEvent e) {
            Component component = e.getComponent();
            apply(component);
        }
    
        public void apply(Component baseComponent) {
            Dimension size = baseComponent.getSize();
            int maxWidth = (int) size.getWidth();
    
            int remaining = maxWidth;
    
            Set> entrySet = relativeWidths.entrySet();
            Iterator> entrySetIter = entrySet.iterator();
    
            while (entrySetIter.hasNext()) {
                Entry componentEntry = entrySetIter.next();
                T componentToResize = componentEntry.getKey();
                Double relativeWidth = componentEntry.getValue();
    
                int width = (int) (maxWidth * relativeWidth.doubleValue());
                remaining -= width;
    
                boolean lastComponent = !entrySetIter.hasNext();
                if (lastComponent && remaining > 0) {
                    width += remaining;
                }
                componentResize.setWidth(componentToResize, width);
            }
        }
    }
    

提交回复
热议问题