Results 1 to 5 of 5
  1. #1
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    3,864
    Rep Power
    8

    Default GridLayout but with Max Heights?

    Hey all,

    I'm trying to build a JFrame that contains a single column of multiple JScrollPanes. Components can be dynamically inserted into these JScrollPanes, and the following should happen:

    If the JFrame is below some max height, the JFrame grows to show the newly added component.
    If the JFrame has already reached the max height, the JScrollPanes should share the height of the JFrame equally.

    However, if one of the JScrollPanes only has, say, 3 components in it, and another has 45 components in it, then the JScrollPane that only has 3 should not have the same height as the JScrollPane with 45 components in it.

    In other words, the JScrollPanes should expand to share the height of the JFrame equally with the other JScrollPanes, but none of them should go over their maximum height.

    I've tried using a BoxLayout, but it respects the preferred sizes of the JScrollPanes too much- if one JScrollPane has 20 components and another has 100 components in it, the second JScrollPane will be 5 times larger than the first, even though they should be the same height. GridLayout seems to almost do what I want, except it completely ignores the max size of the JScrollPanes.

    I feel like there must be some standard Swing approach to this, but I'm having a bit of trouble finding it. Any suggestions are much appreciated!

    Here is an SSCCE that might help explain my issue better:

    Java Code:
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.BoxLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    
    
    public class LayoutTest {
    
    	static final int LABEL_HEIGHT = 20;
    	static final int MAX_FRAME_HEIGHT = 300;
    	static final int FRAME_WIDTH = 200;
    	
    	//add components to this
    	static ScrolledPanel lastScrolledPanel;
    	
    	public static class ScrolledPanel{
    		
    		static int count = 0;
    		
    		JPanel scrolledPanel = new JPanel();
    		JScrollPane scrollPane = new JScrollPane(scrolledPanel);
    		
    		public ScrolledPanel(){
    			count++;
    			
    			scrolledPanel.setLayout(new BoxLayout(scrolledPanel, BoxLayout.Y_AXIS));
    			
    			JLabel label = new JLabel("Scroll Panel " + count);
    			scrolledPanel.add(label);
    		}
    		
    		public void add(){
    			scrolledPanel.add(new JLabel("Test 1"));
    			scrolledPanel.add(new JLabel("Test 2"));
    			
    			scrolledPanel.revalidate();
    			
    			scrollPane.setMaximumSize(new Dimension(FRAME_WIDTH, scrolledPanel.getPreferredSize().height));
    		}
    	}
    	
    	public static void main(String... args){
    		
    		final JFrame frame = new JFrame("Layout Test");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		
    		final JPanel contentPane = new JPanel();
    		contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
    		
    		frame.setContentPane(contentPane);
    		
    		frame.setSize(FRAME_WIDTH, 60);
    		frame.setVisible(true);
    		
    		lastScrolledPanel = new ScrolledPanel();
    		contentPane.add(lastScrolledPanel.scrollPane);
    		
    		
    		//used for testing
    		JFrame buttonFrame = new JFrame("Layout Test");
    		buttonFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		
    		//add a new JScrollPane
    		JButton addPanel = new JButton("Add Panel");
    		addPanel.addActionListener(new ActionListener(){
    
    			@Override
    			public void actionPerformed(ActionEvent e) {
    				lastScrolledPanel = new ScrolledPanel();
    				contentPane.add(lastScrolledPanel.scrollPane);
    				contentPane.revalidate();
    				
    				frame.setSize(frame.getWidth(), Math.min(frame.getHeight()+LABEL_HEIGHT, MAX_FRAME_HEIGHT));
    			}
    			
    		});
    		
    		//add components to the last added JScrollPane
    		JButton addComponent = new JButton("Add Component");
    		addComponent.addActionListener(new ActionListener(){
    
    			@Override
    			public void actionPerformed(ActionEvent e) {
    				lastScrolledPanel.add();
    				contentPane.revalidate();
    				
    				frame.setSize(frame.getWidth(), Math.min(frame.getHeight()+LABEL_HEIGHT*2, MAX_FRAME_HEIGHT));
    			}
    		});
    		
    		buttonFrame.add(addPanel, BorderLayout.WEST);
    		buttonFrame.add(addComponent, BorderLayout.EAST);
    		
    		buttonFrame.setSize(300, 150);
    		buttonFrame.setLocation(200,  0);
    		buttonFrame.setVisible(true);
    		
    	}	
    }
    How to Ask Questions the Smart Way
    Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!

  2. #2
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,669
    Rep Power
    5

    Default Re: GridLayout but with Max Heights?

    wow that is a whopper of a requirement. The first thing that pops into my head is that you need a layout manager that supports weights because the number of components in a scrollpane influences how much "priority" it should have.

    But that is as far as I get, probably Rob or Darryl have actual suggestions. Speaking of which: have you checked the tips4java repository for anything that might match your needs?

    Java Tips Weblog
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  3. #3
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    3,864
    Rep Power
    8

    Default Re: GridLayout but with Max Heights?

    Yeah, my first reaction to this was "this is a dumb requirement", but that decision is above my pay grade.

    I tried using BoxLayout and setting the max heights by weight, but that's not exactly the requirement. For example, say the JFrame's max height is equal to 20 components, and that JFrame contains two JScrollPanes. One JScrollPane contains 40 components, and another contains 80. In this case GridLayout would do exactly the right thing, split it so each JScrollPane has the same height, 50% of the JFrame, each showing 10 components.

    However, the flip side is where it gets complicated: say one JScrollPane contains 3 components, and another contains 40. In this case, they shouldn't still both be the same height: the JScrollPane with 3 components should only show those 3, and the other should fill the rest of the JFrame (showing 17 of its components at a time). In this case BoxLayout seems to work a little better, but then it breaks for the first example.

    I've seen the Java Tips Weblog, but I haven't specifically searched for this problem. I'll do that now, thanks for the reminder.
    How to Ask Questions the Smart Way
    Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!

  4. #4
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,233
    Rep Power
    7

    Default Re: GridLayout but with Max Heights?

    I would guess the BoxLayout is your best bet. You would probably need to override the getMaximumSize() method of the scrollPane to be calculated dynamically based on the number of components in the panel.

    If you can't get it to work using a standard layout manager then you will need to write your own to incorporate your specific requirements.

  5. #5
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    3,864
    Rep Power
    8

    Default Re: GridLayout but with Max Heights?

    Quote Originally Posted by camickr View Post
    I would guess the BoxLayout is your best bet. You would probably need to override the getMaximumSize() method of the scrollPane to be calculated dynamically based on the number of components in the panel.
    Thanks Rob. I thought about that too, although it's not as simple as say, dividing the height of the JFrame by the number of JScrollPanes, or weighting the height of each JScrollPane by the number of components it contains. The height of each JScrollPane depends on not only the height of the JFrame, but also the height of the other JScrollPanes. I was hoping I was missing something obvious, but I guess not!

    Quote Originally Posted by camickr View Post
    If you can't get it to work using a standard layout manager then you will need to write your own to incorporate your specific requirements.
    Yeah, a more top-down approach might be necessary. That's what I was afraid of, but I guess they wouldn't pay me if this stuff was easy!
    How to Ask Questions the Smart Way
    Static Void Games - Play indie games, learn from game tutorials and source code, upload your own games!

Similar Threads

  1. JPanel widths/heights
    By jasonw749 in forum AWT / Swing
    Replies: 2
    Last Post: 05-22-2013, 08:06 PM
  2. help! Gridlayout
    By eiramae in forum Java Applets
    Replies: 3
    Last Post: 02-19-2011, 05:11 AM
  3. SWT GridLayout
    By Java Tip in forum Java Tip
    Replies: 0
    Last Post: 01-08-2008, 09:04 AM
  4. Gridlayout
    By Marty in forum AWT / Swing
    Replies: 2
    Last Post: 05-31-2007, 11:48 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •