3

I have a complex question I cant find an answer anywhere.

here is a example :

public static void main(final String[] args) {
    final JFrame frame = new JFrame("test");
    final JPanel bigPane = new JPanel(new GridLayout(0, 1));
    frame.setContentPane(new JScrollPane(bigPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));
    bigPane.add(new JTextField("reterterter ertertrert erterter ert"));
    bigPane.add(new JTextField(" ertertrert erterter ert"));
    bigPane.add(new JTextField("reterterter ertertrert  ert"));
    bigPane.add(new JTextField("reterterter ertertrert erterter "));
    frame.pack();
    frame.setSize(frame.getSize().width/2, frame.getSize().height);
    frame.setVisible(true);
}

Here, clearly the textfields are cut. More precisely, bigPane is cut. But I would like the textfields to be resized instead of cut, so we can still use them.

Since the horizontal scrollbar is forbidden to appear, I would like the layout to forget the view's (bigPane) preferred width and always force the view's width to match the viewport's width. Like there would be no virtual viewport for the horizontal direction, only in the vertical.

I can't find a solution to that, and not even a hack, thaks if you can help.

Nico.

PS: looks like the code for ViewportLayout doesn't contain any code for that

PS2 : here is a cap of the result of the above code http://www.nraynaud.com/kilombo/testLayout.png see the right side.

nraynaud
  • 4,924
  • 7
  • 39
  • 54
  • What do you mean by "I would like the text inside the textfields to be cut"? Do you want to limit length of the text? – Denis Tulskiy Aug 08 '09 at 16:26
  • here is what I want : http://www.nraynaud.com/kilombo/textcut.png (I did that by removing the scrollpane) here is what I get and don't want : http://www.nraynaud.com/kilombo/textfieldcut.png wich render the textfield unusable. – nraynaud Aug 08 '09 at 16:55
  • I don't understand the down votes on either of these answers. They both do what you want. – banjollity Aug 08 '09 at 21:05
  • not really, because they are narrow hacks, in real life I have other components in my columns, I want to be able to use the preferred size in some circumstances etc. I converted the points in upvotes because, in the exact precise case of my example, they work. But it's hardly a solution. – nraynaud Aug 08 '09 at 21:19
  • *"in the exact precise case of my example, they work. But it's hardly a solution"* - hmmm. If you are going to encourage people to help, down-voting working solutions isn't a great idea! – oxbow_lakes Aug 09 '09 at 12:06
  • yeah, that's why I upvoted in the end. But I'm not sure rewarding this kind of answer is the way to go either. The real problem for me, more that karma-whoring, is that I don't have a good solution to my problem. But now I have a better understanding of what I want, maybe one day I will find the courage to tweak ScrollPaneLayout#layoutContainer() to my taste, but right now, digging in a 300+ lines spagetti function is over my forces. – nraynaud Aug 09 '09 at 17:58

3 Answers3

4

I think the "correct" way to do this is to use the Scrollable interface:

public class ScrollPaneWidthTrackingPanel extends JPanel implements Scrollable {
    private static final long serialVersionUID = 1L;

    public ScrollPaneWidthTrackingPanel(LayoutManager layoutManager) {
        super(layoutManager);
    }

    public Dimension getPreferredScrollableViewportSize() {
        return getPreferredSize();
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
        return Math.max(visibleRect.height * 9 / 10, 1);
    }

    public boolean getScrollableTracksViewportHeight() {
        return false;
    }

    public boolean getScrollableTracksViewportWidth() {
        return true;
    }

    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
        return Math.max(visibleRect.height / 10, 1);
    }
}

Two lines of your code then have to change to:

final ScrollPaneWidthTrackingPanel bigPane = new ScrollPaneWidthTrackingPanel(new GridLayout(0, 1));
frame.setContentPane(new JScrollPane(bigPane));

And the components should always fill the entire width of the JScrollPane, whatever the size of the frame. This change has a side effect that the components will now not fill the height of the JScrollPane. To solve that add the following code to the top of the getScrollableTracksViewportHeight method:

if (getParent() instanceof JViewport) {
    JViewport viewport = (JViewport) getParent();
    return component.getPreferredSize().height < viewport.getHeight();
}
Russ Hayward
  • 5,617
  • 2
  • 25
  • 30
  • I really read the Scrollable javadoc too fast. Clearly, what I want is in public boolean getScrollableTracksViewportWidth() { return true; } Thank you, very much. – nraynaud Aug 10 '09 at 11:21
  • Technically I have swingx already used in my project, I will use a JXPanel and call panel.setScrollableTracksViewportHeight(false); on it. That will avoid the rest of the custom code. – nraynaud Aug 10 '09 at 20:54
1

Use the JTextField constructor which takes an int as a parameter. This is the number of visible characters in the text field. You can then use setText to initialize the contents of the field (if required).

Alternatively, set the maximum and preferred sizes (setMaximumSize, setMinimumSize) of the text fields appropriately.

oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449
  • none of those solutions address my problem I think. I want the current behaviour unaltered for the vertical part, so this rules out touching any size by hand. Setting the column number doesn't at all change the layout behaviour, it just indirectly changes the preferredSize. – nraynaud Aug 08 '09 at 13:53
  • I can't say that I understand what you want then. What exactly is the problem and what do you mean by "cut"? Is the frame appearing too wide? Not wide enough? What is the issue? – oxbow_lakes Aug 08 '09 at 14:47
  • when resizing down the frame, the fields are cut instead of resized. here is what I get : http://www.nraynaud.com/kilombo/textfieldcut.png here is what I want : http://www.nraynaud.com/kilombo/textcut.png – nraynaud Aug 08 '09 at 17:22
  • I'm sorry to say I'm still not sure what you mean! What is the difference between a "cut" field and a resized one? The only difference I can see between your 2 pictures is the vertical size of your text fields... Perhaps you are saying you want the whole fields to be smaller (including font-size etc)? If that's the case, you'll need to, um, change the font-size. This is not typical behaviour - if I make my browser smaller I don't end up with a miniature thumbnail of the web page! – oxbow_lakes Aug 08 '09 at 22:54
  • look at the right side of the pictures. Maybe you'll see the difference. It's complicated to show you the behaviour with a picture. – nraynaud Aug 09 '09 at 09:59
  • Ah yes, now I see it. What you mean is that you cannot see the full extent of the fields. I must say, I wouldn't normally use a scroll pane for anything other than displaying tables/lists. Do you *have* to use a scroll pane in this case? – oxbow_lakes Aug 09 '09 at 12:04
1

From the JavaDoc:

Parameters:
text - the text to be displayed, or null
columns - the number of columns to use to calculate the preferred width; if columns is set to zero, the preferred width will be whatever naturally results from the component implementation

Since you're calling the 0 constructor, you're getting the "whatever naturally results" implementation, which takes the lengths of your too-long strings. Simply calling the columns constructor, with a non-zero will fix this for you. Try these lines:

bigPane.add(new JTextField("reterterter ertertrert erterter ert",3));
bigPane.add(new JTextField(" ertertrert erterter ert",3));
bigPane.add(new JTextField("reterterter ertertrert  ert",3));
bigPane.add(new JTextField("reterterter ertertrert erterter ",3));

Here is a screenshot of the resulting pane:

alt text
(source: mcglashan.net)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
banjollity
  • 4,490
  • 2
  • 29
  • 32
  • I think I already answered that. This will destroy the preferred size purpose, and as an example destroy the JFrame.pack() intent. I don't want to change the preferred size (by hand), I would like the preferred width to be ignored in the computation of the view width in this particular case. – nraynaud Aug 08 '09 at 21:10