Java Swing - JScrollPane fit Viewport width to JScrollPane width - java

I have been trying to make the content of a JScrollPane shrink in width, eg. i have set the the HorizontalScrollBarPolicy to NEVER, but that just ends up in no ScrollBar appearing and the content not being dispalyed anymore.
What i expect it to look like is this:
This is my MCVE:
final JPanel panel = new JPanel( new MigLayout( new LC().flowX().gridGapX( "20" ).fill() ) );
panel.add( new JXTitledSeparator( "Test" ), new CC().growX().spanX().wrap() );
panel.add( new JLabel( "Shrink me please!" ), new CC().minWidth( "1" ) );
panel.add( new JLabel( "Never shall anyone ever be able to shrink me." ), new CC().growX() );
final JScrollPane scrollPane = new JScrollPane( panel );
scrollPane.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );
final JFrame frame = new JFrame( "Test" );
frame.getContentPane().add( scrollPane );
frame.setVisible( true );
frame.pack();
I sadly have no clue how to do this, the JViewport of the JScrollPane doesn't offer any methods which might helpful, neither does the JScrollPane itself afaik.
Also i have already tried to achieve the same thing using BoxLayout and FlowLayout instead of MigLayout in order to verify that MigLayout isn't the cause of the problem.

You need to implement the Scrollable interface on your panel.
You would want to implement the getScrollableTracksViewportWidth() method to return true.
This will force the width of the panel to match the width of the viewport. Then each component on the panel will be sized based on the rules of the layout manager.
If you don't want to implement the Scrollable interface yourself then you can use the Scrollable Panel which provides method that allows you to control the scrollable properties.

Try setting the Max width for Shrink Label.
You don't need scroll bar?
if need to use scrollbar as needed from scroll pane constants
final JFrame frame = new JFrame( "Test" );
frame.setLayout(new BorderLayout());
frame.add( scrollPane , BorderLayout.CENTER);
frame.pack();
frame.setVisible( true );
Used border layout, and moved the pack before visible.

Related

Parsing large text to textfield, how to set view position on beginning of text

When parsing large text in this case, it is "Still loving you - Scorpions" to textfield it have look like this ->
. I wanna, view start from beginning. Have also trouble with scroll bar, use JScrollPane on Jlist, and when it need scroll because large text, on initialization, it take down scroll, it be like this, what I have described for textfield.
Have this code for textfield:
textField_1 = new JTextField();
textField_1.setEditable(false);
textField_1.setColumns(10);
textField_1.setBounds(149, 33, 129, 20);
frame.getContentPane().add(textField_1);
Frame, have absolute layout:
frame = new JFrame();
frame.setBounds(100, 100, 317, 516);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
You simply need to add this line:
textfield_1.setCaretPosition ( 0 );
Moreover, one should not use Absolute Positioning as much as possible.
Although it is possible to do without a layout manager, you should use a layout manager if at all possible. A layout manager makes it easier to adjust to look-and-feel-dependent component appearances, to different font sizes, to a container's changing size, and to different locales. Layout managers also can be reused easily by other containers, as well as other programs
For more info, have a look at Absolute Positioning Doc
EDIT 1:
Regarding JScrollPane
One can achieve that in two ways:
1. Either use, setPreferredSize ( ... ) on the JScrollPane, like:
myList = new JList ( listData );
JScrollPane listScroller = new JScrollPane ();
listScroller.setViewportView ( myList );
listScroller.setPreferredSize ( new Dimension ( 100, 100 ) ) ;
contentPane.add ( listScroller );
2. Or one can override, getPreferredSize () for the said JComponent, like:
myList = new JList ( listData );
JScrollPane listScroller = new JScrollPane () {
#Override
public Dimension getPreferredSize () {
return new Dimension ( DIMENSION, DIMENSION );
}
};
listScroller.setViewportView ( myList );
contentPane.add ( listScroller );

How to add JPanel into another JPanel with vertical scrollpane at runtime?

