2

I'm making a GUI for a a custom source server browser with improved filtering.

This is what I have so far.

However, when I resize...

When I resize the window I want the L4D2 'filter panel' to resize to the current maximum width of the container. I also want to be able to add more of these panels in a column (such as box layout provides).

Boxlayout get's the panels to appear in a column, but it doesn't do anything for their widths. I'm thinking I may need to override the filter panels preferred size methods so that they can retrieve the size of the parent container, but I'm not sure how to do this.

How should I approach this problem?

EDIT: Here's an example program depicting the problem.

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

public class guiExampleProblem {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final MyWindows wnd = new MyWindows("guiExampleProblem");
                wnd.setVisible(true);
            }
        });
    }
}

class MyWindows extends JFrame {
    public MyWindows(String text) {
        super(text);

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);        

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));        

        JPanel containerPanel1 = new JPanel();
        JPanel containerPanel2 = new JPanel();
        JPanel containerPanel3 = new JPanel();
        containerPanel1.setBackground(Color.BLACK);
        containerPanel2.setBackground(Color.RED);
        containerPanel3.setBackground(Color.GREEN); 

        mainPanel.add(containerPanel1);
        mainPanel.add(containerPanel2);
        mainPanel.add(containerPanel3);

        this.add(mainPanel);
        pack();
    }   
}

When the window is resized, I want the panels to expand only along the x-axis, and remain at a constant height on the y-axis, however in the example the panels expand on both the x y axis.

tommy
  • 21
  • 3

2 Answers2

0

Put the panel (with BoxLayout) that is to stretch in the CENTER of a BorderLayout -- put the panel to the right in the EAST of that BorderLayout. You have given no detail of what else you want this to do, nor any code, but this might be what you want.

--

After your solution: it seems to me that using FlowLayout here is confusing -- it lays out its components one after the other horizontally, and your trick of getting preferred size from the width of the container makes it behave differently. I also avoid getting into layout logic in my application when I can, so I looked for another way to do this and came up with:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class guiExampleProblem2
{
  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new Runnable()
    {
      @Override
      public void run()
      {
        final MyWindows2 wnd = new MyWindows2("guiExampleProblem2");
        wnd.setVisible(true);
      }
    });
  }
}

class MyWindows2 extends JFrame
{
  public MyWindows2(String text)
  {
    super(text);

    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));

    JPanel containerPanel1 = addContainedPanel(Color.BLACK, 60, 60, mainPanel);
    JPanel containerPanel2 = addContainedPanel(Color.RED,   60, 60, mainPanel);
    JPanel containerPanel3 = addContainedPanel(Color.GREEN, 60, 60, mainPanel);

    this.add(mainPanel, BorderLayout.NORTH);

    pack();
  }

  JPanel addContainedPanel(Color color, int width, int height, JPanel container)
  {
    JPanel panel = new JPanel();
    panel.setPreferredSize(new Dimension(width, height));
    panel.setBackground(color);
    container.add(panel);
    return panel;
  }
}

This uses the NORTH portion of a BorderLayout (which is the default layout for a JFrame, by the way) to do the main thing you wanted -- stretch things horizontally. The BoxLayout with a page axis is intended to lay things out top-to-bottom, so I think that's less confusing for the reader. Anyway, it's another way to do it that I think uses the components - including the layout managers - more like they were intended and documented.

arcy
  • 12,845
  • 12
  • 58
  • 103
0

I managed to get the desired functionality by overriding the 'filter panels' getPrefferedSize methods so that they retrieve the parent containers width and use that. Here is the code in the form of an example:

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

public class guiExampleProblem {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final MyWindows wnd = new MyWindows("guiExampleProblem");
                wnd.setVisible(true);
            }
        });
    }
}

class MyWindows extends JFrame {
    public MyWindows(String text) {
        super(text);

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);        

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new FlowLayout());      


        JPanel containerPanel1 = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(this.getParent().getWidth(),60);
            }
        };
        JPanel containerPanel2 = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(this.getParent().getWidth(),60);
            }
        };
        JPanel containerPanel3 = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(this.getParent().getWidth(),60);
            }
        };
        containerPanel1.setBackground(Color.BLACK);
        containerPanel2.setBackground(Color.RED);
        containerPanel3.setBackground(Color.GREEN); 

        mainPanel.add(containerPanel1);
        mainPanel.add(containerPanel2);
        mainPanel.add(containerPanel3);


        this.add(mainPanel);
        pack();
    }   
}
tommy
  • 21
  • 3
  • bad idea - sizing hints are expected to return sizes based on content (and/or children), not on parents. Doing the latter might give unexpected results or even hang an application. As BoxLayout respects a component's maxSize, the way to go is to override the getMaxSize to return some limit for the height. – kleopatra Jan 23 '14 at 14:07