How to get the painted size of a Swing component? - java

When I add Swing component (like a JButton) to a JPanel, it renders with it's 'preferred size'.
However, the preferred size is actually larger than the painted button. There appears to be an invisible border around it.
Here's a simple frame with my test panel:
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TestPanel pnl = new TestPanel();
frame.getContentPane().add(pnl);
frame.pack();
frame.setVisible(true);
Here's my test panel ...
public class TestPanel extends JPanel {
JButton btn1 = new JButton("Test1");
JButton btn2 = new JButton("Test2");
public TestPanel() {
this.add(btn1);
this.add(btn2);
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.RED);
Dimension dim = btn1.getPreferredSize();
g.drawRect(btn1.getX(), btn1.getY(), (int)(dim.getWidth()), (int)(dim.getHeight()));
}
}
Notice I painted btn1's "PreferredSize" in RED to demonstrate that the preferredSize is actually larger than the button itself.
My question is, how can I determine the width and height of the painted button, not the JButton's preferredSize?
Any help is greatly appreciated, thanks!
UPDATE
Because I actually need this to work for all Swing components, here's a screen shot with the more components.
Unfortunately, I need to figure this out, determining the "real" size of the visible widget is crucial to my application.

I don't think this is particular or practically achievable.
The problem is, the button is using the "unpainted" area to paint other elements, like the focus highlight.
You could try look at the AbstractButton#set/getMargin

If nothing better comes along, note that the authors "recommend that you put the component in a JPanel and set the border on the JPanel."
Addendum: Based on your comments below, it's clear that your question is not about rendering borders but about establishing a component's boundary. What you perceive as unused space is actually reserved by the UI delegate for any number of uses, e.g. selection highlighting or esthetic coherence. You can get an idea of how this varies by selecting different Look & Feel themes in the examples here and here.
Using getbounds():
Using setBorder():
import component.Laf;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
* #see https://stackoverflow.com/a/15490187/230513
*/
public class Test {
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new FlowLayout());
// https://stackoverflow.com/a/11949899/230513
f.add(Laf.createToolBar(f));
f.add(decorate(new JButton("Test")));
f.add(decorate(new JTextField("Test")));
f.add(decorate(new JTextArea(3, 8)));
f.add(decorate(new JCheckBox("Test")));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JPanel decorate(final JComponent c) {
JPanel p = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle r = c.getBounds();
g.setColor(Color.red);
// NB pen hangs down and to the right
g.drawRect(r.x - 1, r.y - 1, r.width + 1, r.height + 1);
}
};
p.add(c);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test().display();
}
});
}
}

Related

Java : using graphics component within an action listener

