Showing components drawn outside JPanel boundary
Hello all,
I need to draw some components in a JPanel. Usually, I need a JPanel which will have a height and width way larger than any screen can support. I thought if I add the JPanel in a JScrollPane the problem would be solved. User will scroll to view all the components. But it is not working. JPanel does not complain me drawing components outside its boundary but the scrollbar is not also showing up, no matter what I do. Can you suggest me any solution?
Basically, I need a large area where I can draw many components and then add scrollbars to facilitate users to view them. How can I do them?
Thanks in advance,
Russoue
[661 byte] By [
Russouea] at [2007-11-27 10:34:04]

# 1
my car won't start.
it won't start, no matter what I do.
Can you suggest me any solution?
enough information to provide a solution?
(or do you just want guesses)
# 2
Code or it didn't happen.
# 3
Well, let me give an example. Suppose, I need a JPanel of size 1000 x 800 (width x height). I use setSize(Dimension) method to set this size and then I draw all over the place. But when I add that JPanel to a JFrame or another JPanel, it gets resized to 400 x 300. Now, the components outside the 400 x 300 area are lost. I cannot see them anymore.
The problem description ends here.
Now, I need to show all components I drew in that 1000 x 800 area to my users.
I thought if I add the JPanel to a JScrollPane, I would get a viewport of 400 x 300 but I can scroll the whole area of 1000 x 800 but it is not happening.
# 4
Once again, code or it didn't happen.
# 5
code shows us what you're doing, so we can offer solution/s
descriptions of problems are generally useless
here's a working example, compare to your (unposted) code and see if there's a difference
import javax.swing.*;
import java.awt.*;
class Testing
{
public void buildGUI()
{
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK,10));
panel.setPreferredSize(new Dimension(3000,2000));
JScrollPane sp = new JScrollPane (panel);
JFrame f = new JFrame();
f.getContentPane().add(sp);
f.setSize(600,400);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new Testing().buildGUI();
}
});
}
}
# 6
Thank you Michael Dunn for your code. But I do not know what my panel size will be when I create it. So I create it with a small size then try to resize it. I think, as you guys asked, the following code which is basically the modification of Michael Dunn's code will demonstrate the problem I am facing:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Testing implements ActionListener
{
private JPanel m_Panel;
private JButton m_Button;
public void buildGUI()
{
m_Panel = new JPanel();
m_Panel.setBorder(BorderFactory.createLineBorder(Color.BLACK,10));
m_Panel.setPreferredSize(new Dimension(300,200));
JScrollPane sp = new JScrollPane (m_Panel);
m_Button = new JButton("Resize JPanel");
m_Button.addActionListener(this);
JFrame f = new JFrame();
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(sp, BorderLayout.CENTER);
f.getContentPane().add(m_Button, BorderLayout.SOUTH);
f.setSize(600,400);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
System.out.println("Panel's size in buildGUI is " + m_Panel.getSize().width + " : " + m_Panel.getSize().height);
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource() == m_Button)
{
System.out.println("Panel's size before setPreferredSize(3000, 2000) is " + m_Panel.getSize().width + " : " + m_Panel.getSize().height);
m_Panel.setPreferredSize(new Dimension(3000, 2000));
//m_Panel.setSize(new Dimension(3000, 2000));
System.out.println("Panel's size after setPreferredSize(3000, 2000) is " + m_Panel.getSize().width + " : " + m_Panel.getSize().height);
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new Testing().buildGUI();
}
});
}
}
You can click the button multiple times to see the problem.
# 7
Scrollbars will appear when the preferred size of the component added to the scrollpane is greater than the size of the scroll pane.
Just resetting the preferred size does not notify the scrollpane that the preferred size has changed. So after resetting the preferred size you need to add:
sp.revalidate();
By the way the size of the panel will not change. It will only be the size of the viewport. When using layout managers you never set the size, only the preferred size and let the layout manager to the work.
# 8
Hello camickr, I used the revalidate method of JScrollPane, but it did not help. Can you suggest anything else?
# 9
works fine like this
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource() == m_Button)
{
System.out.println("Panel's size before setPreferredSize(3000, 2000) is " + m_Panel.getSize().width + " : " + m_Panel.getSize().height);
m_Panel.setPreferredSize(new Dimension(3000, 2000));
m_Panel.revalidate();//<--
SwingUtilities.invokeLater(new Runnable(){
public void run(){
System.out.println("Panel's size after setPreferredSize(3000, 2000) is " + m_Panel.getSize().width + " : " + m_Panel.getSize().height);
}
});
}
}
[EDIT]
also works OK with
sp.revalidate();
after giving sp the necessary scope
# 10
> Hello camickr, I used the revalidate method of JScrollPane, but it did not help.
Works fine for me. Post your SSCCE (your demo program) showing how you tested it.
Oops, missed your edit commment..
> [EDIT]
> also works OK with
> sp.revalidate();
> after giving sp the necessary scope
# 11
Thanks a lot to camickr and Michael Dunn.
Using revalidate for both JPanel and JScrollPane working fine. Previously I was only doing JScrollPane.revalidate().
Thanks again. Bye.
# 12
> Previously I was only doing JScrollPane.revalidate().
That all you need to do.
You only need to revalidate() the scrollpane which is the most efficient since you only validate a single component.
Or you revalidate() the panel, which is extra work since it revalidates the panel and then the scroll pane.
You do not need to revalidate both components.
Thats why I asked for your SSCCE because if it doesn't work the way Michael and I described with the scroll pane, then
a) you are doing something wrong
b) your version of the jdk has a bug.
# 13
Thanks camickr, I removed the first revalidate. It is working nicely. However, I am facing a new problem here, not related to the original problem. The vertical scrollbar remains at the value 0 if nothing is done. But I want it to be at the bottom. So, I did:
JScrollBar.setValue(JScrollBar.getMaximum());
But it is not working. Printing JScrollBar.getValue() after that line shows 0 i.e. it has not changed. Can anyone give me any idea why this is happening?
# 14
> Can anyone give me any idea why this is happening?
My best guess is that sometimes behind the scenes some methods use SwingUtilities.invokeLater() to add code to the end of the event thread. So basically your code got executed and then got overridden by the code that got added to the end of the event Thread. You can play the same game by adding your code to the end of the event Thread.
m_Panel.setPreferredSize(new Dimension(3000, 2000));
sp.revalidate();
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JScrollBar sb = sp.getVerticalScrollBar();
sb.setValue(sb.getMaximum());
}
});