I'm trying to insert a new panel into another panel in runtime everytime I press a button. My problem is the original panel runs out of space and I can't see the new panels I'm adding.
What I've tried so far:
Using scrollpane for vertical scrolling with no success.
Using flowlayout-no luck. Tried disabling horizontal scrolling-keep pushing the new panel to the right (can't get to it because there is no scrolling).
Tried using borderlayout-no luck.
testpanel t = new testpanel();
t.setVisible(true);
this.jPanel15.add(t);
this.jPanel15.validate();
this.jPanel15.repaint();
This code suppose to insert the t panel into jpanel15.
With flowlayout it pushes the t panel downwards just like I want it to but with no vertical scroll.
PS: I'm using netbeans in order to create my GUI.
My problem is the original panel runs out of space and I cant see the new panels i'm adding. Tried using scrollpane for vertical scrolling with no success.
A FlowLayout adds components horizontally, not vertically so you will never see vertical scrollbars. Instead you can try the Wrap Layout.
The basic code to create the scrollpane would be:
JPanel main = new JPanel( new WrapLayout() );
JScrollPane scrollPane = new JScrollPane( main );
frame.add(scrollPane);
Then when you dynamically add components to the main panel you would do:
main.add(...);
main.revalidate();
main.repaint(); // sometimes needed
Use JScrollPane instead of the (outer) JPanel
Or have a BorderLayout for the JPanel, put in a JScrollPane at BorderLayout.CENTER as the only control. The JScrollPane takes a regular JPanel as view.
In any case you will then add the control to the JScrollPane. Suppose your JScrollPane variable is spn, your control to add is ctrl:
// Creation of the JScrollPane: Make the view a panel, having a BoxLayout manager for the Y-axis
JPanel view = new JPanel( );
view.setLayout( new BoxLayout( view, BoxLayout.Y_AXIS ) );
JScrollPane spn = new JScrollPane( view );
// The component you wish to add to the JScrollPane
Component ctrl = ...;
// Set the alignment (there's also RIGHT_ALIGNMENT and CENTER_ALIGNMENT)
ctrl.setAlignmentX( Component.LEFT_ALIGNMENT );
// Adding the component to the JScrollPane
JPanel pnl = (JPanel) spn.getViewport( ).getView( );
pnl.add( ctrl );
pnl.revalidate( );
pnl.repaint( );
spn.revalidate( );

when adding 2+ buttons to east layout, only 1 shows

When adding 2+ buttons to east layout, only 1 shows. I am trying to test a layout that uses tabbed panes. For some reason when I try to add multiple buttons to the east region, it only shows 1 button. It just so happens the button displayed is the last one added to the east region, the rest are ignored. I am thinking maybe they are just hidden underneath the last button.
public void createPage1()
{
{
panel1 = new JPanel();
panel1.setLayout( new BorderLayout() );
panel1.add( new JButton( "North" ), BorderLayout.EAST );
panel1.add( new JButton( "South" ), BorderLayout.EAST );
panel1.add( new JButton( "East" ), BorderLayout.EAST );
panel1.add( new JButton( "West" ), BorderLayout.EAST );
panel1.add( new JButton( "Center" ), BorderLayout.EAST );
}
}
I dont know, how you want your UI to look like, but try it this way:
public void createPage1() {
//This will be the main panel.
//We are going to put several buttons only in the "EAST" part of it.
panel1 = new JPanel();
panel1.setLayout( new BorderLayout() );
//We create a sub-panel. Notice, that we don't use any layout-manager,
//Because we want it to use the default FlowLayout
JPanel subPanel = new JPanel();
subPanel.add( new JButton( "1" ));
subPanel.add( new JButton( "2" ));
subPanel.add( new JButton( "3" ));
//Now we simply add it to your main panel.
panel1.add(subPanel, BorderLayout.EAST);
}
BorderLayout only allows one component per section. If you want to keep BorderLayout, but have 2+ buttons, I suggest first putting each of those buttons into a JPanel and then putting that JPanel into the east slot.
However, there are probably much better layout choices for you. You also mention tabs, which there is already JTabbedPane for.
Check out the different LayoutManagers, and try to figure out which one is right for you.
1. The default layout for JFrame is BorderLayout, and it has East, West , North , South, and Center area, out of which Center is the default if positioning is not mentioned.
2. Now each section/area can hold only one widget (ie. swing component).
3. You will have this done in much better way by using Group Layout, which was developed by NetBeans team in 2005, use Windows Builder Pro, now free from google.
4. But if you still want to go with the BorderLayout, i will suggest you to use JPanel on the content pane of the JFrame to add Buttons in the manner you want......

Java. Swing. Multiline labels in a JScrollPane

I have a JFrame with JScrollPane in it. I have JPanel inside a scrollPane. And add multiline labels in it.
Everything is ok with multiline labels. I enclose my text in <HTML>..</HTML> tags.
And labels display its wrapped text.
"..." means long multiline text.
The problem is that useless area is displayed in the bottom.
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(300, 300));
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
label1.setText("<html>" + "..." + "</html>");
panel.add(label1);
label2.setText("<html>" + "..." + "</html>");
panel.add(label2);
JScrollPane scroll = new JScrollPane(panel);
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
frame.setContentPane(scroll);
frame.pack();
frame.setVisible(true);
EDIT.
So I have to set preferred size for inner JPanel. After that scrollPane draws its content(shows scrollbars) as its content has this fixed "inner panel preffered size".
If I won't set preferred size for the panel, JLabels wouldn't wrap the text.
After being layed out by the layout manager inner panel's size grows and became larger than previously set preferred size. Panel grows itself, its ok, I see wrapped text of labels in it. But scrollpane behaves incorrectly. It paints scroll as inner panel is still of prefferred size size. So I need correct resizing behaviour for JScrollPane.
use JTextPane or JEditorPane instead of JPanel contains bunch of JLabels
JTextPane or JEditorPane supporting stylled text or Html <= 3.2 for Java6
theoretically you can use JList, instead of Jlabels, but in this case you have to call for setPreferredScrollableViewportSize(new Dimension) same as for JPanel in the JScrollPane
EDIT
then use Highlighter
use built-in reader/writer for JTextComponents

