I have a JFrame which contains just one JPanel.
I have tried setting the Panel's size and packing the frame, but that has no effect.
If I set the JFrame's size, it will change the size so it includes the title bar and borders.
How do I set the "actual size" so it doesn't include the title bar and borders?
Example:
Thanks in advance, guys
You could set the contentPane's preferredSize and call pack on the JFrame, but in general it's usually best to let components size themselves based on their preferred sizes as determined by their layout managers.
This is an example of setting JPanel's size and packing the frame:
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 200));
frame.add(panel);
frame.pack();
frame.setVisible(true);
Did you try something like this?
If you set the preferred size of the JPanel then the JFrame's pack() method will respect it.
Use the .getInsets method on JFrame which gives you the dimensions of the sizes around the non-client area.
Then add it up to your wanted size, and set the size using setSize.
If you want to get Frame border then first use pack on your frame and after that get Frame Insets like in this code bellow:
frame.pack();
Insets insets = frame.getInsets();
int frameLeftBorder = insets.left;
int frameRightBorder = insets.right;
int frameTopBorder = insets.top;
int frameBottomBorder = insets.bottom;
Is better to use the pack method right after your setResizable(boolean) method, because resizable for some reason changes your frame borders, but if you dont use resize method then use pack method right on the start of frame constructor.
Setting the actual size of the usable space in JFrame could be done through setting the preferred size of the container in
createComponents(Container container) method. Done in this way, you skip setting the size of
the whole JFrame through setPreferredSize(new Dimension (width, length) in the run() method. So, the code will look like this:
#Override
public void run() {
JFrame frame = new JFrame();
// other code ...
this.createCompoents(frame.getContentPane());
}
private void createCompoents(Container container) {
// other code ...
container.setPreferredSize(new Dimension(width, length));
}
Related
I have multiple JTextAreas inside a JPanel. I am using a BoxLayout to make them align vertically and fill the width of the container.
It works, but they seem to expand to fill the entire height as well.
What I really want is simple - a text area that wraps text where I can control the width but allow the height to scale dynamically as more lines are added. The above method was just my best attempt at it. If there is a solution that uses a different layout manager, different text component, etc, that works.
minimal verifiable example below:
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(300, 300));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel textAreas = new JPanel();
textAreas.setLayout(new BoxLayout(textAreas, BoxLayout.Y_AXIS));
JTextArea area1 = new JTextArea();
area1.append("this is a string");
area1.setLineWrap(true);
area1.setWrapStyleWord(true);
textAreas.add(area1);
JTextArea area2 = new JTextArea("and another that is much longer, so that it wraps to the next line");
area2.setLineWrap(true);
area2.setWrapStyleWord(true);
textAreas.add(area2);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(textAreas);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
}
I have done research on this topic on my own, including looking at different layout managers (http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html), and checking other questions on the site, but I haven't had much luck.
TLDR: Can I make it so each element of a layout has a height that scales to its content but a fixed width? If so how?
What I really want is simple - a text area that wraps text where I can control the width but allow the height to scale dynamically as more lines are added.
The BoxLayout respects the maximum size so the text area grows to fill all the space available in the panel. You can override the getMaximumSize() method to return the preferred height by using something like:
JTextArea area1 = new JTextArea()
{
public Dimension getMaximumSize()
{
Dimension d = super.getMaximumSize();
d.height = getPreferredSize().height;
return d;
}
};
It works...
Not really. Make the frame wider and the text will unwrap. Then shrink the frame and the scrollbar will appear. That is the text will not wrap again
What you need to do is force the panel added to the scroll pane to be the same width as the viewport. This will allow wrapping to work properly.
You do this by implementing the Scrollable interface on the panel. Specifically you need to override the getScrollableTracksViewportWidth() method to return true.
Or an easier solution is to use the Scrollable Panel class which allows you to set properties of the panel to control this behaviour.
You can replace a JPanel with the ScrollablePanel:
//JPanel textAreas = new JPanel();
ScrollablePanel textAreas = new ScrollablePanel();
textAreas.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
Edit:
If there is a solution that uses a different layout manager
Without overriding the getMaximumSize() method of the text areas and when using the Scrollable Panel you should be able to use the following layout managers.
The GridBagLayout allows you to specify the "weightx" constraint. This will allow the component to fill all the available space in the panel.
Or if you don't like specifying all the constrains of the GridBagLayout you could use the Relative Layout which support vertical/horizontal layout of components at their preferred size.
You would just need to use the following to force the component to fill the horizontal space:
//textAreas.setLayout(new BoxLayout(textAreas, BoxLayout.Y_AXIS));
RelativeLayout rl = new RelativeLayout(RelativeLayout.Y_AXIS);
rl.setFill( true );
textAreas.setLayout(rl);
I am a beginner. I am programming a Java game, and I am having trouble changing the size of the button buttonPlayAgain. The size of the button does not change using the code below. How can I change the size of the button?
Here is my code:
public hoppa(IModele modele) {
super(new GridLayout(1, 1));
setSize(VueGrille.FACT * modele.getGrille().getLongueur(), 1);
Dimension dim = new Dimension(1, 1);
labMines = new JLabel();
labMines.setPreferredSize(dim);
add(labMines);
buttonPlayAgain = new JButton("New Game");
//buttonPlayAgain.setSize(1, 1);
buttonPlayAgain.setPreferredSize(new Dimension(50,50));
add(buttonPlayAgain);
labTimer = new JLabel();
labTimer.setPreferredSize(dim);
add(labTimer);
initValues(modele);
}
It can be normal that your button is not resized while calling setPreferredSize. try setSize instead. See Java: Difference between the setPreferredSize() and setSize() methods in components
Use setSize() if your component's parent has no layout manager, and setPreferredSize() (see also setMinimumSize and setMaximumSize) if it does.
setSize() most likely won't do anything if the component's parent is using a layout manager
So I'm pretty new to GUI, and came across the problem that whatever I set my preferred size to ( via setPreferredSize(new Dimension(width, height)) ) it adds 10 to both width and height. I was wondering, why does this happen? Yes I understand that it is "preferred size" but surely there is a way to prevent this. I can fix it by simply subtracting 10 from width and height before passing it to the method, but I was wondering what was going on.
My (relevant) Code:
Main method:
public static void main(String[] args)
{
final App app = new App(500, 500);
JFrame frame = new JFrame("Block Stacker 3000");
frame.getContentPane().add(app);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
System.out.println(app.getSize());
app.start();
}
App constructor (extends JPanel):
public App(int width, int height)
{
this.width = width;
this.height = height;
System.out.println(width + " " + height);
setPreferredSize(new Dimension(width , height));
setBackground(Color.CYAN);
}
When run, it outputs the following:
500 500
java.awt.Dimension[width=510,height=510]
Also, I've tried using setMinimumSize() and setMaximumSize() but neither really affected anything.
The size of your JPanel is going to be determined by the layout manager handling the components in its container. JFrame has a default layout manager, so there is one even though you are not setting it. Some layout managers pay attention to preferred size, some don't, some pay more attention to minimum/maximum size than others.
You can set a "null layout manager", also known as "absolute positioning", and control all the sizes yourself, but I would think you aren't trying to do that (since you are setting a "preferred" size). What you will need to do to design your UI is figure out what relative sizes and positions you want things to have AND what you want to happen to them when the size of the window changes; that determines which layout managers go onto and into which container panels and the container panels that contain them, etc.
And I wouldn't eliminate frame.pack(); it essentially tells the layout manager to do its stuff, and you usually WANT the layout manager to handle things once you get them set up the way you want them...
I copied/pasted your code and got the following output:
500 500
java.awt.Dimension[width=510,height=530]
But then, I toke a screenshot of the frame:
If you download the picture and check the file properties, you will see that it is 502 pixels width (due to the window 1 pixel thin border) and 531 pixels height (due to the window title bar 31 pixels height), checking the image in gimp, I could find that the Cyan area is in fact 500x500 pixels wide.
UPDATE: Move the setResizable(false) sentence to the line after frame.setVisible(true);:
JFrame frame = new JFrame("Block Stacker 3000");
frame.getContentPane().add(app);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setResizable(false);
After that, it will print:
500 500
java.awt.Dimension[width=500,height=500]
You must call pack() after calling setResizable(false), because when window is resizeable, layout manager will leave 10px margin for (potential) scrollbars.
public static void main(String[] args) {
final App app = new App(500, 500);
JFrame frame = new JFrame("Block Stacker 3000");
frame.getContentPane().add(app);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
System.out.println(app.getSize());
app.start();
}
I was trying out JLayeredPane. So, in the following code, I created a JLayeredPane and a JLabel. I added the label to the layered pane, which I added to a JPanel. This panel was then added to a JFrame.
public static void main(String[] args) {
frame = new JFrame("LayeredPane Example");
frame.setPreferredSize(new Dimension(500,500));
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(400, 400));
JLabel label = new JLabel("Label on LayeredPane");
label.setLocation(200, 200);
System.out.println("Width " + label.getWidth() );
label.setBounds(20, 20, 400, 40);
layeredPane.add(label);
layeredPane.setLayer(label, 10, 1);
frame.setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.add(layeredPane);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
Now the problem is that if I do not have the statement label.setBounds(20, 20, 400, 40);, then the label does not appear on the layered pane. This raises two questions:
Why is setBounds so important?
Probably a part of my previous questions answer, the label had an initial height and width of 0 before setting bounds, which might be the reason setBounds is important. In that case, I want to know how can I determine appropriate bounds for a Swing component when I am adding it to a JLayeredPane. (If my bounds are less than the appropriate size of the component, the component will appear hidden)
Edit:
The first question was answered earlier in more detail here.
Regarding:
Why is setBounds so important: A JLayeredPane uses essentially a null layout, and whenever you use null layouts, you the coder are completely responsible for both the size and position of the components that you add. That's simply the rules of this layout.
How to determine the appropriate bounds: One thing I've done is simply to let the component tell me what its preferredSize is and then use it for its size:
myJLabel.setSize(myJLabel.getPreferredSize());
Another thing I've done is to use non-opaque JPanels for each layer of my JLayeredPane, give these JPanels appropriate layouts and then add my components to the appropriate layer JPanel. I then use a listener to be sure that the layer JPanel's size matches that of its JLayeredPane container.
I'm trying to implement a quite simple UI using SpringLayout (partly because I, as opposed to most tutorial writers I find on the net, quite like the coding interface compared to other layout managers and partly because I want to learn how to use it). The UI basically looks like this:
This is all well. The UI resizes the way I want (keeping the welcome text centered and expanding the text area to fill all the new available space) if I increase the window size. However, below a certain point (more specifically when the window becomes too narrow for the welcome text):
I would like the window to not allow further shrinking, so that if the user tries to shrink the window to a size smaller than enough to house the components, it simply stops. How do I accomplish this, using the SpringLayout layout manager?
I know I could probably do this by handling some resize-event and checking if the minimum size is reach, and then just set the size to the minimum size. But this requires me to a) know, or know how to calculate, the minimum size of the window, even before it renders, b) write a bunch of event-handling code just to get some UI rendering right, and c) write a bunch of code for things that I expect a good layout manager to take care of ;)
you can override MinimumSize for TopLevelContainer
you have put JTextArea to the JScrollPane
easiest way is mixing LayoutManagers (called as NestedLayout) by spliting GUI to the parts (separated JPanels with same or different LayoutManager), rather than implements some most sofisticated LayoutManager (GridBagLayout or SpringLayout) for whole Container
some LayoutManagers pretty ignore setXxxSize
SpringLayout isn't my cup of Java
import java.awt.*;
import javax.swing.*;
public class MinSizeForContainer {
private JFrame frame = new JFrame("some frame title");
public MinSizeForContainer() {
JTextArea textArea = new JTextArea(15, 30);
JScrollPane scrollPane = new JScrollPane(textArea);
CustomJPanel fatherPanel = new CustomJPanel();
fatherPanel.setLayout(new SpringLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(fatherPanel, BorderLayout.CENTER);
frame.setLocation(20, 20);
frame.setMinimumSize(fatherPanel.getMinimumSize());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MinSizeForContainer Mpgp = new MinSizeForContainer();
}
});
}
}
class CustomJPanel extends JPanel {
private static final long serialVersionUID = 1L;
#Override
public Dimension getMinimumSize() {
return new Dimension(400, 400);
}
}
There are several issues to achieve a "real" (that is not shrinkable beyond) min size:
the child components must return some reasonable (based on their content) min size, many core components don't
the layoutManager must respect the compounded min of all children, no matter how little space is available
the top-level container (here the JFrame) must not allow shrinking beyond the min
The first is true for a JLabel, the second is met for SpringLayout (that's why the label is truncated) - which leaves the third as the underlying problem, the solution to which isn't obvious, actually I wasn't aware it's even possible before running #mKorbel's example. The relevant line indeed is
frame.setMinimumSize(someSize);
With that line in place, it's not possible to shrink the frame below. Without, it is. Starting from that observation, some digging turns out the doc for its override in Window
Sets the minimum size of this window to a constant value. [..] If
current window's size is less than minimumSize the size of the window
is automatically enlarged to honor the minimum size. If the setSize or
setBounds methods are called afterwards with a width or height less
[...] is automatically enlarged to honor the minimumSize value.
Resizing operation may be restricted if the user tries to resize
window below the minimumSize value. This behaviour is platform-dependent.
Looking at the code, there are two (implementation, don't rely on them :-) details related to the min size
Dimension minSize;
boolean minSizeSet;
and public api to access
public Dimension getMinimumSize()
public boolean isMininumSizeSet()
the first rather oldish (jdk1.1), the latter rather newish (jdk1.5) - implying that the first can't rely on the latter but internally has to check for a null minSize. The overridden sizing methods (with their guarantee to doing their best to respect a manually set minSize) on Window are the latest (jdk6) and do rely on the latter. Or in other words: overriding isMinimumSizeSet does the trick.
Some code snippet (beware: it's a hack, untested, might well be OS dependent with undesirable side-effects!):
// JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("some frame title") {
/**
* Overridden to tricks sizing to respect the min.
*/
#Override
public boolean isMinimumSizeSet() {
return true; //super.isMinimumSizeSet();
}
/**
* Overridden to adjust for insets if tricksing and not using
* LAF decorations.
*/
#Override
public Dimension getMinimumSize() {
Dimension dim = super.getMinimumSize();
// adjust for insets if we are faking the isMinSet
if (!super.isMinimumSizeSet() && !isDefaultLookAndFeelDecorated()) {
Insets insets = getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.bottom + insets.top;
}
return dim;
}
};
// add a component which reports a content-related min
JLabel label = new JLabel("Welcome to my application!");
// make it a big min
label.setFont(label.getFont().deriveFont(40f));
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);