swingjframeawtjscrollpanejava-17

Java Swing - JFrame GUI Elements made invisble on resize and open


I have a secondary JFrame for a settings panel, however, whenever it is opened or resized all elements inside it (a lot of textfields, sliders and so forth) go invisible. I can get the GUI elements visible by clicking and dragging over them, so to me it sounds like a rendering order error / missing redraw call. But, the call is very much there (in setVisible()), it just doesn't help. Also the window is toggled from a button on a main window.

Here's an excerpt of the parts I'm quite sure is messing with me currently:

public class SettingsWindow{

    public SettingsWindow(int xW, int yH){
    frame = new JDialog();
    frame.setTitle("Generator Settings");
    frame.setBounds(0,0,xW,yH);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.addWindowListener(new WindowListener() {
            
            ...
        @Override
        public void windowClosing(WindowEvent e) {
            SettingsWindow.this.onClose();
        }
            ...
    });
    frame.addComponentListener(new ComponentAdapter()
    {
        public void componentResized(ComponentEvent evt) {
            setVisible(true);
        }
    });
    localConfig = new Config(); //Config auto-loads in parameters from a file
    addComponents(frame);

}

private void addComponents(JDialog frame) {
    JScrollPane scrollPane = new JScrollPane();
    scrollPane.setBounds(0,0,frame.getWidth(),frame.getHeight());
    scrollPane.createVerticalScrollBar();

    int heightOffset = frame.getHeight()/14;
    int i = 0;
    for(JComponent jc : localConfig.getModComp((int) (frame.getWidth() * 0.95), heightOffset)){   //config.getModComp() gets all the buttons and sliders needed, each in the size specified
        jc.setLocation(0,i * heightOffset);
        scrollPane.add(jc);
        i++;
    }

    scrollPane.setVisible(true);
    frame.add(scrollPane);
}

private void onClose() {
    setVisible(false);
}
public void toggle(){
    frame.setVisible(!isVisible);
    isVisible = !isVisible;        //class atribute
}
public void setVisible(boolean state){
    isVisible = state;         //class attribute
    frame.setVisible(state);
    for(Component jc : frame.getContentPane().getComponents()){
        jc.setVisible(state);
        jc.revalidate();
        jc.repaint();
    }
}

}

I've tried a lot of things, but none has worked so far. This was meant to be a quick, 10 min adventure into some generative patterns and stuff, but uh. I guess that didn't happen. Any suggestions are much appreciated.

Here's how it looks when I've dragged over all of the invisible components to make them appear: Generator Settings made visible

PS: None of the GUI components are special / anonymous sub-classes. All stock with a couple of ActionListeners on some of them.


Solution

  • scrollPane.add(jc);
    

    Don't add components directly to the scroll pane. Instead, a single component is added to the "viewport" of the scroll pane.

    So typically you would create a JPanel (using appropriate layout managers) and add the components to the panel and then create the scroll pane using this panel:

    JPanel panel = new JPanel(...);
    panel.add( component1 );
    panel.add( component2 );
    JScrollPane scrollPane = new JScrollPane( panel );
    ...
    dialog.add( scrollPane );