I'm trying to make positions for my labels i have created and added to a panel.
Right now, I have some text, and an icon. I want to change to position for the icon to be in the bottom.
My code:
frame = new JFrame(); // Create a new frame
frame.setVisible(true); // Makes it visible
frame.setSize(900, 500); // Sets size
frame.setTitle(""); // Sets title
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null); // Sets the window on the center of the screen
//Create temperature panel
temp_panel = new JPanel(); // Creates new JPanel
temp_panel.setBackground(Color.decode("#f1c40f")); // Sets color
//Create temperature label
temp_label = new JLabel("Temperature");
label1 = new JLabel(new ImageIcon(temp_icon));
//Add label to temperature panel
temp_panel.add(temp_label);
temp_panel.add(label1);
// Creates the main panel for all panels
panel = new JPanel();
panel.setLayout(new GridLayout(1, 3));
panel.add(temp_panel);
// Add panel to frame
frame.add(panel);
My goal is to make multiple labels on a panel, and control where they are going to be placed, like this example:
--------------
| TEXT |
| |
| |
| Text |
| |
| |
| |
| Icon |
--------------
Have tried thing like:
temp_label = new JLabel("Temperature", BorderLayout.END.PAGE);
This dont seem to help, because my labels are just positioned in the top.
This doesn't make sense:
temp_label = new JLabel("Temperature", BorderLayout.END.PAGE);
since if you look at the JLabel API, you'll not find a constructor that takes a BorderLayout constant, nor would it make sense even if it were legal. We would sometimes call code like the above -- throwing poop at the wall and seeing what sticks. This heuristic rarely works in programming. You will want to use the Java API resource to avoid making up things like this.
As to your problem, you're adding your JLabel to a JPanel that uses a default FlowLayout. If you want its contents to stack as in your image, give that JPanel a different layout. Here a BoxLayout that uses the PAGE_AXIS sounds about right.
Please check out the layout manager tutorials for more on this and other layouts.
Related
I have a strange problem.
I wanted a date be displayed in the bottom right of my panel.
The problem was, no matter how much I split up the south panels, it wouldn't be in the bottom right, so I found the PAGE_END placement. This works.
The problem is, that every JPanel .SOUTH is overwritten somehow, even if there is more than enough space for it.
Code is partially in german, so to avoid confusion, here is an abstract:
JPanel south has 3 Buttons which are displayed in the center.
JLabel date is 10 characters long and used with the Main JPanel.PAGE_END
edit:
public class bsp {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(1200,600);
JPanel panelall = new JPanel();
JPanel panelsouth = new JPanel();
JPanel panelsouthsouth = new JPanel();
JPanel panelsoutheast = new JPanel();
panelall.setLayout(new BorderLayout());
panelsouth.setLayout(new BorderLayout());
panelsouthsouth.setLayout(new FlowLayout());
panelsoutheast.setLayout(new BorderLayout());
JButton button1 = new JButton("Button1");
JButton button2 = new JButton("Button2");
JButton button3 = new JButton("Button3");
JLabel bottomright = new JLabel ("I should be even further in the bottom right corner");
panelsoutheast.add(bottomright,BorderLayout.EAST);
panelsouthsouth.add(button1);
panelsouthsouth.add(button2);
panelsouthsouth.add(button3);
panelsouth.add(panelsoutheast,BorderLayout.EAST);
panelsouth.add(panelsouthsouth, BorderLayout.SOUTH);
panelall.add(panelsouth, BorderLayout.SOUTH);
frame.add(panelall);
frame.setVisible(true);
}
}
You shouldn't mix absolute and relative positioning constants
Sorry it didn't ring a bell earlier, but the BorderLayout javadoc is pretty clear on it:
Mixing both absolute and relative positioning constants can lead to unpredicable results. If you use both types, the relative constants will take precedence. For example, if you add components using both the NORTH and PAGE_START constants in a container whose orientation is LEFT_TO_RIGHT, only the PAGE_START will be layed out.
The absolute positioning constants are NORTH, SOUTH, EAST, and WEST. The relative positioning constants are PAGE_START, PAGE_END, LINE_START, and LINE_END. Don't mix them: if you start with one type, keep using it.
If you want to have something like this:
+---------------+
| HEADER |
+---------------+
| MAIN CONTENT |
+---------------+
| FIRST FOOTER |
+---------------+
| SECOND FOOTER |
+---------------+
Use the following kind of code:
JPanel mainPanel = getContentPane();
JPanel footerPanel = new JPanel();
mainPanel.add(new JLabel("HEADER"), NORTH);
mainPanel.add(new JLabel("MAIN CONTENT"), CENTER);
mainPanel.add(footerPanel, SOUTH);
footerPanel.add("FIRST FOOTER", NORTH);
footerPanel.add("SECOND FOOTER", SOUTH);
I have a JPanel subclass on which I add buttons, labels, tables, etc. To show on screen it I use JFrame:
MainPanel mainPanel = new MainPanel(); //JPanel subclass
JFrame mainFrame = new JFrame();
mainFrame.setTitle("main window title");
mainFrame.getContentPane().add(mainPanel);
mainFrame.setLocation(100, 100);
mainFrame.pack();
mainFrame.setVisible(true);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
But when I size the window, size of panel don't change. How to make size of panel to be the same as the size of window even if it was resized?
You can set a layout manager like BorderLayout and then define more specifically, where your panel should go:
MainPanel mainPanel = new MainPanel();
JFrame mainFrame = new JFrame();
mainFrame.setLayout(new BorderLayout());
mainFrame.add(mainPanel, BorderLayout.CENTER);
mainFrame.pack();
mainFrame.setVisible(true);
This puts the panel into the center area of the frame and lets it grow automatically when resizing the frame.
You need to set a layout manager for the JFrame to use - This deals with how components are positioned. A useful one is the BorderLayout manager.
Simply adding the following line of code should fix your problems:
mainFrame.setLayout(new BorderLayout());
(Do this before adding components to the JFrame)
If the BorderLayout option provided by our friends doesnot work, try adding ComponentListerner to the JFrame and implement the componentResized(event) method. When the JFrame object will be resized, this method will be called. So if you write the the code to set the size of the JPanel in this method, you will achieve the intended result.
Ya, I know this 'solution' is not good but use it as a safety net.
;)
From my experience, I used GridLayout.
thePanel.setLayout(new GridLayout(a,b,c,d));
a = row number, b = column number, c = horizontal gap, d = vertical gap.
For example, if I want to create panel with:
unlimited row (set a = 0)
1 column (set b = 1)
vertical gap= 3 (set d = 3)
The code is below:
thePanel.setLayout(new GridLayout(0,1,0,3));
This method is useful when you want to add JScrollPane to your JPanel. Size of the JPanel inside JScrollPane will automatically changes when you add some components on it, so the JScrollPane will automatically reset the scroll bar.
As other posters have said, you need to change the LayoutManager being used. I always preferred using a GridLayout so your code would become:
MainPanel mainPanel = new MainPanel();
JFrame mainFrame = new JFrame();
mainFrame.setLayout(new GridLayout());
mainFrame.pack();
mainFrame.setVisible(true);
GridLayout seems more conceptually correct to me when you want your panel to take up the entire screen.
I am using MigLayout I find it flexible etc,but I am having a problem with centring stuff with it. I tried using gapleft 50% but it seems like the percent number needs to change on different frame sizes, because it's also depending on component's size. so if the component is centred using gapleft 25%, it will be on a different location if i resize the width of my frame.
I've tried using just align center and it doesn't nothing at all.
I've also tried new CC().alignX("center").spanX() and same thing:
(source: gyazo.com)
It's sticks to left, however it does work when I use gapleft, why?
super.setLayout(new MigLayout());
this.loginPane = new LoginPanel();
BufferedImage logo = ImageIO.read(new File("assets/logo.png"));
JLabel logoLabel = new JLabel(new ImageIcon(logo));
super.add(logoLabel, new CC().alignX("center").spanX());
It's sticks to left, however it does work when I use gapleft, why?
Based on this single line:
super.setLayout(new MigLayout()); // why super? Did you override setLayout() method?
By default MigLayout rows doesn't fill all available width but only the necessary to display the longest row (based on components width). Having said this your JLabel fits the logo image width and nothing more and it looks like stick to left side. You have to tell the layout manager that it has to fill all available width when you instantiate it:
super.setLayout(new MigLayout("fillx"));
Or
LC layoutConstraints = new LC();
layoutConstraints.setFillX(true);
super.setLayout(new MigLayout(layoutConstraints);
Then, your component constraints will work as expexted.
Picture
Based on this code snippet:
MigLayout layout = new MigLayout("fillx, debug");
JPanel content = new JPanel(layout);
JLabel label = new JLabel("Warehouse");
label.setFont(label.getFont().deriveFont(Font.BOLD | Font.ITALIC, 18));
CC componentConstraints = new CC();
componentConstraints.alignX("center").spanX();
content.add(label, componentConstraints);
Note: you can enable debug feature by doing this:
super.setLayout(new MigLayout("fillx, debug"));
Or
LC layoutConstraints = new LC();
layoutConstraints.setFillX(true);
layoutConstraints.setDebugMillis(500);
super.setLayout(new MigLayout(layoutConstraints);
I have a JFrame that contains two nested JSplitPanes. I want them to be set to an exact proportion on startup.
I can not use setDividerLocation(int) as I don't know the frame's size yet (I maximize it on startup). So, I use the proportional version, setDividerLocation(double).
Code:
// ...
JSplitPane left = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
JSplitPane right = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
right.setResizeWeight(1); // So that I can move the dividers independently
left.setLeftComponent(scrollPane1);
right.setLeftComponent(scrollPane2);
right.setRightComponent(scrollPane3);
left.setRightComponent(right);
add(left, BorderLayout.CENTER);
add(statusLabel, BorderLayout.PAGE_END);
setVisible(true);
setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
left.setDividerLocation(0.3);
right.setDividerLocation(0.7);
// ...
Now, sometimes this works perfectly fine, but sometimes it doesn't change the dividers. I believe this is because the frame is not loaded on screen. From the setDividerLocation(double) docs:
If the split pane is not correctly realized and on screen, this method will have no effect (new divider location will become (current size * proportionalLocation) which is 0).
Is there a way to wait until the frame is "on screen"? This is probably about a few milliseconds, but it still breaks the layout on startup. I would not like to use Thread.sleep with a fixed value but some way that works with Swing.
EDIT: I tried the hack Behe suggested. It did not work, so it might not be about the timing.
EDIT 2: I debugged some more. It appears that this is caused by my resize weight being set to 1. However this is required by my layout.
I found a way. I added a ComponentListener to the inner JSplitPane that notifies me when it is resized by the frame maximizing. When that happens I can then safely set the resize weight.
final JSplitPane left = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
final JSplitPane right = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
left.setDividerLocation(0.3);
right.setDividerLocation(0.3);
left.setLeftComponent(scrollPane1);
right.setLeftComponent(scrollPane2);
right.setRightComponent(scrollPane3);
left.setRightComponent(right);
add(left, BorderLayout.CENTER);
add(status, BorderLayout.PAGE_END);
setVisible(true);
right.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
right.setResizeWeight(1);
}
});
setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
Program ScreenShot
I'm making a animation. When I press on a button it triggers a animation which makes a JPanel float in from the right side. The JPanel gets DeAnimated(JPanel exit animation) when the mouse leaves the JPanel, but the problem is that I have a JButton on the animated JPanel. So the panel does not only disappear when i move the mouse out of the animated JPanel but also when I move the mouse on the button (which is a component of the panel), which means that when I want to click on the button it disappears, because the MouseExit is fired when the mouse leaves the JPanel.
Look at the picture above where I marked certain areas.
Is the JPanel which is getting animated and disappears when i move over the button.
Is the button which causes the JPanel to be DeAnimated.
Is the area which should trigger the DeAnimation of the 1st JPanel.
I have been trying to fix this for a long time now, but I can't get it working. I would really appreciate it if you guys could help me. Thanks!
"but the problem is that I have a JButton on the animated JPanel. "
Don't put the button on the same panel then. Learn to use layout managers. With your image, I would use nested JPanels with BorderLayouts
The right side
JButton button = new JButton();
JPanel animatedPanel = new JPanel();
Add them to another JPanel
JPanel rightPanel = new JPanel(new BorderLayout());
rightPanel.add(button, BorderLayout.NORTH);
rightPanel.add(animatedPanel, BorderLayout.CENTER);
/** result **/
+-----+
| |
| |
+-----+
| |
| |
| |
| |
| |
+-----+
Then create another JPanel to hold the BigPanel and the RightPanel
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel leftBigPanel = new JPanel();
mainPanel.add(leftBigPanel, BorderLayout.CENTER);
mainPanel.add(rightPanel);
/** result **/
*--------------------+-----+
| | |
| | |
| +-----+
| | |
| | |
| | |
| | |
| | |
+--------------------+-----+
The button no longer overlaps the right animated panel
Note : #override the getPreferredSize() in the JPanels for your desired dimension.