Java – JScrollPane resizes with variable size content
The contents of my resizable JScrollPane have a minimum width If the JScrollPane is less than this width, a horizontal scroll bar should be displayed If it is greater than this width, the viewport contents should be expanded to fill the entire viewport
It looks like a simple concept. I have some work, but it feels like a hacker:
import javax.swing.*; import java.awt.*; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; public class SSBTest { public static void main(String[] args) { SwingUtilities.invokelater(new Runnable() { public void run() { final Component view = new MyView(); final JScrollPane jScrollPane = new JScrollPane(view); jScrollPane.addComponentListener(new ComponentAdapter() { @Override public void componentResized(final ComponentEvent e) { final Dimension minimumSize = view.getMinimumSize(); final int width = Math.max(minimumSize.width,jScrollPane.getViewport().getWidth()); view.setPreferredSize(new Dimension(width,minimumSize.height)); } }); showInDialog(jScrollPane); } }); } private static void showInDialog(final JScrollPane jScrollPane) { final JDialog dialog = new JOptionPane(jScrollPane).createDialog("JScrollPane Resize Test"); dialog.setResizable(true); dialog.setModal(true); dialog.setVisible(true); Sy@R_502_2354@.exit(0); } private static final class MyView extends JPanel { @Override protected void paintComponent(final Graphics g) { super.paintComponent(g); g.setColor(Color.RED); g.drawString("Dimensions are " + getSize(),10,20); g.drawRect(0,getMinimumSize().width-1,getMinimumSize().height-1); g.setColor(Color.BLUE); g.drawRect(0,getPreferredSize().width-1,getPreferredSize().height-1); } @Override public Dimension getMinimumSize() { return new Dimension(200,200); } @Override public Dimension getPreferredSize() { return super.getPreferredSize(); } } }
Resizing the dialog box triggers componentlistener, which explicitly sets the preferred size of the viewport view and triggers component validation However, resizing causes the scroll bar to shake Is there a cleaner way to do this?
Editor: thanks to camickr's scrollablepanel link, I modified my JPanel class to implement scrollable and dynamically changed the return value of getscrollabletracksviewportwidth()
When the viewport is large, I return true to getscrollabletracksviewportwidth(), telling JScrollPane to fill the view with my components When the viewport is small, I return false, so the scroll bar appears
import javax.swing.*; import java.awt.*; public class SSBTest { public static void main(String[] args) { SwingUtilities.invokelater(new Runnable() { public void run() { final Component view = new MyView(); final JScrollPane jScrollPane = new JScrollPane(view); showInDialog(jScrollPane); } }); } private static void showInDialog(final JScrollPane jScrollPane) { final JDialog dialog = new JOptionPane(jScrollPane).createDialog("JScrollPane Resize Test"); dialog.setResizable(true); dialog.setModal(true); dialog.setVisible(true); Sy@R_502_2354@.exit(0); } private static final class MyView extends JPanel implements Scrollable { @Override protected void paintComponent(final Graphics g) { super.paintComponent(g); g.setColor(Color.RED); g.drawString("MyView: " + getWidth() + "x" + getHeight(),getPreferredSize().height-1); g.drawString("Preferred/Minimum Size",getPreferredSize().height/2); g.setColor(Color.GREEN); g.drawLine(0,getWidth(),getHeight()); } @Override public Dimension getMinimumSize() { return new Dimension(200,200); } @Override public Dimension getPreferredSize() { return getMinimumSize(); } public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } public int getScrollableUnitIncrement(final Rectangle visibleRect,final int orientation,final int direction) { return 10; } public int getScrollableBlockIncrement(final Rectangle visibleRect,final int direction) { return visibleRect.width; } public boolean getScrollableTracksViewportWidth() { final Container viewport = getParent(); return viewport.getWidth() > getMinimumSize().width; } public boolean getScrollableTracksViewportHeight() { return true; } } }
Solution
Not sure, but you may be able to use scrollable panel You can configure component resizing (try using stretch) The code applies to the preferred size of the component, not the minimum size, so it may not fully meet your requirements