I have a JScrollPane whose client is a Container with layout BoxLayout.
Within the BoxLayout are multiple (dynamically generated) JPanels. However, the JScrollPane doesn't scroll (the scrollbars show and resize, but you can't actually move them), and I also can't interact with the contents of the JScrollPane.
Here's the code:
public static void setupOrderTable(){
orderTable = new Container();
scroller = new JScrollPane(orderTable ,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroller.setPreferredSize(new Dimension(810,500));
orderTable.setLayout(new BoxLayout(orderTable,BoxLayout.Y_AXIS));
if (orderTable!=null)
mainContainer.remove(orderTable);
for (Order o: OrderManager.getList()){
orderTable.add(new ControlRowItem(o));
}
mainContainer.add(scroller,BorderLayout.CENTER);
frame.pack();
}
It works fine if I just replace the line
mainContainer.add(scroller,BorderLayout.CENTER);
with
mainContainer.add(orderTable,BorderLayout.CENTER);
But then it obviously doesn't scroll. Otherwise, as I said, the scrollbars don't work and I can't interact with any of the JPanels within the orderTable.
Don't mix heavy weight (Container) components with lightweight (JScrollPane) components, they just don't mix well. Change orderTable to be a JPanel instead
While it's suppose to have been fixed in Java 6, I've seen too many weird things with trying this to make it worth any effort at all. Simply rule, don't mix heavy weight components (AWT) in Swing containers
Related
I am trying to create a JScrollPane that contains a JPanel that will be increasing and decreasing in height. When it becomes larger than the size of the JScrollPane, it should create a vertical scroll bar which will allow me to scroll through the entire JPanel. However, I am having difficulty achieving this. Yes, I know I am not using LayoutManagers. No, I will not be using them, and I need a solution that does not involve their usage.
Here are the two button's AbstractActions that add and subtract from the JPanel:
class AddACT extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
info.setSize(420,info.getHeight() + 40);
info.add(new SubPanel); // Adds another JPanel into the main JPanel (for content input)
gui.repaint();
infoS.validate();
}
}
class RemoveACT extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
info.remove(subPanel()); // This would remove the last JPanel added to the main JPanel
info.setSize(420,info.getHeight() - 40);
gui.repaint();
infoS.validate();
}
And here is the code for the main JPanel and the JScrollPane:
final JPanel info = new JPanel();
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
info.setLayout(null);
info.setSize(420,600);
infoS.setLocation(10,80);
infoS.setSize(420,490);
gui.add(infoS); // gui is the frame's content pane (the overall JPanel)
This is the second project I've been trying to learn GUI by doing. I am a complete novice in Swing and am only intermediate in Java. Sorry if I am making a blindingly obvious mistake.
1) Use LayoutManagers (+1 to #kleopatra and #GagandeepBali comments)
The absence of LayoutManagers only guarantees your GUI's will look very trashy (especially when run on other OSes/builds) and being a Novice you should rather learn the correct way than learn the wrong way and get into bad habits like calling setSize() etc.
Have a read on these links to get you started:
A Visual Guide to Layout Managers
Concurrency in Swing
2) See this example for how to use a JScrollPane, it simply adds a JPanel with buttons to a JScrollPane which in-turn is added to the JFrame.
3) Also see this example for how to make the JScrollPane vertically scroll-able only.
4) For more on JScrollPanes have a look here: How to Use Scroll Panes.
5) As for how it interacts with LayoutManager, if you do not explicitly set its size via setPreferredSize(Dimension d) the scroll pane computes it based on the preferred size of its nine components (the viewport, and, if present, the two scroll bars, the row and column headers, and the four corners)
6) On your usage of validate():
validate() is used when new JComponents are added to a visible component
revalidate() is used when JComponent is removed/added from a visible component
revalidate() covers validate() too
Thus always use this:
//add or remove component(s)
revalidate();
repaint();
References:
http://www.daniweb.com/software-development/java/threads/405568/validate-vs-revalidate
LayoutManager is not required to solve the problem. The problem in Thrfoot's example is in these lines:
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
info.setLayout(null);
info.setSize(420,600);
The program appears to recognize there is a need for scroll bars (it would show the scroll bar if your setting was VERTICAL_SCROLLBAR_AS_NEEDED), but the actual scrolling does not work (the scroll bar slider is not there).
To fix this, first set the preferred size of info, then construct the infoS.
Example:
info.setPreferredSize(420,600);
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
The idea is to set the preferred size of the info panel before it is used for the scroll pane. This is the same reason to set the size and location of infoS before adding to the gui:
infoS.setLocation(10,80);
infoS.setSize(420,490);
gui.add(infoS); // gui is the frame's content pane (the overall JPanel)
How can I position a JButton under a JTable? What kind of layouts? How? I have a JTable table what is scrollable, and the table is in a frame.
There are many layouts to fulfill this need.
The simplest is using BorderLayout:
JFrame frame = new JFrame();
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(new JScrollPane(jtable), BorderLayout.CENTER);
contentPane.add(button, BorderLayout.SOUTH);
If you want this button to be not resized just add JPanel to contentPane. This JPanel should contain your button centered using almost any layout.
If you would like to use more sophisticated layout - the best in my opinion is MigLayout
To correct LoveToCode's well-meaning but misleading advice, you would never want to give a JTable itself a layout. The solution to your problem is not to set the JTable's layout but to set the layout for the JPanel that holds both the JTable's JScrollPane and the JButton. Likely a BorderLayout would work best with the JScrollPane being placed BorderLayout.CENTER and the JPanel that holds the JButton BorderLayout.SOUTH.
Note, if you're adding these components to the JFrame, then know that its contentPane already uses BorderLayout (the tutorials will tell you this -- please read them). So just add these guys to the contentPane as described above.
If hard coding of swing and awt is not mandatory, try using the WindowsBuilder Pro, a Free tool now from google, install its plugin in to eclipse, then Use
GroupLayout - Introduced by NetBeans team in 2005 integrated in WindowsBuilder Pro, is one of the most convenient way create a good gui in less time in Java.
It seems that you can set the layout of a jtable the same way in which you can set the layout of a jframe or a jpane:
table.setLayout(new grideLayout(4, 3)
would give it a grid layout with 4 rows and 3 columns.
the scrollable feature allows you to 'scroll' through your table with the moving bar. It may be a default feature, or it may be that you must use it, try seeing what methods your table gives you.
Lastly, your table should be in a frame, so that you can view it on your window, make you class extend JFrame and it will automatically be a frame upon which you can simply add a table!
I want to add a Jpanel on a jscrollpane; also I want to have only vertical scrolling. I want to set layout of my jPanel "flowLaout" and add several components to my jPanel in my code by jpanel.add(component) method. The result is that all components are placed in just one row that excide width of jpanel and are not shown. I have used this tricks and both failed:
jScrollPane1.setHorizontalScrollBar(null);
jScrollPane1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
Wrap Layout should work for you.
I am unsure of the particulars for your current project, but i would recommend MigLayout. It has never served me wrong.
I am currently writing a touchscreen interface with nested MigLayout panels up to 4 or five layers deep, and have not had a single problem.
Please use the below policy to turn on vertical scrolling and turn off horizontal scrolling(Works with Java SE 7):
Panel graphicPanel = new Panel();
JScrollPane scrollbar = new JScrollPane(graphicPanel);
scrollbar.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollbar.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollbar.setPreferredSize(new Dimension(1300, 600));
scrollbar.setVisible(true);
add(scrollbar, BorderLayout.CENTER);
I'm building a Swing application in Java using NetBeans and I have a problem with layout. My main frame contains a JScrollPane which contains a JPanel called contentPanel which in turn contains a JPanel called listPanel. The listPanel is empty when the program starts, but when the user interacts with the program an unpredictable number of smaller JPanels are added to it. I've used the NetBeans GUI-builder to snap the top edge of listPanel to the top of contentPanel, and the same with the bottom edges.
The problem I have is that when more components are added to listPanel the vertical scrollbar doesen't appear on my scrollpane. The verticalScrollBarPolicy of my scrollpane is set to AS_NEEDED and its viewportView is set to contentPanel. What I think I need to do is to make contentPanel grow when more items are added to listPanel.
The problem I have is that when more components are added to listPanel the vertical scrollbar doesen't appear on my scrollpane.
The scrollbar will appear when the preferred size of the component added to the scrollpane is greater than the size of the scrollpane. When you add components dynamically you need to tell the scrollpane something has changed. So you basic code should be:
panel.add( subPanel );
panel.revalidate();
Or, because you are adding a panel to the sub panel, you may need to revalidate the scrollpane (I don't remember):
panel.add( subPanel );
scrollPane.revalidate();
The key is the revalidate() which tell the layout manager to recalculate its size.
Use a different LayoutManager. One that will allow for vertical growth like BoxLayout. Also remember that you can use multiple layouts and nest them inside of each other for different effects.
I'm trying to make some components inside a JSrollPane unresizable, because content inside can grow dynamically and I must prevent it from growing over a predefined size.
My approach so far is this one:
scrollPane(constraints:BL.CENTER, size:[500,200], maximumSize:[500,200]){
panel(background:Color.WHITE, border:BF.createTitledBorder('Results')) {
gridBagLayout()
f0 = label(constraints:gbc(gridx:0, gridy:0))
fk = label(constraints:gbc(gridx:0, gridy:1))
}
}
(this is Groovy but objects are the same as Swing (eg label = JLabel, panel = JPanel..)
And it works but when inserting into the label a text that is long for example 2000px the first call to repaint in the frame that contains this scrollpane makes the whole scrollpane resize (until the scrollbar actually disappears).
I need to force to remain to the size I want!
Am I missing something? Or is it a bug of groovy? (it seems strange because this should just maps calls to normal swing components)
Why don't you just wrap the text? Anyway, Swing components have setMaximumSize(Dimension) method