1

I noticed an issue with the setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED) resizes the height content when the scrollbar gets added (due to the content going over the width).

The Code...

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;

public class TestGui extends JFrame {
    //**************************************************************************************
    //************************************* Constructor ************************************
    //**************************************************************************************
    private TestGui() {
        add(createTopScrollPane(), BorderLayout.NORTH);
        add(createCenterScrollPane(), BorderLayout.CENTER);

        setSize(800,600);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    //**************************************************************************************
    //*********************************** Support Method ***********************************
    //**************************************************************************************
    private static GridBagConstraints setGbc(int gridx, int gridy, int gridWidth, int gridHeight, int ipadx, int ipady, String anchorLocation, double weightx, double weighty, Insets insets, boolean fillCell){
        GridBagConstraints gbc = new GridBagConstraints();

        if (anchorLocation.toUpperCase().equals("NORTHWEST")){
            gbc.anchor = GridBagConstraints.NORTHWEST;
        } else if (anchorLocation.toUpperCase().equals("NORTH")){
            gbc.anchor = GridBagConstraints.NORTH;
        } else if (anchorLocation.toUpperCase().equals("NORTHEAST")){
            gbc.anchor = GridBagConstraints.NORTHEAST;
        } else if (anchorLocation.toUpperCase().equals("WEST")){
            gbc.anchor = GridBagConstraints.WEST;
        } else if (anchorLocation.toUpperCase().equals("EAST")){
            gbc.anchor = GridBagConstraints.EAST;
        } else if (anchorLocation.toUpperCase().equals("SOUTHWEST")){
            gbc.anchor = GridBagConstraints.SOUTHWEST;
        } else if (anchorLocation.toUpperCase().equals("SOUTH")){
            gbc.anchor = GridBagConstraints.SOUTH;
        } else if (anchorLocation.toUpperCase().equals("SOUTHEAST")){
            gbc.anchor = GridBagConstraints.SOUTHEAST;
        } else {
            gbc.anchor = GridBagConstraints.CENTER;
        }

        gbc.gridx = gridx; // column
        gbc.gridy = gridy; // row
        gbc.gridwidth = gridWidth; // number of columns
        gbc.gridheight = gridHeight; // number of rows
        gbc.ipadx = ipadx; // width of object
        gbc.ipady = ipady; // height of object
        gbc.weightx = weightx; // shifts columns to side of set anchor
        gbc.weighty = weighty; // shifts rows to side of set anchor
        gbc.insets = insets; // placement inside cell
        if (fillCell){
            gbc.fill = GridBagConstraints.BOTH;
        }

        return gbc;
    }

    //**************************************************************************************
    //************************************ Panel Methods ***********************************
    //**************************************************************************************
    private JPanel createTopFrame() {
        JPanel pnl = new JPanel();

        Border lineBorder = BorderFactory.createMatteBorder(0, 0, 0, 5, Color.BLUE);
        JLabel lineSplitter = new JLabel();
        lineSplitter.setBorder(lineBorder);

        pnl.setLayout(new GridBagLayout());
        pnl.add(new JLabel("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),setGbc(0,0, 1,1, 0,0,"CENTER", 0, 0, new Insets(10, 10, 10, 10), false));
        pnl.add(new JLabel("XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),setGbc(0,1, 1,1, 0,0,"CENTER", 0, 0, new Insets(10, 10, 10, 10), false));
        pnl.add(lineSplitter, setGbc(1,0,1,2,0,0,"CENTER",0,0,new Insets(0,0,0,0),true));
        pnl.add(new JLabel("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),setGbc(2,0, 1,1, 0,0,"CENTER", 0, 0, new Insets(10, 10, 10, 10), false));
        pnl.add(new JLabel("XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"),setGbc(2,1, 1,1, 0,0,"CENTER", 0, 0, new Insets(10, 10, 10, 10), false));

        return pnl;
    }

    private JScrollPane createTopScrollPane(){
        JScrollPane scrollPane = new JScrollPane();
        Border raisedBevel = BorderFactory.createRaisedBevelBorder();
        Border lineBorder = BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(224,224,224));
        Border loweredBevel = BorderFactory.createLoweredBevelBorder();
        Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder);
        Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel);

        //scrollPane.setPreferredSize(new Dimension(0, 160));
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
        scrollPane.setBorder(compoundFinal);
        scrollPane.getViewport().setView(createTopFrame());
        return scrollPane;
    }

    private JScrollPane createCenterScrollPane(){
        JScrollPane scrollPane = new JScrollPane();
        Border raisedBevel = BorderFactory.createRaisedBevelBorder();
        Border lineBorder = BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(224,224,224));
        Border loweredBevel = BorderFactory.createLoweredBevelBorder();
        Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder);
        Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel);

        scrollPane.setBorder(compoundFinal);
        return scrollPane;
    }

    //**************************************************************************************
    //************************************ Start Program ***********************************
    //**************************************************************************************
    public static void main(String[] args) {
        new TestGui();
    }
}

Note: If I use setPreferredSize, it adds spacing between borders when maximizing the window, and I don't want that.

As you can see, the 2nd row gets cut off, is there anyway to have it not resize (other than setting it to HORIZONTAL_SCROLLBAR_ALWAYS, which still shows the bar if you maximize the window)?

Fiddle Freak
  • 1,923
  • 5
  • 43
  • 83

1 Answers1

2

You need to override the methothd getPreferredSize() of your scroll pane. Also you need provide revalidation when component changed.

private TestGui() {
    add(createTopScrollPane(), BorderLayout.NORTH);
    add(createCenterScrollPane(), BorderLayout.CENTER);
    addComponentListener(new ComponentAdapter() {
        @Override
        public void componentResized(ComponentEvent e) {
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    revalidate();
                    repaint();
                }
            });
        }
    });

    setSize(800,600);
    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

