Java. Swing. JScrollPane's JViewport size changed - java

I have a customText component in a JScrollPane. When the text is empty and there are no scrollbars, I can see all the text. But when the scrollbars become visible, some text is "hidden" behind these scrollbars.
Maybe I can listen to JViewPort size changes and set preferredsize for my text component?
JComponent component = getResTextArea();
component.setPreferredSize(RES_TEXT_AREA_PREFFERED_SIZE);
JScrollPane scrollPane = new JScrollPane(component);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.getVerticalScrollBar().setUnitIncrement(UNIT_INCREMENT);
panel.add(scrollPane);
I see how size of the viewport changes when text exceeds the panel's visible area and scrollbars being shown.
EDIT. My custom component is a subclass of JEditorPane.

The best way to implement this would be for your custom component to implement javax.swing.Scrollable, with getScrollableTracksViewportWidth() returning true. This will lock the width of your JComponent to the width of the viewport.

Related

JTextField stretches to fill BoxLayout.PAGE_AXIS

I have added a JTextField to a JPanel that is using BoxLayout.PAGE_AXIS.
I am then adding this panel to a content pane at BorderLayout.CENTER.
Right now my text field is stretching the entire width and height of BorderLayout.CENTER.
Is there a way to set a width and height of this text field without using a null layout? Or just somehow make it not stretch the entire width and height of BorderLayout.CENTER?
I see there is a JTextField.setMaximumSize(Dimension arg0); but I'm not sure what a Dimension is, or how to utilize it in this context.
Add a panel to the CENTER. Give the panel a layout that does not stretch component sizes (e.g FlowLayout). Add the text field to the flow layout.

How does a JLabel or JButton tell a JScrollPane that view size has changed?

How does a JLabel or JButton notify a JScrollPane that the view size has changed (for example when an icon has been set) so it can determine whether showing scrollbars are necessary?
How could I implement similar behaviour to display an image with a simple JPanel without resorting to the aforementionned components?
P.S: I've looked through the source code and so far all I see is that a Component is referred to as "view" and is passed on to a JView or JViewport which registers some listeners. From there on things seem unclear.
As noted in the JScrollPane API, unless you change the policy, "both horizontal and vertical scrollbars appear whenever the component's contents are larger than the view." Once pack() has sized the Window "to fit the preferred size and layouts of its subcomponents," any subsequent changes are seen by the scroll pane when the container is validated and repainted. See Painting in AWT and Swing for more.

How to prevent JScrollPane from automatically scrolling down?

I am using a JScrollPane which contains inside it a JTextArea. The problem is when the JTextArea is populated with a lot of text, the JScrollPane automatically scrolls down. What property should I set on the JScrollPane to avoid this automatic scrolling down? Thanks.
If the JScrollPane is decorating a text component, it will automatically scroll to the bottom, but after it loads calling setCaretPosition(0) on your text component will cause it to scroll to the top.
However, if it's not a text component, you can also alter the viewport like this:
scrollPane.getViewport().setViewPosition(new Point(0,0));

How to set only the preferred width of Panel with flow layout?

I have a panel with flow layout, and it can contain a variable number of items - from 1 to 2000. I want to put it inside a scroll pane, scrollable in vertical direction, and with fixed width. The problem is, when I set preferred size of panel to something like (800,600), some items are missing, and there is no scroll. If I set up preferred size of scroll pane, then all elements in flow pane are put on one very long line.
Setting maximum size on any element seems to do nothing at all - layout managers ignore it.
How can I fix this?
I want to put it inside a scroll pane, scrollable in vertical direction, and with fixed width
You can use the Wrap Layout for this.
Don't set the preferred size of the panel. But you can set the preferred size of the scroll pane so the frame.pack() method will work.
You could use BoxLayout to do this:
JPanel verticalPane = new JPanel();
verticalPane.setLayout(new BoxLayout(verticalPane, BoxLayout.Y_AXIS));
JScrollPane pane = new JScrollPane(verticalPane);
//add what you want to verticalPane
verticalPane.add(new JButton("foo"));
verticalPane.add(new JButton("bar"));
This of course will use the preferred size of each component added. If you want to modify the preferred size for example of a JPanel, extend it and override getPreferredSize:
class MyPanel extends JPanel(){
public Dimension getPreferredSize(){
return new Dimension(100,100);
}
}
A note: BoxLayout will take in consideration getPreferredSize, other LayoutManager may not.
Please criticize my answer, I'm not sure it's completely correct and I'm curious to hear objections in order to know if I understood the problem.

Scrollable flow panel

I need to create a panel where I can put some rectangles and it automatically reorder just inserting a scrollbar and growing up vertically. Also this panel can be resizable and again the rectangles must to be reordered to correctly be displayed inside the panel.
If I understand the question you want components to wrap to the next line so that the panel grows vertically while the width remains fixed.
If so then check out the WrapLayout
Note: the FlowLayout already supports the wrapping of components to a new row on the panel. This issue is that the preferred size calculation assumes all components are placed on a single row. The WrapLayout overrides the preferred size calculation to support the wrapping of components on a new row.
Use a JScrollPane. If you never want a horizontal scroll bar you can add the following:
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
(By default the scroll pane will add horizontal and vertical scroll bars when required.)
The scroll pane itself will only be resizeable if you add it to a Container with the appropriate layout manager; e.g.
JFrame frm = new JFrame();
frm.setLayout(new BorderLayout());
JScrollPane sp = new JScrollPane();
frm.add(sp, BorderLayout.CENTER); // Adding a component to the CENTER will cause the component to grow as the frame is resized.

Categories