How to place components beneath tabs in right oriented JTabbedPane - java

So I just stumbled across placement of tabs in a JTabbedPane to the right and left (i.e. setTabPlacement(JTabbedPane.RIGHT)) which I love the look of. What I need is to utilize the space this leaves beneath the tabs. I currently have a column of JButtons, but they get pushed to the side, leaving a lot of blank space.
Any thoughts on how to do this? Some kind of custom overlay or something?
Here's a screenshot. In the code I basically have one horizontally aligned Box, with the JTabbedPane over a JTree, then the column of buttons after that.
boxOfEverything.add(tabbedPane);
boxOfEverything.add(boxColumnButtons);
Screenshot here.

I made this community wiki because this answer is not mine. #cheesecamera seems to have posted the same question on another forum and got an answer there. I copied the answer so that people coming here looking for an answer can get an answer.
The idea is to use swing's glasspane.
import java.awt.*;
import javax.swing.*;
public class RightTabPaneButtonPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new RightTabPaneButtonPanel().makeUI();
}
});
}
public void makeUI() {
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setTabPlacement(JTabbedPane.RIGHT);
JPanel panel = new JPanel(new GridLayout(0, 1));
for (int i = 0; i < 3; i++) {
JPanel tab = new JPanel();
tab.setName("tab" + (i + 1));
tab.setPreferredSize(new Dimension(400, 400));
tabbedPane.add(tab);
JButton button = new JButton("B" + (i + 1));
button.setMargin(new Insets(0, 0, 0, 0));
panel.add(button);
}
JFrame frame = new JFrame();
frame.add(tabbedPane);
frame.pack();
Rectangle tabBounds = tabbedPane.getBoundsAt(0);
Container glassPane = (Container) frame.getGlassPane();
glassPane.setVisible(true);
glassPane.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.fill = GridBagConstraints.NONE;
int margin = tabbedPane.getWidth() - (tabBounds.x + tabBounds.width);
gbc.insets = new Insets(0, 0, 0, margin);
gbc.anchor = GridBagConstraints.SOUTHEAST;
panel.setPreferredSize(new Dimension((int) tabBounds.getWidth() - margin,
panel.getPreferredSize().height));
glassPane.add(panel, gbc);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Related

Shrinking the JPanel in Swing

I am trying to make a login page but unfortunately my formPanel's border is so out of bounds. Here in the pic you can see the titled border is way out. I need it to be more around my panel with login form:
I see that when creating this formPanel it is that big and the border just surround it. I tried with setPrefferedSize but its not working. How can I fix it?
Here is my code:
public class LoginPanel extends JPanel {
private JLabel title;
public LoginPanel() {
this.setBackground(new Color(0, 128, 43));
this.setBorder(new EmptyBorder(10, 10, 10, 10));
this.setLayout(new BorderLayout());
//adding the title
title = new JLabel("<html><h1><strong><i>Krisko Beatz Quiz</i></strong></h1><hr></html>");
title.setForeground(Color.BLACK);
JPanel titlePanel = new JPanel();
titlePanel.setBackground(new Color(0, 128, 43));
titlePanel.add(title);
this.add(titlePanel, BorderLayout.PAGE_START);
//creating the login form
JPanel formPanel = new JPanel(new GridBagLayout());
formPanel.setBackground(new Color(0, 128, 43));
//gbc
GridBagConstraints gbc = new GridBagConstraints();
//gbc for username
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(5, 0, 0, 0);
JLabel username = new JLabel("Username: ");
username.setForeground(Color.BLACK);
formPanel.add(username, gbc);
//gbc for textfield
gbc.gridx = 1;
gbc.gridy = 0;
JTextField usernameField = new JTextField(10);
formPanel.add(usernameField, gbc);
//gbc for pass
gbc.gridx = 0;
gbc.gridy = 1;
JLabel password = new JLabel("Password: ");
password.setForeground(Color.BLACK);
formPanel.add(password, gbc);
//gbc for pass field
gbc.gridx = 1;
gbc.gridy = 1;
JPasswordField passField = new JPasswordField(10);
formPanel.add(passField, gbc);
//gbc for button
gbc.gridx = 1;
gbc.gridy = 2;
gbc.gridwidth = 2;
gbc.anchor = GridBagConstraints.PAGE_END;
JButton loginButton = new JButton("Login");
formPanel.add(loginButton, gbc);
//add border to the form panel
TitledBorder title = BorderFactory.createTitledBorder("Login");
formPanel.setBorder(title);
this.add(formPanel, BorderLayout.CENTER);
}
}
I tried with setPrefferedSize but its not working.
Don't try to manage the preferredSize of a component.
I would guess the problem is that you are using setSize(...) instead of pack().
You should be using pack() AFTER all the components have been added to the frame. Then all the components will be displayed at their preferred size.
Edit:
I originally misread your question and changed my original answer. The point in my original answer of using the "wrapper" panel is to give extra space to the wrapper panel, while keeping the "formPanel" at a fixed size. This way the titled border will remain around the formPanel even as the frame size is changed.
So again the basic approach for this type of solution is:
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(formPanel, new GridBagConstraints());
this.add(wrapper, BorderLayout.CENTER);
//this.add(formPanel, BorderLayout.CENTER);
I took your LoginPanel class as is, and wrote a Main class around it to start the GUI.
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new LoginPanel());
frame.pack();
frame.setVisible(true);
});
}
}
Especially note, I did no explicit setting of the size, only a pack() call which resizes everything to its preferred size according to your layout.
The resulting layout looks perfectly fine to me.
So the conclusion is: Your LoginPanel is fine, but probably there is something wrong in your other code which you didn't post here.

