Note that there are some explanatory texts on larger screens.

plurals
  1. POsetPreferredSize not working on panels when frame maximized on Windows XP?
    primarykey
    data
    text
    <p>I have overridden validate() in my JFrame so that I can manually control the size of a couple of nested JPanels (they're used in scrolling content onto the screen and no layout manager I know of lets you lay out components outside of the bounds of the parent container). This works fine when dragging the window to resize it, but when clicking the Maximize button, validate() gets called, the setPreferredSize()s get called, but the panel sizes don't update. Problem seen on XP, not seen in OSX.</p> <pre><code>public void validate() { super.validate(); LOGGER.debug("Validate called on Frame. Resizing panel"); if (inited == true) { Dimension size = panelLeft.getSize(); int referenceHeight = size.height; LOGGER.info("referenceHeight is " + referenceHeight); size = lower.getSize(); size.height = referenceHeight; lower.setPreferredSize(size); lower.setMinimumSize(size); size.height = size.height * 2; movingPanel.setPreferredSize(size); movingPanel.setMinimumSize(size); LOGGER.info("sizes now: panel: " + lower.getSize().height + ", scrollpane: " + movingPanel.getSize().height); if (panelSlideController != null) { panelSlideController.redraw(); LOGGER.debug("redrawing panel slide controller"); } } } </code></pre> <p>panelLeft is a panel which is auto-resized by its layout manager to be the full height of the frame. So its height is used as a reference.</p> <p>The relevant panels are arranged:</p> <pre><code> ---------------------------------- |scrollPane | | -------------------------------- | ||movingPanel || || ------------------------------ || |||upper ||| ||| ||| ||| ||| ||| ||| || ------------------------------ || || ------------------------------ || |||lower ||| ||| ||| ||| ||| ||| ||| || ------------------------------ || | -------------------------------- | ---------------------------------- </code></pre> <p>The user only sees the top half of this layout. The movingPanel JPanel is in the viewport of a JScrollPane. The goal is to keep the upper panel taking up all the visible vertical space, so is roughly the same height as the enclosing JFrame. The lower panel is ready to scroll on and is kept with the same height as upper panel. By keeping lower.height == panelLeft.height and movingPanel.height == panelLeft.heightx2, it means half of movingPanel is showing, and upper ends at the bottom of the Frame.</p> <p>Like I said, works fine. When dragging the window, some example output is:</p> <pre><code>2013-06-20 23:15:41,298 [WT-EventQueue-0] DEBUG s.billing.ui.Form - Validate called on Frame. Resizing panel 2013-06-20 23:15:41,298 [WT-EventQueue-0] INFO s.billing.ui.Form - newheight is 617 2013-06-20 23:15:41,298 [WT-EventQueue-0] INFO s.billing.ui.Form - sizes now: panel: 607, scrollpane: 1214 2013-06-20 23:15:41,538 [WT-EventQueue-0] DEBUG s.billing.ui.Form - Validate called on Frame. Resizing panel 2013-06-20 23:15:41,538 [WT-EventQueue-0] INFO s.billing.ui.Form - newheight is 640 2013-06-20 23:15:41,538 [WT-EventQueue-0] INFO s.billing.ui.Form - sizes now: panel: 636, scrollpane: 1272 </code></pre> <p>When maximizing the window, output is like:</p> <pre><code>2013-06-20 22:08:21,234 [WT-EventQueue-0] DEBUG s.billing.ui.Form - Validate called on Frame. Resizing panel 2013-06-20 22:08:21,234 [WT-EventQueue-0] INFO s.billing.ui.Form - newheight is 783 2013-06-20 22:08:21,234 [WT-EventQueue-0] INFO s.billing.ui.Form - sizes now: panel: 543, scrollpane: 1086 </code></pre> <p>I added the setMinimumSize in there to try to be more persuasive but it didn't help.</p> <p>Any thoughts very welcome</p> <p>EDIT: Added SSCCE</p> <pre><code>import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JViewport; import javax.swing.ScrollPaneConstants; import javax.swing.Timer; import javax.swing.UIManager; class Frame extends JFrame { private JPanel panelLeft; private JScrollPane scrollPane; private JPanel movingPanel; private JPanel upper; private JPanel lower; private boolean inited; private JLabel labelUpper; private JLabel labelLower; private JButton scrollBtn; private Frame.PanelSlideController panelSlideController; private JButton resizeBtn; private boolean lowerShowing = false; public Frame() { getContentPane().setLayout(new BorderLayout()); panelLeft = new JPanel(); panelLeft.setBackground(Color.CYAN); panelLeft.setPreferredSize(new Dimension(300, 400)); getContentPane().add(panelLeft, BorderLayout.WEST); labelUpper = new JLabel("upper"); panelLeft.add(labelUpper); labelLower = new JLabel("lower"); panelLeft.add(labelLower); resizeBtn = new JButton("resize"); resizeBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { doResize(); } }); panelLeft.add(resizeBtn); scrollBtn = new JButton("Scroll"); scrollBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { doScroll(); } }); panelLeft.add(scrollBtn); scrollPane = new JScrollPane(); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); movingPanel = new JPanel(new GridLayout(2, 1)); movingPanel.setOpaque(false); movingPanel.setPreferredSize(new Dimension(300, 400)); upper = new JPanel(); upper.setBackground(Color.YELLOW); movingPanel.add(upper); lower = new JPanel(); lower.setBackground(Color.RED); movingPanel.add(lower); scrollPane.setViewportView(movingPanel); getContentPane().add(scrollPane, BorderLayout.EAST); setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); inited = true; } /** * This is a manual step instead of overriding validate() */ protected void doResize() { // Get the height we want int referenceHeight = panelLeft.getSize().height; // Update the height of the lower panel to equal this Dimension size = lower.getSize(); size.height = referenceHeight; lower.setPreferredSize(size); lower.setMinimumSize(size); // Update the height of the surrounding panel size = scrollPane.getSize(); size.height = referenceHeight * 2; movingPanel.setPreferredSize(size); movingPanel.setMinimumSize(size); if (panelSlideController != null) { panelSlideController.redraw(); System.out.println("redrawing panel slide controller"); } upper.invalidate(); lower.invalidate(); scrollPane.revalidate(); } protected void doScroll() { panelSlideController = new PanelSlideController(scrollPane, 20); int scrollDirection = lowerShowing ? -1 : 1; panelSlideController.scrollY(panelLeft.getHeight() * scrollDirection); lowerShowing = !lowerShowing; } @Override public void validate() { super.validate(); System.out.println("Validating"); if (inited) { labelUpper.setText("upper: " + upper.getSize().height); labelLower.setText("lower: " + lower.getSize().height); } } class PanelSlideController implements ActionListener { private final JScrollPane scrollPane; private final int speed; private Timer timer; private int endPos; private boolean scrollingPositive; public PanelSlideController(JScrollPane scrollPane, int speed) { this.scrollPane = scrollPane; this.speed = speed; } public void scrollY(int scrollDistance) { endPos = scrollPane.getViewport().getViewPosition().y + scrollDistance; scrollingPositive = scrollDistance &gt; 0; timer = new Timer(speed, this); timer.start(); } public void redraw() { JViewport viewport = scrollPane.getViewport(); Point position = viewport.getViewPosition(); if (scrollingPositive) { position.y = endPos; } else { position.y = 0; } viewport.setViewPosition(position); } @Override public void actionPerformed(ActionEvent e) { JViewport viewport = scrollPane.getViewport(); Point position = viewport.getViewPosition(); int offset = scrollingPositive ? 10 : -10; position.y += offset; viewport.setViewPosition(position); if ((scrollingPositive &amp;&amp; position.y &gt;= endPos) || (!scrollingPositive &amp;&amp; (position.y &lt;= endPos || position.y &lt;= 0))) { timer.stop(); } } } public static void main(String[] args) { try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (Exception e) { e.printStackTrace(); } java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new Frame().setVisible(true); } }); } } </code></pre> <p>Right, so the above is runnable. panelLeft (cyan) is used as the reference height. I moved the code out of validate() and instead it's run by clicking resize button.</p> <p>So you can se the red panel (lower) should <em>not</em> be visible until scroll is clicked, at which point yellow scrolls up while red scroll into view. And then back again in the opposite direction. To do this, I need the yellow panel taking up all the vertical height and if I can do this with a layout manager then yay.</p> <p>I've updated the original snippet and the 'diagram' to mirror the names used in here.</p> <p>Thanks</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload