Why am I not getting a functioning JScrollPane? - java

I have a JFrame window, and I'd like to add a scrollable JTable towards the middle of it. I have a method, called collectionTableScrollPane() that generates the JScrollPane (and I know this is guaranteed to work).
I then proceed to add it to my mainPanel panel. However, I'd like there to be some forced 30px padding on the left and right of the JScrollPane. Logically, I would create a holding JPanel with a centred FlowLayout, and add Box.createHorizontalStrut(30) either side of the JScrollPane.
JPanel tableHolderPanel = new JPanel(new FlowLayout());
mainPanel.add(tableHolderPanel);
tableHolderPanel.add(Box.createHorizontalStrut(30));
tableHolderPanel.add(collectionTableScrollPane());
tableHolderPanel.add(Box.createHorizontalStrut(30));
However, I'm getting a strange result, where the JScrollPane in the middle of the window (denoted by the arrows) sort of becomes ineffectual.
Does anyone know what the problem is?
Note that the JTable contains four rows, of which only two are visible.

I had some issues in the past when i used a JScrollPane inside a panel with a FlowLayout. The behaviour could be tricky, when the content grow, the horizontal scrollbar may appear or the FlowLayout should add a new line.
In your case, i will replace the FlowLayout by a BorderLayout :
JPanel tableHolderPanel = new JPanel(new BorderLayout());
mainPanel.add(tableHolderPanel);
tableHolderPanel.add(Box.createHorizontalStrut(30), BorderLayout.WEST);
tableHolderPanel.add(collectionTableScrollPane(), BorderLayout.CENTER);
tableHolderPanel.add(Box.createHorizontalStrut(30), BorderLayout.EAST);

As far as I'm aware, Box is suppose to be used with the BoxLayout, this may be causing you some issues. Instead, why not use a EmptyBorder on the tableHolderPane

BoxLayout accepting size that came from JComponents, the same issue with default FlowLayout pre_implemented for JPanel
you have to returns PreferredSize by overrode JPanel nested JScrollPane,
use another LayoutManager, e.g. GridBagLayout or todays MigLayout
use NestedLayout, by using BorderLayout where you put two JLabels (e.i. that returns PreferredSize) to the EAST and WEST area
everything depends if you really to want to create the empty area and if shoud be resiziable or not

Related

Placing components on Jpanel

Can i combine Java layouts in same JPanel. I'm stuck with with placing my components on JPanel. It shoudl be like this: JLabel, JButton, JButton , JLabel and new line and same. I used BorderLayout but it wont go to the next row, keep adding components to same row and I need a new row. Ideal sit combined with cardlayout or some other good solution.
EDIT: Solved with GridLayout (0,4) It will do the job till i learn to use GridBaglayout. Thank you for trying to help me.
Yes you can combine layouts.
Using a JPanel you are able to embed other JPanels:
JPanel back = new JPanel(new BorderLayout());
JPanel rows = new JPabel(new GridLayout(3,3));
back.add(rows, BorderLayout.CENTER);
Without seeing your code though it's difficult to know exactly what you are trying to achieve!
Yes you can combine java layouts.
A common pattern I use is BorderLayout first on a frame. The central component expands out, while the other components shrink in. Inside these panels I might have a Flowlayout to show buttons evenly spaced horizontally on top.
Another common approach for forms is using a Gridbaglayout, then adding all the form elements at gridX and gridY positions. I then later can stretch and teak these cells using other constraints in the Gridbaglayout repetoire.
Can you add a screenshot so that we can see what you want to do?

Adding panel to BorderLayout region, elements not wrapping as they should