java BoxLayout panel's alignment

I have browsed around and haven't found a solution that specifically tailors to my situation. I have a panel that I display in a dialog box:
//create dialog panel
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(headerPanel);
panel.add(type1Panel);
panel.add(type2Panel);
panel.add(type3Panel);
panel.add(type4Panel);
panel.add(type5Panel);
panel.add(type6Panel);
int result = JOptionPane.showConfirmDialog(null, panel, "Please enter values.", JOptionPane.OK_CANCEL_OPTION);
The size of the last two panels, type5 & type6, are of equal size so they look fine. However, the header and first 4 panels are of different sizes and I would like them all to be left aligned. As of yet I haven't found a good solution as how to fix this.
Question is, how can I left align the first 5 panels, but not last 2? If not how can I left align them all? The setalignmentx() isn't available for panels. I've tried using GridLayout, but then the width of the gui's main window is rather large and doesn't fit nicely onto the screen, hence the BoxLayout along Y axis.Thanks for any help or suggestions.
Here is an example that will left align all the JPanels added to the panel used as a container.
JPanel a = new JPanel();
JPanel b = new JPanel();
JPanel c = new JPanel();
a.setBackground( Color.RED );
b.setBackground( Color.GREEN );
c.setBackground( Color.BLUE );
a.setMaximumSize( new Dimension( 10, 10) );
b.setMaximumSize( new Dimension( 50, 10) );
a.setAlignmentX( Component.LEFT_ALIGNMENT );//0.0
b.setAlignmentX( Component.LEFT_ALIGNMENT );//0.0
c.setAlignmentX( Component.LEFT_ALIGNMENT );//0.0
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(a);
panel.add(b);
panel.add(c);
int result = JOptionPane.showConfirmDialog(null, panel, "Please enter values.", JOptionPane.OK_CANCEL_OPTION);
Create a horizontal javax.swing.Box object to contain each typenPanel object. Using horizontal struts and glue you can do whatever you want:
Box b1 = Box.createHorizontalBox();
b1.add( type1Panel );
b1.add( Box.createHorizontalGlue() );
panel.add( b1 );
For simplicity, write a helper method to do this for you:
private Component leftJustify( JPanel panel ) {
Box b = Box.createHorizontalBox();
b.add( panel );
b.add( Box.createHorizontalGlue() );
// (Note that you could throw a lot more components
// and struts and glue in here.)
return b;
}
Then:
panel.add( leftJustify( headerPanel ) );
panel.add( leftJustify( type1Panel ) );
panel.add( leftJustify( type2Panel ) );
etc.... You can get fancier with each line, adding components, glue, and struts. I've had great luck deeply nesting vertical and horizontal boxes, and writing helper methods when I want to do the same layout in a box more than once. There's no limits to what you can do, mixing components, struts, and glue as necessary.
I'm sure there's a better way to do all this, but I haven't found it yet. And the dynamic resizing lets a user with short bits of text use a small window and a user with lots of text resize it so it all fits.
You should use setAlignmentX on the panels because it is available for JPanel. The methods setAlignmentX and setAlignmentY are found in JComponent, which JPanel extends. It works...I've got code that uses those methods to align JPanels in a BoxLayout.
Ok, fine, edit your question while I'm answering it :)
Instead of using a JPanel try using a Box. I've found the Box class to be very useful as a container. From the API:
A lightweight container that uses a BoxLayout object as its layout
manager. Box provides several class methods that are useful for
containers using BoxLayout -- even non-Box containers.
If you haven't seen it yet, the tutorial How to Use BoxLayout is very helpful.

Categories