I have a JFrame, in this JFrame I have a JPanel that I draw on, this Panel can be any size and so I placed it into a JScrollpane to let me scroll when the panel is larger than the window screen size.
Unfortunately does not work as I expected:
Making the JFrame window smaller than the JPanel size does not show scroll bars
The JScrollPane size now seems locked to the size of the JPanel I have added to it, where as before it resized to the bounds of it's JFrame window (it still kinda does this but only vertically now?!)
The JPanel seems to assume the size of the JScrollpane regardless of what I set for preferred size
I am sure I'm doing something stupid, if someone could point out what I would be most grateful!
JPanel imageCanvas = new JPanel(); // 'Canvas' to draw on
JScrollPane scrollPane = new JScrollPane();
// set size of 'canvas'
imageCanvas.setMinimumSize(new Dimension(100,100));
// Scroll pane smaller then the size of the canvas so we should get scroll bars right?
scrollPane.setMinimumSize(new Dimension(50,50));
// Add a border to 'canvas'
imageCanvas.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
scrollPane.setViewportView(imageCanvas);
setPreferredSize() is the trick, setMinimumSize() and even setSize() on the component will be ignored by JScrollPane. Here's a working example using a red border.
import java.awt.*;
import javax.swing.*;
public class Scroller extends JFrame {
public Scroller() throws HeadlessException {
final JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.red));
panel.setPreferredSize(new Dimension(800, 600));
final JScrollPane scroll = new JScrollPane(panel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(scroll, BorderLayout.CENTER);
setSize(300, 300);
setVisible(true);
}
public static void main(final String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Scroller().setVisible(true);
}
});
}
}
// suggest a size of 'canvas'
_ImageCanvas.setPreferredSize(new Dimension(100,100));
// Scroll pane smaller then the size of the canvas so we should get scroll bars right?
_ScrollPane.setPreferredSize(new Dimension(50,50));
// ..later
_Frame.pack();
Set preferred size on the canvas.
Increase dimensions 100,100 is too small atleast on my computer.
You may want to use new GridLayout(1,1); for you JFrame if you want the scrollpane to expand when you expand the frame.
As far as I remember there are 2 options:
define the preferredSize of _ImageCanvas
create a subclass of JPanel and implement Scrollable: http://docs.oracle.com/javase/7/docs/api/javax/swing/Scrollable.html
For more details, see the Javadoc:
http://docs.oracle.com/javase/7/docs/api/javax/swing/JScrollPane.html
Check out the Scrollable interface, this may help with the sizing issues.
These two method maybe helpful:
boolean getScrollableTracksViewportWidth();
boolean getScrollableTracksViewportHeight();
Related
I am using Miglayout to define a layout for my program. The problem is the JScrollPane prevents the JButton shrinking below its preferred size. The minimum, preferred, and maximum widths for the JButton are set like this, "w 300:600:900" //min:pref:max.
What is the best way to fix this problem?
SSSCE
import java.awt.*;
import javax.swing.*;
import net.miginfocom.swing.MigLayout;
public class ButLay extends JFrame {
private ButLay() {
super("Button Layout");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new MigLayout("", "grow", "grow"));
createPanel();
setSize(800, 200);
setVisible(true);
}
JPanel panel = new JPanel(new MigLayout("", "grow", "grow"));
JScrollPane scroll;
JButton button = new JButton("Button");
private void createPanel() {
panel.add(button, "gapleft 100, align right, w 300:600:900, south");
scroll = new JScrollPane(panel);
getContentPane().add(scroll, "grow");
}
public static void main(String[] args) {
new ButLay();
}
}
The default behaviour of a JScrollPane is to display the component in the scroll pane at its preferred size so that the scrollbars can appear as required.
If you want to change the behaviour then you can try to implement the Scrollable interface on your panel. You might be able to override the getScrollableTracksViewportWidth() method to return true. Now your panel should resize as the viewport of the scrollpane resizes. However using this approach your won't get a scrollbar if you make the viewport too small.
If you want the scrollbar in the above situation, then you may also need to override the getPreferredSize() method to return the minimum size when the preferredSize is greater than the size of the viewport.
You can also check out Scrollable Panel which implements the Scrollable interface for you and allows you to customize the behaviour with some convenience methods.
I got a JPanel called 'Main' which I managed to make transparent. The problem is, I only want to make the panel itself transparent, I want the components in it to be visible.
This bit of code is my Panel;
JPanel window=new JPanel();
static JTextArea dialog=new JTextArea(14,35);
JTextField input=new JTextField(35);
JScrollPane scroll=new JScrollPane(
dialog,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
public Main() {
super("Test");
setSize(400,270);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
dialog.setEditable(false);
dialog.setFocusable(false);
dialog.setOpaque(false);
scroll.setOpaque(false);
scroll.getViewport().setOpaque(false);
input.setOpaque(false);
input.addKeyListener(this);
window.add(scroll);
window.add(input);
this.setUndecorated(true);
this.setAlwaysOnTop(true);
window.setBackground(new Color(255,200,0));
add(window);
setVisible(true);
}
Now, when actually creating the window I use this;
Main Main = new Main();
Main.setOpacity(0.75f);
It does what it's supposed to which is make the panel and all it's components transparent.
However, I want only the panel to become transparent.
How would I go about doing this?
Try setting the background color of window to this as well.
new Color(255,200,0,0);
The last 0 sets the alpha - I believe 0 should make it transparent.
I have the following code to create my GUI.
private static void createGUI() {
JFrame frame = new JFrame ("Tiles Game");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar (new JMenuBar());
frame.setContentPane (MainPanel.getInstance());
frame.pack();
frame.setResizable (false);
frame.setLocationRelativeTo (null);
frame.setVisible (true);
}
This is the MainPanel (extends JPanel) constructor:
private MainPanel() {
super (new BorderLayout());
setPreferredSize (new Dimension (IMG_SIZE + 10, IMG_SIZE + 10));
...
panel = new ImagePanel();
add (panel, BorderLayout.CENTER);
}
And this is the ImagePanel (extends JPanel) constructor:
private ImagePanel() {
super();
setPreferredSize (new Dimension (IMG_SIZE, IMG_SIZE));
...
}
However the ImagePanel is aligned to the top left corner of the MainPanel rather than centered, so I get a bunch of extra padding at the bottom and right sides, and none at the top and left sides. How do I place it at the center of the MainPanel?
Probably what's happening is that you are drawing your image from (0, 0) which are the top-left corner. Then you set the preferred size to 10 pixels larger which makes the panel larger, but the image is still at (0, 0)
Instead use the same size witoout adding 10, and just use an EmptyBorder for the panel. Also as a recommendation, override getPreferredSize() instead of using setPreferredSize()
public class ImagePanel extends JPanel {
public ImagePanel() {
setBorder(new EmptyBorder(10, 10, 10, 10));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(IMG_SIZE, IMG_SIZE);
}
}
Also you may want to consider using a GridBagLayout for the container panel, for a sure center, if the container is to be larger than the the child panel. Few things you could do. Even consider using a ImageIcon and JLabel instead of painting (if the image doesn't need to be resized (as Camickr(+1) pointed out). A JLabel could easily be made a background by just setting the layout of the label and set it as the content pane of the frame.
ImageIcon icon = new ImageIcon(...)
JLabel frameBackground = new JLabel(icon);
frameBackground.setLayout(new BorderLayout());
frame.setContentPane(frameBackground);
Don't use a JPanel to display an image.
Instead use a JLabel with an ImageIcon.
If you want extra space around the image then you use an EmptyBorder on the label.
I'm wondering why I can't resize my Frame below and have all of the components resize smaller and bigger as I resize frame. Thank you!!!
public class TPASimulatorGUI extends JFrame{
JPanel mainPanel = new JPanel();
BoxLayout layout = new BoxLayout(mainPanel,BoxLayout.Y_AXIS);
mainPanel.setLayout(layout);
// add things to main panel
JPanel it = new JPanel(new FlowLayout(FlowLayout.LEADING));
it.add(mainPanel);
this.getContentPane().add(it);
this.setSize(new Dimension(1190,770));
this.setVisible(true);
}
JPanel it = new JPanel(new FlowLayout(FlowLayout.LEADING));
it.add(mainPanel);
A FlowLayout always respects the preferred size of the components added to it.
Get rid of the "it" panel and try just using
//this.getContentPane().add(it);
add(mainPanel);
The default layout for a frame is a BorderLayout which will try to increase/decrease the size of all components added to it.
I have developed a desktop application. Now in that app I want to add panel with a scrollbar. I am trying using JScrollPane, but its not working.
JPanel paraJPanel = new JPanel();
JScrollPane SP_para_list = new JScrollPane(paraJPanel);
add(SP_para_list).setBounds(10,30,250,350);
This way I am adding scrollbars to panel. But it shows only empty panel with borders. It is not showing components in the panel. Although I have added several labels in it. Is it correct? Is there any other way to add scroll bar to panel.
Thanks in advance
You need to set the PreferredSize for the panel, to make the scrollbar show up, like below.
even you do not set a layout, the panel already has a default layout set.
public static void main(String[] args)
{
JFrame frame = new JFrame();
JPanel panel = new JPanel()
{
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 1000);
}
};
panel.add(new JLabel("Test1"));
panel.add(new JLabel("Test2"));
frame.getContentPane().add(new JScrollPane(panel), BorderLayout.CENTER);
frame.setSize(600, 800);
frame.setVisible(true);
}