I'm trying to put a vertical JScrollBar on top of a JPanel. I can add the scoll bar easily enough, but when I run the program, my scroll bar doesn't have any effect. I can drag it up and down, but the contents of the JPanel don't move. I've read all what I can find about how to do this, and it seems very straightforward, but I'm obviously missing something.
Please note that my JPanel layout is set to NULL. Here is the relevant code. Thanks!
public JDlgResults(ArrayList<AnsweredProblem> probList) {
initComponents();
pnlResults.setLayout(null); //allows free form placing of JLabels
/* Iterate over the ArrayList and add each problem to the results table */
Iterator iter = probList.iterator();
int row = 1;
while(iter.hasNext()) {
addRow(row, iter.next());
row++;
}
JScrollBar jScrollResults = new javax.swing.JScrollBar();
pnlResults.add(jScrollResults);
jScrollResults.setBounds(590, 0, 17, 196);
}
I assume that your initComponents() method sets up a bunch of components and adds them to your contentPane and establishes your dialog (whether it be dialog or a frame).
Simply adding your JScrollPane to that panel wont do the trick.
Instead, add your pnlResults to the JScrollPane instance and make that your contentPane.
That's by design. It would be kind of bad if the scroll bar magically tried to pick up panels in its vicinity and started scrolling them.
On a low level, you can add listeners to the scroll bar and implement scrolling yourself. You would also have to tell the scroll bar how much there is to scroll.
However, this is not what you want. You want a JScrollPane that you wrap around your panel. In that way, you never instantiate the scroll bars directly and do not have to deal with the low-level mechanics of scrolling (which is quite complicated).
Related
I know there are a lot of questions similar to this one, but unfortunately they are all about auto scrolling a scrollBar inside of a TextArea.
I use a JScrollPane to simulate a JList: I add small JPanels to a JScrollPane with GridLayout, and they stack verically.
I want the scroll bar to follow the last added element (down), but I can't get it to work.
I tried to adapt some of the answers for the Text, such as:
.autoScrolls(true);
or
JScrollBar vertical = scollPan.getVerticalScrollBar();
vertical.setValue( vertical.getMaximum() );
and even one on changing the updatePolicy, but nothing works for a JScrollPane that isn't bound to a text area, I can only scroll the bar manually.
vertical.setValue( vertical.getMaximum() );
did do something, it scrolls the bar down, but just about 2/3 of the way, and only because I added .revalidate() on the scrollPane after calling it.
Any idea?
After add components to the panel you need to do revalidate() and repaint() to make sure the layout manager is invoked.
JScrollBar vertical = scollPan.getVerticalScrollBar();
vertical.setValue( vertical.getMaximum() );
Then wrap the above code in a SwingUtilities.invokeLater() to make sure the code is added to the end of the Event Dispatch Thread (EDT) so it is executed after all the layout code.
I know that this question might have been asked before, but I just can't get by head around this, and hopefully we could produce a complete answer to a somewhat tricky interface.
The GUI could be described as follows:
Application extends JFrame. Application adds a JPanel mPanel. mPanel adds a JScrollPane ml containing a MoviePanel extending JPanel.
The JScrollPane ml has vertical scrolling. My goal is that once the content of MoviePanel changes, and a run a revalidate() on it, the scroll pane should not, as it currently does, scroll to the bottom. Rather I'd like it to scroll to what ever position it had before the change to MoviePanel. Giving the feel that it never scrolled at all.
I have tried to manually set the scroll position after I run the revalidate() method:
removeAll(); // Removes all components from the JPanel MoviePanel
add(mList()); // Adds a bunch of content (other JPanels) to MoviePanel
revalidate();
ml.getVerticalScrollBar().setValue(0); // Scroll to top (don't work) - and I'd like this value to be the position of the scroll before these lines started to run
but it seems it really doesn't do anything.
I would be so grateful if someone might help me with this!
Add the scrolling code to a SwingUtilities.invokeLater:
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
ml.getVerticalScrollBar().setValue(0);
}
});
I have got the following basic setup on a Part of my GUI:
A JScrollPane
On it, a JPanel with a BoxLayout (new BoxLayout(tablePanel, BoxLayout.PAGE_AXIS))
And on this Panel, a Bunch ob Panels.
I am trying to scroll to the Panel that has been highlighted... this works ALMOST.
Currenly, if a Panel is only half-visible on the bottom Part, the ScrollPane scrolls to make it fully visible.. great.
If it is half-visible on the TOP part, it does not... I could live with that.
But if a totally invisible Panel at the very bottom is highlighted, the system does not comment, but neither does it scroll there!
if(selectedPanel!=null){
Rectangle targetRectangle = new Rectangle(selectedPanel.getX(), selectedPanel.getY(), selectedPanel.getWidth(), selectedPanel.getHeight());
Rectangle r = scrollPane.getVisibleRect();
if (!r.contains(targetRectangle)) {
tablePanel.scrollRectToVisible(targetRectangle);
}
}
I am unfortunately not 100% sure how it behaves when the second-to-last panel is selected while not visible, because I cannot make that happen without some code-gymnastics; perhaps someone can help with the information I can give at this point.
you have to compare Rectangle from/returns JViewport(visible rectangle from JScrollPane), not from JScrollPane
use selectedPanel.getBounds instead of (selectedPanel.getX(), selectedPanel.getY(), selectedPanel.getWidth(), selectedPanel.getHeight());
still isn't centerred, have to divide JVievports and selectedPanel with 2
the same result as to use single code line JComponentPlacedIntoJScrollPane.scrollRectToVisible(selectedPanel.getBounds())
for better help sooner post an SSCCE/MCVE, short, runnable, compilable
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)
I am trying to initialize a JScrollPane to start life at the bottom. I do not want it to scroll automatically after it is initially shown. The scroll pane does not contain a subclass of JTextComponent, but rather a JPanel(GridLayout(0, 1)) containing many JPanels.
I tried using JViewport.scrollRectToVisible() inside an event handler on the parent Window (addComponentListener:componentShown), but it did not seem to work.
Any ideas?
The scroll pane does not contain a
subclass of JTextComponent, but rather
a JPanel(GridLayout(0, 1)) containing
many JPanels.
Then you need to scroll the panel:
panel.scrollRectToVisible(...);
Or you should be able to use:
JScrollBar sb = scrollPane.getVerticalScrollBar();
sb.setValue( sb.getMaximu() );
Also, this code needs to be executed "after" the GUI is visible.