I've made a JFrame with Diferent JButtons and i'd like to get an image from another class. Any ideas? Or how draw on the same class but on the action performed?
Because it doesnt let me to do any drawings...my complier always gives me error messages
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.*;
public class red extends JFrame {
public JButton b;
public JButton b1;
public JButton b2;
public JButton b3;
public JButton b4;
public static Image p;
public static Graphics g;
public red() throws IOException {
gui1 x = new gui1();
setTitle(" ");
setSize(1200,700);
setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
b= new JButton("click");
b1= new JButton();
b.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e0){
b1.setBounds(0, 0, 200, 200);
b.show(false);
add(x);
}
});
b.setBounds(0, 0, 100, 100);
add(b1);
add(b);
setVisible(true);
}
public static void main(String[] args) throws IOException {
red k = new red();
}
}
import java.awt.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class gui1 extends Canvas {
public static Image p;
public void paint(Graphics g){
g.drawImage(p, 700, 200, 100, 100, this);
}
{
try {
p= ImageIO.read(new File("Lighthouse.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Phew! I see A LOT of errors in your code (even after I corrected the compilation errors):
You're not following the Java naming conventions:
Class names should be nouns, in mixed case with the first letter of each internal word capitalized
while red is a noun it should be more descriptive and be capitalized. The same goes for gui1
You're extending JFrame which in plain english would say: red is a JFrame, you should really avoid this and create your GUI based on JPanels instead... see Java Swing using extends JFrame vs callint it inside of class
You're setting size (a REAAAAAAALLY big one window for the JButton sizes you're using), instead use pack()
You're using null-layout, while pixel-perfect GUIs might seem like the easiest way to create complex GUIs for Swing newbies, the more you use them the more problems related to this you'll find in the future, they are hard to maintain and cause random problems, they don't resize, etc. Please read Null layout is evil and Why is it frowned upon to use a null layout in Swing? for more information about why you should avoid its use and why you should change your GUI to work with Layout Managers along with Empty Borders for extra spacing between components.
You're making use of a deprecated method JFrame#show() you should be using JFrame#setVisible(...) instead.
Related to point #4, you shouldn't be calling setBounds(...) method, but let that calculations to the layout managers.
You're not placing your program on the Event Dispatch Thread (EDT), Swing is not thread safe, you can fix this by changing your main() method as follows:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Your constructor here
}
});
}
You're mixing AWT and Swing components, instead of using AWT's Canvas use Swing's JPanel which has more functionality and support.
Images will become embedded resources once they're packaged in a JAR file, so it's wise to start treating them as if they already were, not as external files as shown in the embedded-resource tag.
Once you change from Canvas to JPanel you should override its paintComponent(...) method and not paint(...) and call it's super.paintComponent(g) method as the first line, also don't forget to add the #Overrides annotation. See the tutorial on Swing custom painting.
You're abusing the use of static keyword, see how does the static keyword works?
After seeing all the above errors I recommend you to go back and Learn the basics of the language before starting with a graphical environment which will only add more difficulty to your learning.
From what I understand you want to draw an image on a button click, if that's the case then you can wrap your image in a JLabel and add that JLabel to a JPanel which then is added to a parent JPanel which is later added to the JFrame:
As you can see in the GIF above, the icon is displayed after user presses the button.
Obviously this can be improved for the GUI to be more "attractive" with combinations of layout managers and empty borders as stated before.
This was done with the following code:
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageDrawingFromOneClassToAnother {
private JFrame frame;
private JPanel pane;
private JPanel leftPane;
private JPanel rightPane;
private ImageIcon icon;
private JButton button;
private JLabel label;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ImageDrawingFromOneClassToAnother().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
icon = new ImageIcon(this.getClass().getResource("king.png")); //Read images as if they were already embedded resources
button = new JButton("Draw image");
label = new JLabel(""); //Create an empty label
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setIcon(icon); //On button click, we set the icon for the empty label
}
});
pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200); //Set a size for the main panel
}
};
pane.setLayout(new GridLayout(1, 2)); //The main panel
leftPane = new JPanel(); //The button panel
leftPane.setLayout(new BoxLayout(leftPane, BoxLayout.PAGE_AXIS));
leftPane.add(button);
rightPane = new JPanel(); //The panel where the image will be drawn
rightPane.add(label);
//We add both (button and image) panels to the main panel
pane.add(leftPane);
pane.add(rightPane);
frame.add(pane); //Add the main panel to the frame
frame.pack(); //Calculate its preferred size
frame.setVisible(true); //Set it to be visible
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

JPanel size not being set