// another stuff

private JScrollPane createTopScrollPane(){
    JScrollPane scrollPane = new JScrollPane() {
        @Override
        public Dimension getPreferredSize() {
            Dimension size = super.getPreferredSize();
            if (getHorizontalScrollBar() != null && getHorizontalScrollBar().isVisible()) {
                size.height += getHorizontalScrollBar().getHeight();
            }
            return size;
        }
    };
    Border raisedBevel = BorderFactory.createRaisedBevelBorder();
    Border lineBorder = BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(224,224,224));
    Border loweredBevel = BorderFactory.createLoweredBevelBorder();
    Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder);
    Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel);

    //scrollPane.setPreferredSize(new Dimension(0, 160));
    scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
    scrollPane.setBorder(compoundFinal);
    scrollPane.getViewport().setView(createTopFrame());
    return scrollPane;
}
Sergiy Medvynskyy
  • 11,160
  • 1
  • 32
  • 48
  • The issue is still happening when I maximize the GUI, a space is created between the grid border line, and the JScrollPane border. Any idea how to stop that from happening? – Fiddle Freak May 11 '17 at 13:24
  • In addtion, clicking restore down (after maximize), the cut off happens again on the 2nd row. Also, thank you for trying to help with this... I'm sure the answer lies somewhere in what happens with that override, but I'm not sure how to handle the changes with the scroll bar. – Fiddle Freak May 11 '17 at 13:30
  • @FiddleFreak Yes, you are right. Looks like a problem on revalidation. I've added a workaround. – Sergiy Medvynskyy May 11 '17 at 14:34
  • This works perfectly thanks! There is just one thing. On my actual application, I have a squiggly line under `revalidate();` The application runs fine, and I get no compile or runtime error. It just bothers me that it is there. Intellij says "Usage of API documented as @since1.7 | This inspection finds all usages of methods have @since tag in their documentation | This may be useful when development is performed under newer SDK version as the target platform for production". I'm not sure what this means... – Fiddle Freak May 11 '17 at 14:59
  • As for the squiggly line warning, I found a relevant topic here > http://stackoverflow.com/questions/38551978/usage-of-api-documented-as-since1-6. The issue is I don't see that setting, and when I try to use #9, i get a compilation error. I suppose I'll have to do some more digging if I want it to go away. – Fiddle Freak May 11 '17 at 15:14
  • Alright I solved the issue with the squiggly line. Go to File > Project Structure > Project Settings > Project > Project Language Level... Select "SDK Default(...)". And yes camickr, I was going to do that as soon as I solved the squiggly line issue. Thanks. – Fiddle Freak May 11 '17 at 15:35