So I have some code like this inside init() for an applet:
layout = new BorderLayout();
setLayout(layout);
northPanel = new JPanel(new FlowLayout());
northPanel.add(inputDropDown);
northPanel.add(lowBoundLabel);
northPanel.add(lowBoundField);
northPanel.add(highBoundLabel);
northPanel.add(highBoundField);
northPanel.add(new JLabel("using"));
northPanel.add(categoriesField);
northPanel.add(new JLabel("categories"));
northPanel.add(showTotalsBox);
northPanel.add(refreshButton);
add(northPanel, BorderLayout.NORTH);
Now when I test it, all of the elements are in a straight line and do not wrap around when there is not enough space. I even made sure to specify that the panel is FlowLayout (even though it's the default) and it didn't change anything.
Shouldn't they wrap instead of just going off the screen? What's going on? I came up with a temporary solution by changing the northPanel to BorderLayout, splitting up these elements into to separate panels and adding them to North and South. However, the elements just disappear off the screen without the necessary space in this method so I'd rather have them wrap around.
This is actually exactly how FlowLayout works, annoying isn't it...
Take a look at WrapLayout instead...

Typing in JTextArea affects other components

I'm working on panel which has four components: a label, a textfield that is uneditable, another label and a JTextArea. These components are aligned vertically one after the other and I am using Box Layout for this panel. What I have noticed is that when I type in the text area component, it shifts the labels character by character till it can't anymore. They labels initially are aligned to the left but as soon as I start typing they start moving to the right. I have tried so many other components but Box Layout seems to do what I want, I just have to fix this error. Any one ideas?
This is my panel code:
JPanel Panel = new JPanel();
Panel.setLayout(new BoxLayout(Panel,BoxLayout.Y_AXIS));
Panel.add(new JLabel("just a label here"));
Panel.add(textFieldComponent);
Panel.add(new JLabel("just a label here"));
Panel.add(textAreaComponent);
Use another LayoutManager e.g. GridBagLayout or
Place the JLabel in a panel with Horizontal BoxLayout (or BorderLayout) to actieve desired alignment.
another alternative:
add the textAreaComponent to a JScrollPane (set the scrollPane's alignmentX to 0.0f)
I had this issue as well and I added: textArea.setLineWrap(true). It prevented other objects from being pushed when you type in the field.
You should definitely use another Layout. One of my personal favorite is Forms from JGoodies. I've yet to see a Java Swing layout that comes anywhere close.

Automatic wrapping using MigLayout

I'm looking to wrap a JPanel when it reaches the 'edge' of the screen using MigLayout. At the moment I have a JScrollPane (which I only want to be enabled vertically). The JScrollPane contains any number of JPanels which are arranged horizontally - when a panel is added so that the JPanel would go off the edge I want it to add to the next line. Is this possible?
This is the code:
public void setupPanels(){
JScrollPane scrollPane = new JScrollPane();
JPanel mainPanel = new JPanel(new MigLayout("insets 2"));
for (Object object : objects){
JPanel subPanel = new JPanel(new MigLayout("insets 0"));
mainPanel.add(subPanel, "alignx left, gapx 2px 5px, gapy 2px 2px, top");
}
scrollPane.setViewportView(mainPanel);
}
Also, to add an extra factor, every time it reaches the edge I need to add a new/different panel (a timeline) - so is there a way of finding out when it is going to wrap onto a new line?
Thanks
MigLayout does not have such a feature. It is based on a grid and while you can use the nogrid option to flow components horizontally or vertically in a cell span, you cannot make them flow into the next row or column.
The java.awt.FlowLayout contained in the JDK wraps the contained components automatically:
JPanel mainPanel = new JPanel(new FlowLayout());
mainPanel.add(subPanel1);
mainPanel.add(subPanel2);
mainPanel.add(subPanel3);
...
The preferred height is off, but there are ways to fix this, see WrapLayout.
As for the second requirement:
Also, to add an extra factor, everytime it reaches the edge I need to
add a new/different panel (A timeline) - so is there a way of finding
out when it is going to wrap onto a new line?
A layout manager should layout components that have already been added to a container, not add new components based on the results of the layout. Adding invisible placeholder components for the timeline after each subpanel that are made visible by the layout manager on demand might work.
You definitely need a custom layout manager to do this. To get started I would recommend to take the source of FlowLayout. In the layoutContainer implementation there is a loop that iterates over all components. After a line wrap, check if the next component is a timeline placeholder component, make it visible and wrap again.

How do I add space to a JPanel, so that JScrollPane doesn't sit on top of my components?

I have a JScrollPane and when I load my application the bar is sitting on top of one of my buttons. What I would like to do is add some space to the side of my button so that the scroll bar draws over the space and not my button.
Example code that I tried:
JPanel eButton = new JPanel(new BorderLayout());
JPanel spaceFiller = new JPanel();
spaceFiller.setSize(30, 10);
eButton.add(editButton, BorderLayout.EAST);
eButton.add(spaceFiller, BorderLayout.WEST);
The problem with this code is that it still overwrites my button and no space is added. What is the best way to make sure that JScrollPane doesn't overlap the components in my JFrame?
Thanks
To ensure that the size of the JPanel is respected you should use setPreferredSize() instead of setSize().
In your sample code, didn't you reverse EAST and WEST? Shouldn't it be like:
eButton.add(editButton, BorderLayout.WEST);
eButton.add(spaceFiller, BorderLayout.EAST);
That would make more sense, sicne the scrollbar will appear on the right side (EAST).
Please note that the solution you suggest, even though it may work (after exchanging EAST and WEST) looks more like a hack than a real solution.

Categories