I'm currently working on an irc bot and today I would like to create a GUI for it.
I'm trying to create a column layout that has two parts, left and right.
The left side will show console output, the right will contain all the controls (joining channels, commands etc).
I'm having issues creating the two columns. I have a JPanel that is the whole width and height of the window and has a border of 10 pixels, and then I have two panels within that; left and right.
The left and right panels are for some reason taking the whole size of the window, and the right panel is overlapping everything.
Here's an example picture: http://i.imgur.com/lc4vHVH.png
The white is the right panel, it should only be half the size and have an identical but black panel on the left of it.
Here's my current code, sorry if it's messy, new to the whole Swing GUI.. Thanks for any help.
package tk.TaylerKing.GribbyBot;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.BorderFactory;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.alee.laf.WebLookAndFeel;
import com.alee.laf.menu.WebMenuBar;
import com.alee.laf.menu.WebMenuItem;
import com.alee.laf.panel.WebPanel;
import com.alee.laf.rootpane.WebFrame;
public class GribbyBot extends WebFrame {
private static final long serialVersionUID = 4641597667372956773L;
public static HashMap<String, ArrayList<String>> connections = new HashMap<String, ArrayList<String>>();
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(WebLookAndFeel.class.getCanonicalName());
SwingUtilities.invokeLater(new Runnable(){
public void run(){
GribbyBot gb = new GribbyBot();
gb.setVisible(true);
}
});
}
public GribbyBot(){
WebPanel panel = new WebPanel();
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.setPreferredSize(new Dimension(780, 580));
WebMenuBar menu = new WebMenuBar();
WebMenuItem file = new WebMenuItem("Exit");
file.setMnemonic(KeyEvent.VK_E);
file.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
menu.add(file);
setJMenuBar(menu);
WebPanel left = new WebPanel();
left.setPreferredSize(new Dimension(380, 580));
left.setBackground(Color.BLACK);
WebPanel right = new WebPanel();
right.setPreferredSize(new Dimension(380, 580));
right.setBackground(Color.WHITE);
add(panel);
panel.add(left);
panel.add(right);
setTitle("GribbyBot");
setSize(800, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
}
}
On a side note, all the variables that are prefixed with "Web" are the same as Swing, but it's a custom GUI.
Override JComponent#getPreferredSize() instead of using setPreferredSize()
Read more Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
If extremely needed in case of Performing Custom Painting then try in this way:
Sample code:
final JPanel panel = new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
// your custom painting code here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(40, 40);
}
};
Why are using setPreferredSize() method whereas you can achieve this design easily using any proper layout such as BoxLayout, GridLayout, BorderLayout etc.
Read more about layout How to Use Various Layout Managers
EDIT
try JPanel panel = new JPanel(new GridLayout(1,2));

Java JTabbedPane Inset Color

I was wondering how you would get the color of the inset of a JTabbedPane. I cannot seem to get this color. Every attempt I make I get 236,236,236 which is the outside frame color, where the inside frame color is about 10 darker, 227,227,227 (using the built in apple color meter).
I am setting the look and feel using UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
You can see this in an image that I found on the internet. http://pagesofinterest.net/wordpress/wp-content/uploads/2009/06/Quaqua-Maven-Netbeans.jpg Where the words "Panel's Title" is the area that I am getting the lighter color that is not useful to me. Inside the round corners is the darker color I am trying to obtain. I tried getting the color of the content pane to no avail.
Thanks for all your help!
**EDIT:**Added code! As you see, I am trying to get the color of the area inside the rounded corners(if your on a mac) not the color of the frame or the tabs that say "1" "2". I have attached a photo and I am trying to get the background color of the portion that says "Here" Thanks!
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
public class main {
JFrame frame;
Container c1 = new Container();
Container c2 = new Container();
JTabbedPane top = new JTabbedPane();
static main GUI;
public void createGUI(){
frame = new JFrame();
Container c = frame.getContentPane();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
top = new JTabbedPane(JTabbedPane.TOP);
top.setFocusTraversalKeysEnabled(false);
top.setFocusable(false);
top.addTab("1", c1);
top.addTab("2", c2);
frame.setSize(315,450);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setResizable(true);
c.add(top);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {}
GUI = new main();
GUI.createGUI();
}
}
EDIT: camickr, Here is a screenshot of the UIManager Defaults. Unfortunately none of there colors in the are the correct color that the inset is.
You might be able to use UIMangaer Defaults to find the color.
You can override paintComponent() to use a GradientPaint in the tab's background, as shown below. A few notes,
Let the content adopt the preferred size of it contents, as shown here.
Construct the GUI in the event dispatch thread.
Use conventional Java names.
Addendum: the elements are not always in the same spot, so I do not know what place to get the color.
It sounds like you want to match a color used internally by the TabbedPaneUI delegate. One approach would be as follows:
Render a BufferedImage of the component, as shown here.
Determine the coordinates of a Point in top relative to the top of c1.
Point p = SwingUtilities.convertPoint(c1, 0, -1, top);
Obtain the color using getRGB(), as shown here; use Zoom to verify the result.
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
/** #see https://stackoverflow.com/a/16625260/230513 */
public class Main {
JFrame frame;
Container c1 = new GradientPanel();
Container c2 = new GradientPanel();
JTabbedPane top = new JTabbedPane();
private static class GradientPanel extends JPanel {
public GradientPanel() {
this.add(new JLabel("Here"));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
GradientPaint p = new GradientPaint(0, 0, Color.white,
getWidth(), getHeight(), Color.gray);
g2d.setPaint(p);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
public void createGUI() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
top = new JTabbedPane(JTabbedPane.TOP);
top.addTab("1", c1);
top.addTab("2", c2);
frame.add(top);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Main().createGUI();
}
});
}
}

