6

I will rephrase my question:**

How to prevent Java ScrollBar from being enabled in FlowLayout when there is enough space to show all items by warping them.

example**

Here a screenshot of what I am trying to achieve:

Note that scrollbar is disabled when it is not necessary. enter image description here

And when you resize the window scrollbar should appear if some items are out the viewplane enter image description here

P.S. I am aware of things called documentation and web.

Vitalij
  • 4,587
  • 9
  • 42
  • 65
  • 2
    *"What I currently have is:"* Uncompilable code snippets. For better help sooner, post an [SSCCE](http://sscce.org/). *"However compared to WPF, Java doesn't show and hide scrollbars when necessary"* Java must be broken, use WPF for this one. – Andrew Thompson Nov 15 '11 at 18:17
  • [Read the documentation](http://download.oracle.com/javase/tutorial/uiswing/components/scrollpane.html) – fireshadow52 Nov 15 '11 at 19:12
  • 1
    You may be looking for [Wrap Layout](http://tips4java.wordpress.com/2008/11/06/wrap-layout/). – trashgod Nov 16 '11 at 22:17
  • This looks like it is addressing the problem I am having. The only thing I do not understand is why FlowLayout doesn't do it by default? – Vitalij Nov 16 '11 at 23:10
  • I have to agree with @camickr, `FlowLayout` is a strange animal! In particular "When the components are wrapped to a new row, the preferred size doesn’t change so you never see the components on the extra row." – trashgod Nov 18 '11 at 01:54
  • It's a reach, but you may be able to leverage the `HORIZONTAL_WRAP` mode of `JList`, seen [here](http://stackoverflow.com/questions/7620579/individual-and-not-continuous-jtables-cell-selection/7620726#7620726). – trashgod Nov 18 '11 at 02:00
  • @trashgod, post your comment about Wrap Layout as an answer, to mark it as accepted. – Vitalij Nov 19 '11 at 17:56

3 Answers3

4

Your updated screen shots suggest that you may be looking for Wrap Layout, which "extends the FlowLayout" in a way that "will result in synchronizing the preferred size of the container with the layout of the container." See also Creating a Custom Layout Manager.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 1
    Unfortunately for me, that doesn't look very GPL friendly as there's no license, so that's no good for my project :-( – Tim Abell Sep 05 '12 at 22:45
  • 1
    Ah, found the relevant comment. "Rob Camick said January 12, 2012 at 10:46 am You can use/modify the code however you wish." Hurrah. – Tim Abell Sep 05 '12 at 22:51
  • It was such a royal pain removing the null character from the middle of the file that I created a copy at https://github.com/timabell/WrapLayout to save everyone the hassle. – Tim Abell Sep 06 '12 at 22:30
  • I am a little intrigued how it can be an intermittent issue but hey. I tried chromium, wget and curl and they all resulted in the corrupt file. Some editors seem to cope better than others with the null. – Tim Abell Sep 07 '12 at 21:38
3

The default scroll bar policy is as needed, but I remember having to account for the FlowLayout gaps to get an even number initially. If you stretch this example out, you'll see the horizontal scroll bar disappear.

Update: It doesn't really fix your problem, but it shows how I implemented Scrollable. I wanted to get rid of setPreferredSize(), even tho' the image is just a placeholder. The Wrap Layout article talks about why FlowLayout works the way it does.

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

public class ImageScrollTest extends JPanel implements Scrollable {

    private static final int N = 8;
    private static final int W = 120;
    private static final int H = 100;
    private final FlowLayout layout = new FlowLayout();
    private final int hGap = layout.getHgap();
    private final int vGap = layout.getVgap();
    private final Dimension size;

    // Show n of N images in a Scrollable FlowLayout
    public ImageScrollTest(int n) {
        setLayout(layout);
        for (int i = 0; i < N; i++) {
            this.add(new ImagePanel());
        }
        size = new Dimension(n * W + (n + 1) * hGap, H + 2 * vGap);
    }

    @Override
    public Dimension getPreferredScrollableViewportSize() {
        return size;
    }

    @Override
    public int getScrollableUnitIncrement(
        Rectangle visibleRect, int orientation, int direction) {
        return getIncrement(orientation);
    }

    @Override
    public int getScrollableBlockIncrement(
        Rectangle visibleRect, int orientation, int direction) {
        return getIncrement(orientation);
    }

    private int getIncrement(int orientation) {
        if (orientation == JScrollBar.HORIZONTAL) {
            return W + hGap;
        } else {
            return H + vGap;
        }
    }

    @Override
    public boolean getScrollableTracksViewportWidth() {
        return false;
    }

    @Override
    public boolean getScrollableTracksViewportHeight() {
        return false;
    }

    private static class ImagePanel extends JPanel {

        private static final Random rnd = new Random();
        private Color color = new Color(rnd.nextInt());

        public ImagePanel() {
            this.setBackground(color);
            this.setBorder(BorderFactory.createLineBorder(Color.blue));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(W, H);
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ImageScrollTest ist = new ImageScrollTest(N / 2);
        JScrollPane sp = new JScrollPane(ist);
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        f.add(sp);
        f.pack();
        f.setVisible(true);
    }
}
Community
  • 1
  • 1
Catalina Island
  • 7,027
  • 2
  • 23
  • 42
  • This is a good example +1. That is exactly what I have. The problem is that I want the wrap panel to wrap items as long as there is some available space and if there is none, only the show the scroll bars. – Vitalij Nov 16 '11 at 15:57
  • no, you do not have to "take gaps into account" - that's the job of the layoutManager. Do not use setXXSize - ever. Instead, let your panel/s return reasonable calculated size hints in their respective getXXSize method http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi – kleopatra Nov 16 '11 at 16:32
  • It is possibly true about setXXSize, but it is not a point of the discussion. – Vitalij Nov 16 '11 at 16:38
  • @Vitalij: Now that I see your update, `WrapLayout` looks like the right answer. – Catalina Island Nov 17 '11 at 15:55
  • @kleopatra: You're right; I was lazy on the preferred size. I ysed the gaps to implement `Scrollable` in my update. Is that wrong? – Catalina Island Nov 17 '11 at 15:58
0

You shoud specify to the scrollPane when you want the scrollBars to apprear (possible in both horizontal and vertical direction):

myScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

There is also: HORIZONTAL_SCROLLBAR_ALWAYS and HORIZONTAL_SCROLLBAR_NEVER if you need that anytime soon.

EDIT: For more information, and exactly my answer: http://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html

Hidde
  • 11,493
  • 8
  • 43
  • 68
  • I have already tried this. For some reasons Java doesn't hide scroolbar in FlowLayout – Vitalij Nov 16 '11 at 15:52
  • Well, is the width of all the content larger than the window? Post some code, we can't help you more by guessing... – Hidde Nov 16 '11 at 16:01
  • What I am getting is exactly as posted by @Catalina Island – Vitalij Nov 16 '11 at 16:09
  • Nope it doesn't it shows the scrollbar all the time. But what I am trying to achieve is to show a scrollbar only when it is needed. And by as needed, I mean that if wrap panel can wrap items instead of showing a scrollbar it should do so. – Vitalij Nov 16 '11 at 16:37
  • OK, so please post some code, probably the JFrame creation, so we can see where the problem is... – Hidde Nov 16 '11 at 21:18