Reposition whole GridBagLayout

I have a GridBagLayout which is inside a JPanel, but is centered dead in the middle of it.
Essentially, what im trying to do is keep the arrangement the same, but have it moved to where the red arrow is pointing (or even a bit lower). Here is some of the code I wrote:
setLayout(new GridBagLayout());
...make all the JLabels/RadioBtns..
GridBagConstraints gbc1 = new GridBagConstraints();
gbc1.anchor=GridBagConstraints.FIRST_LINE_START;
gbc1.insets = new Insets(5,5,5,5);
gbc1.gridy=0;
gbc1.gridx=0;
add(title, gbc1);
gbc1.gridx=0;
gbc1.gridy=1;
add(block, gbc1);
..add more components
This problem is almost always caused by not setting the GridBagConstraints.weightx and GridBagConstraints.weighty properties correctly. Their default value is 0, which tells the components to bunch up in the center with a near preferredSize size. Give them both 1.0 on all components and watch what happens.
GridBagConstraints gbc1 = new GridBagConstraints();
gbc1.anchor=GridBagConstraints.FIRST_LINE_START;
gbc1.insets = new Insets(5,5,5,5);
// ***** add: *****
gbc1.weightx = 1.0;
gbc1.weighty = 1.0;
This tells the layout to expand in both the x and y directions if the grid bag cell has room to expand.
If this doesn't help, then you'll want to create and post a Minimal, Complete, and Verifiable example.
One more thing: often the best most pleasing layout is achieved if you let all components strive to reach their preferredSize, and this is best done by avoiding calling setSize(...) or setPreferredSize(...) on most components, but rather simply calling pack() on the top level window before displaying it.
Edit
In comment you state:
I have tried this before. It does align the layout into the top right corner, but it also scatters the components across the Panel. Im looking to keep the same clustering. I want all the labels and radiobtns to be close by (like in the pic)
Then what you want to do is use and nest at least two JPanels, the first using GridBagLayout and holding your GUI components as shown above, and the 2nd holding the first GridBagLayout-using JPanel. This 2nd JPanel could use BoxLayout, or FlowLayout(FlowLayout.LEFT), or a bunch of other possible layouts or combinations of layouts.
For example:
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class GridBagLayoutEg extends JPanel {
private static final Insets INSETS = new Insets(5, 5, 5, 5);
private static final int PREF_W = 800;
private static final int PREF_H = 600;
public GridBagLayoutEg() {
JPanel innerPanel = new JPanel(new GridBagLayout());
innerPanel.add(new JLabel("Sequence name: abcdc"), createGbc(0, 0));
GridBagConstraints gbc = createGbc(1, 0);
gbc.gridwidth = 3;
innerPanel.add(new JLabel(), gbc);
innerPanel.add(new JLabel("Block making alighment tool:", SwingConstants.LEFT), createGbc(0, 1));
innerPanel.add(new JRadioButton("Mafft"), createGbc(1, 1));
innerPanel.add(new JRadioButton("Muscle"), createGbc(2, 1));
innerPanel.add(new JRadioButton("ClusteIO"), createGbc(3, 1));
innerPanel.add(new JLabel("Select Codon Table:", SwingConstants.LEFT), createGbc(0, 2));
innerPanel.add(new JRadioButton("Standard"), createGbc(1, 2));
innerPanel.add(new JRadioButton("Custom"), createGbc(2, 2));
innerPanel.add(new JLabel(), createGbc(3, 2));
innerPanel.add(new JLabel("Strictness:", SwingConstants.LEFT), createGbc(0, 3));
innerPanel.add(new JTextField(2), createGbc(1, 3));
innerPanel.add(new JLabel("Degeneracy:", SwingConstants.LEFT), createGbc(0, 4));
innerPanel.add(new JTextField(2), createGbc(1, 4));
setLayout(new FlowLayout(FlowLayout.LEADING, 0, 0));
add(innerPanel);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.insets = INSETS;
gbc.fill = GridBagConstraints.HORIZONTAL;
return gbc;
}
private static void createAndShowGui() {
JFrame frame = new JFrame("GridBagLayoutEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GridBagLayoutEg());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Fix the size of a JScrollPane of JPanels in a JFrame

I am a beginner in Java Swing and I am trying to put a multiple JPanels in a JScrollPanel. The matter is, the JSCrollPannel (named jp in the code) should not fill all the JFrame but it does even if I fix a size with setSize() and a maximal size with setMaximalSize(). What is the trouble? How can I make the JSCrollPane smaller than the JFrame?
package GUI;
import java.awt.*;
import javax.swing.*;
public class MultiPanels {
private JScrollPane getContent() {
Dimension d = new Dimension(300,200);
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc= new GridBagConstraints();
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(getPanel(d, 6, Color.red), gbc);
panel.add(getPanel(d, 4, Color.green.darker()), gbc);
panel.add(getPanel(d, 4, Color.orange), gbc);
panel.add(getPanel(d, 12, Color.blue), gbc);
panel.add(getEmptyPanel(d), gbc);
return new JScrollPane(panel);
}
private JScrollPane getPanel(Dimension d, int rows, Color color) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(color);
GridBagConstraints gbc= new GridBagConstraints();
gbc.insets = new Insets(10,5,10,5);
gbc.weightx = 1.0;
for(int i = 0, j = 1; i < rows; i++) {
gbc.gridwidth = GridBagConstraints.RELATIVE;
panel.add(new JButton(String.valueOf(j++)), gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(new JButton(String.valueOf(j++)), gbc);
}
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setPreferredSize(d);
return scrollPane;
}
private JScrollPane getEmptyPanel(Dimension d) {
JPanel panel = new JPanel() {
protected void paintComponent(Graphics g) {
int w = getWidth();
int h = getHeight();
GradientPaint gp = new GradientPaint(0,0,Color.red,
0,h,Color.cyan);
((Graphics2D)g).setPaint(gp);
g.fillRect(0,0,w,h);
}
};
panel.setPreferredSize(new Dimension(300,400));
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setPreferredSize(d);
return scrollPane;
}
public static void main(String[] args) {
JFrame f = new JFrame();
JScrollPane jp = new MultiPanels().getContent();
jp.setSize(new Dimension(200, 200));
jp.setMaximumSize(new Dimension(200,200));
jp.setPreferredSize(new Dimension(200,200));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(jp);
f.setSize(400,400);
f.setLocation(200,200);
f.setResizable(false);
f.setVisible(true);
}
}
Any time things don't size or arrange correctly, you have to look into Layouts.
Generally, spend more time on:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
To be specific, the default layout of a JPanel and JFrame is BorderLayout which is a very simple layout manager indeed. When you add to a component managed by BorderLayout without saying where, it is automatically added to the center and fills to use all available space:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html#border
It is possible to use "none" (Absolute Positioning) as the layout, but this is almost always a bad idea and you want to think about what you really want to do with the rest of the space in the JFrame: perhaps by letting new child components, with their own size demands, take up some of the space that the main panel is now swallowing up.

How to make jLabels stay attached to the corners of a window form, despite resizing the form in java?

I have 4 jLabels in my java program, which i placed in 4 corners I want them to stay there despite user resizing the window. I have written the code for the labels, but cannot seem to figure out how to keep them glued to each corner.
here is my code for the jLabels
JLabel label_1 = new JLabel("");
label_1.setEnabled(false);
label_1.setBounds(0, 0, 19, 19);
contentPane.add(label_1);
JLabel label_2 = new JLabel("");
label_2.setEnabled(false);
label_2.setBounds(0, 242, 19, 19);
contentPane.add(label_2);
JLabel label_3 = new JLabel("");
label_3.setEnabled(false);
label_3.setBounds(549, 242, 19, 19);
contentPane.add(label_3);
JLabel label_4 = new JLabel("");
label_4.setEnabled(false);
label_4.setBounds(549, 0, 19, 19);
contentPane.add(label_4);
Thanks
Don't use null layouts
Don't use setBounds(...)
Do use proper layout managers. Read the Layout Manager Tutorials for all the gory details.
Note that by using a null layout and setBounds, you ham-string your application's layout to being very rigid, very difficult to debug, enhance, and modify, and you also create a GUI that might look good on your box, but likely will not look good on another box using a different OS, or even the same OS with a slightly different screen resolution.
For example, using a GridBagLayout:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
import static java.awt.GridBagConstraints.*;
public class LabelLayout extends JPanel {
private static final int[] ANCHORS = {NORTHWEST, SOUTHWEST, NORTHEAST, SOUTHEAST};
public LabelLayout() {
setLayout(new GridBagLayout());
for (int i = 0; i < ANCHORS.length; i++) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = i / 2;
gbc.gridy = i % 2;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = ANCHORS[i];
add(new JLabel("Label " + (i + 1)), gbc);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Labels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new LabelLayout());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
A couple other notes:
I try to avoid using GridBagLayouts since they are one of the more complex layouts, but for your problem, they work nicely and simply.
Your problem can also be solved by using nested JPanels each using a simpler layout such as a BorderLayout.
Demo program, iteration number 2 that shows two GUI's, one using GridBagLayout and the other using nested JPanels, each using BorderLayout:
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
import static java.awt.GridBagConstraints.*;
public class LabelLayout {
private static final int[] ANCHORS = { NORTHWEST, NORTHEAST, SOUTHWEST,
SOUTHEAST };
private JPanel gridBagPanel = new JPanel(new GridBagLayout());
private JPanel borderPanel = new JPanel(new BorderLayout());
public LabelLayout() {
for (int i = 0; i < ANCHORS.length; i++) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = i % 2;
gbc.gridy = i / 2;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = ANCHORS[i];
gridBagPanel.add(new JLabel("Label " + (i + 1)), gbc);
}
JPanel northPanel = new JPanel(new BorderLayout());
JPanel southPanel = new JPanel(new BorderLayout());
northPanel.add(new JLabel("Label 1"), BorderLayout.WEST);
northPanel.add(new JLabel("Label 2"), BorderLayout.EAST);
southPanel.add(new JLabel("Label 3"), BorderLayout.WEST);
southPanel.add(new JLabel("Label 4"), BorderLayout.EAST);
borderPanel.add(northPanel, BorderLayout.NORTH);
borderPanel.add(southPanel, BorderLayout.SOUTH);
}
public JPanel getGridBagPanel() {
return gridBagPanel;
}
public JPanel getBorderPanel() {
return borderPanel;
}
private static void createAndShowGui() {
LabelLayout labelLayout = new LabelLayout();
JFrame frame = new JFrame("Label GridBagLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(labelLayout.getGridBagPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame = new JFrame("Label BorderLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(labelLayout.getBorderPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Which layout to use?

I want to make with swing this interface:
And when I resise it I want all the subpanels and buttons to be resized like this:
Not only main window to be resized. I am using GridBagLayout. And I dont know how to stick the borders of the panel with GridBagLayout to the borders of the Frame in that way, when I am resizing the frame the panel also to be resized.
I normally use nested layouts for this.
Use a JPanel with a BorderLayout as the base.
Store your central components in a JPanel, and add this to the CENTER of the BorderLayout.
Store your bottom components in two separate JPanels.
Create another JPanel with a GridLayout of 1 row and 2 columns.
Add the two JPanels to it in the correct order.
Add this JPanel to the SOUTH of the BorderLayout.
The property to achieve this, i.e. when JFrame is resized the JPanel should also resize itself, will be GridBagConstraints.BOTH. It appears to me that your Left JButton is a bit smaller than the Right JButton. If you really wanted to achieve this with GridBagLayout, here I have crafted a small sample code for your help, have a look and ask any question that may arise :
import java.awt.*;
import javax.swing.*;
public class GridBagExample
{
private JPanel contentPane;
private void displayGUI()
{
JFrame frame = new JFrame("GridBag Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setLayout(new GridBagLayout());
JPanel centerPanel = new JPanel();
centerPanel.setOpaque(true);
centerPanel.setBackground(Color.CYAN);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
gbc.weightx = 1.0;
gbc.weighty = 0.9;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.BOTH; // appears to me this is what you wanted
contentPane.add(centerPanel, gbc);
JButton leftButton = new JButton("Left");
JButton rightButton = new JButton("Right");
gbc.gridwidth = 1;
gbc.gridy = 1;
gbc.weightx = 0.3;
gbc.weighty = 0.1;
contentPane.add(leftButton, gbc);
gbc.gridx = 1;
gbc.weightx = 0.7;
gbc.weighty = 0.1;
contentPane.add(rightButton, gbc);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new GridBagExample().displayGUI();
}
});
}
}

Categories

Resources