drawing a line in Java - line is not visible

I am learning Java on my own. Trying to create a frame with a line in it. It seemed pretty basic, but I can't see the line. The code compiles and I can't seem to understand why I can't see the line. I see other components in the frame.
I am using 2 java files. One file is container file and the other file has the draw line code. They are part of package a1.
Here is my code (please help):
Container File:
package a1;
import javax.swing.*;
import java.awt.*;
public class gameContainer {
public static void addComponentsToPane(Container pane) {
pane.setLayout(null);
//add button to the pane
JButton b3 = new JButton("B1");
pane.add(b3);
//add line to the pane
drawingLine line1 = new drawingLine();
pane.add(line1);
//size and position all relatively
Insets insets = pane.getInsets();
Dimension size;
size = b3.getPreferredSize();
b3.setBounds(350+insets.left,15+insets.top,size.width+50,size.height+20);
size = line1.getPreferredSize();
line1.setBounds(350+insets.left,75+insets.top,size.width+50,size.height+20);
}
private static void createAndShowGUI() {
int l = 200, w = 80;
//Create and set up the window.
JFrame frame = new JFrame("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up content pane
addComponentsToPane(frame.getContentPane());
//add menu bar
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menu.add(new JMenuItem("Do nothing"));
menuBar.add(menu);
frame.setJMenuBar(menuBar);
// size and display root pane/window
Insets insets = frame.getInsets();
frame.setSize(500+insets.left+insets.right,300+insets.top+insets.bottom);
frame.setLocation(w,l);
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Draw line File:
package a1;
import javax.swing.*;
import java.awt.geom.Line2D;
import java.awt.Graphics2D;
import java.awt.Graphics;
public class drawingLine extends JPanel{
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Line2D line = new Line2D.Double(200, 300, 1000, 1000);
//g2d.setColor(Color.black);
g2d.draw(line);
//g.drawLine(200, 300, 1000, 1000);
//g.setColor(color.BLACK);
}
}
Why am I not able to see the line?
Your main problem is that you use null/Absolute layout.
You should have a read here:
Laying Out Components Within a Container
1) You should use an appropriate LayoutManager (or nest together multiple LayoutManagers) and/or override getPreferredSize() of JComponent to return correct dimensions which fit the drawings.
2) Dont call setSize on JFrame rather call pack() before setting JFrame visible (with above in mind)
3) No need for adding to contentPane via getContentPane().add(..) as add(..) setLayout(..) and remove(..) have been forwarded to the contentPane.
4) Watch class names, stick to the java convention a class name begins with a capital letter and each new word thereafter the first letter should be capitilized i.e gameContainer should be GameContainer, drawingLine should be DrawingLine
Here is your code with above fixes implemented (not the most well layed out, but its only an example):
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class GameContainer {
public static void addComponentsToPane(JFrame frame) {
JPanel buttonPanel=new JPanel();//create panel to hold button
//add button to the pane
JButton b3 = new JButton("B1");
buttonPanel.add(b3);
frame.add(buttonPanel, BorderLayout.EAST);//use contentPane default BorderLayout
//add line to the pane
DrawingLine line1 = new DrawingLine();
frame.add(line1);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up content pane
addComponentsToPane(frame);
//add menu bar
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Menu");
menu.add(new JMenuItem("Do nothing"));
menuBar.add(menu);
frame.setJMenuBar(menuBar);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
class DrawingLine extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Line2D line = new Line2D.Double(10, 10, 100, 100);
g2d.draw(line);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
}
The proper (better to say, easier, much less error prone) way to do it has been shown by David Kroukamp. As for your original question, modify the original code like this:
line1.setBounds(350+insets.left,75+insets.top,size.width+50,size.height+20);
line1.setBorder(BorderFactory.createEtchedBorder()); // add this line
Your line starts at point 200,300 but the panel you're drawing it in has width of 50+10 and height of 20+10 - on my computer at least - which means that the line is outside of the drawingLine panel and that's why it doesn't get drawn. To verify that modify the line in your original drawingLine.paintComponent like this:
Line2D line = new Line2D.Double(0, 0, 1000, 1000);
and you will see the following result:
This line in your original code:
pane.setLayout(null);
is pretty clear - you are using no layout manager, or in other words you chose to use absolute positioning. This means that the coordinates, widths and heights of components must be precalculated and set by you. But if you make a mistake somewhere (as your example nicely shows) it'll be hard to detect. Not to mention, for example if you want to handle window resizing. That's why LayoutManagers exist.
I recommend reading also:
Using Layout Managers
Solving Common Layout Problems

Java Swing: problems with width

I have problems with understanding the behavior of my application. I want to create a simple window (1000x700px), divided into two parts (250px and 750px width respectively). I tried the following code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame
{
private static final long serialVersionUID = 1L;
public Example()
{
this.setSize(1000, 700);
this.setTitle("Example");
this.setResizable(false);
this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
JPanel navigation_panel_wrap = new JPanel();
JPanel content_panel_wrap = new JPanel();
navigation_panel_wrap.setPreferredSize(new Dimension(250, 700));
content_panel_wrap.setPreferredSize(new Dimension(750, 700));
content_panel_wrap.setBackground(Color.green);
navigation_panel_wrap.setBackground(Color.red);
this.getContentPane().add(navigation_panel_wrap);
this.getContentPane().add(content_panel_wrap);
}
public static void main(String[] args)
{
Example example = new Example();
example.setVisible(true);
}
}
As you can see I manually set layout manager for JFrame (FlowLayout instead of BorderLayout with zero horizontal and vertical gaps). Of course, I can just use BorderLayout and than use add() method with BorderLayout.EAST and BorderLayout.WEST parameters, but I want to understand what's wrong with FlowLayout.
When I run my application, I get the following (no green JPanel):
If I decrease width of, for example, content_panel_wrap and make it 744px instead of 750px, everything works correctly.
So the question is - what are these strange 6 pixels? I'm not sure this value is constant for all operating systems, so I want to understand its origin.
There's nothing wrong with FlowLayout but you will need to call pack() for all components to be sized.
As for your codes problem (+1 to #Reimeus) calling pack() is the solution.
as per docs:
Causes this Window to be sized to fit the preferred size and layouts
of its subcomponents. If the window and/or its owner are not yet
displayable, both are made displayable before calculating the
preferred size. The Window will be validated after the preferredSize
is calculated.
Tips:
Dont extend JFrame unnecessarily.
Use Event Dispatch Thread when creating and changing UI components:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// create UI components etc here
}
});
Dont call setPreferredSize() rather override getPrefferedSize() of component.
Dont call setSize(...) on JFrame rather call JFrame#pack() before setting it visible.
Dont forget to call JFrame#defaultCloseOperation(..) or your initial/EDT thread will not be terminated when JFrame is closed.
Here is an example combining my advice and your code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Example {
private final JFrame frame;
public Example() {
frame = new JFrame();
frame.setTitle("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//app exited when frame closes
frame.setResizable(false);
frame.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
JPanel navigation_panel_wrap = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(250, 700);
}
};
JPanel content_panel_wrap = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(750, 700);
}
};
content_panel_wrap.setBackground(Color.green);
navigation_panel_wrap.setBackground(Color.red);
frame.add(navigation_panel_wrap);
frame.add(content_panel_wrap);
//pack frame (size components to preferred size)
frame.pack();
frame.setVisible(true);//make frame visible
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
}

Categories