i am trying to make a login page just like facebook, but the code i have written is not showing it on the top left side instead it is showing at the centre of page, i am using GridBagLayout and anchore for setting text at the FIRST_LINE_END.
final JFrame f2=new JFrame("Admin Main");
f2.setSize(1350,730);
f2.setVisible(true);
f1.setVisible(false);
f2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);![enter image description here][2]
GridBagLayout gbl=new GridBagLayout();
final JPanel p2=new JPanel(gbl){
private Image img = ImageIO.read(new File("F:\\Untitled Folder\\Rohan\\football2.jpg"));
#Override
protected void paintComponent( Graphics g ) {
super.paintComponent(g);
g.drawImage(img, 0,0,1366,730, null);
}
};;
GridBagConstraints g2=new GridBagConstraints();
g2.insets=new Insets(3,3,3,3);
JLabel l2=new JLabel("Admin ID",JLabel.LEFT);
JLabel l3=new JLabel("Password",JLabel.LEFT);
l2.setFont(new Font("TimesRoman",Font.BOLD,16));
l2.setForeground(Color.BLUE);
l2.setBackground(Color.WHITE);
l3.setFont(new Font("TimesRoman",Font.BOLD,16));
l3.setForeground(Color.BLUE);
l3.setBackground(Color.WHITE);
final JTextField t1=new JTextField(15);
final JPasswordField pw1=new JPasswordField(15);
JButton b3=new JButton("Back");
JButton b4=new JButton("Sign in");
f2.add(p2);
g2.anchor=GridBagConstraints.FIRST_LINE_END;
g2.gridx=1;
g2.gridy=1;
p2.add(l2,g2);
g2.gridx=2;
g2.gridy=1;
p2.add(t1,g2);
g2.gridx=1;
g2.gridy=2;
p2.add(l3,g2);
g2.gridx=2;
g2.gridy=2;
p2.add(pw1,g2);
g2.gridx=1;
g2.gridy=3;
p2.add(b3,g2);
g2.gridx=2;
g2.gridy=3;
p2.add(b4,g2);
I see two problems in your current layout:
You put your login panel in the center of the parent BorderLayout (so your panel gets stretched to the size of its container)
You have nothing in your GridBagLayout that will "push" your components to the top and to the left.
There are several options here:
You nest your login panel into several panels (for example using BorderLayout, once with the constraint NORTH and the second time with the constraint WEST).
Add your loginPanel to the WEST and you add a "filler" component to the bottom of the GridBagLayout in order to push the other components to the top.
Here is a demo of the second solution:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TestLoginGridBagLayout {
protected void initUI() throws MalformedURLException {
JFrame frame = new JFrame("Admin Main");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel background = new JLabel(new ImageIcon(new URL(
"http://media1.santabanta.com/full1/Football/Football%20Abstract/football-abstract-6a.jpg"))) {
#Override
public Dimension getPreferredSize() {
Dimension preferredSize = super.getPreferredSize();
Dimension layoutPreferredSize = super.preferredSize();
preferredSize.width = Math.max(preferredSize.width, layoutPreferredSize.width);
preferredSize.height = Math.max(preferredSize.height, layoutPreferredSize.height);
return preferredSize;
}
};
background.setLayout(new BorderLayout());
frame.add(background);
GridBagLayout gbl = new GridBagLayout();
final JPanel loginPanel = new JPanel(gbl);
loginPanel.setOpaque(false);
background.add(loginPanel, BorderLayout.WEST);
JLabel adminIDLabel = new JLabel("Admin ID", JLabel.LEFT);
JLabel passwordLabel = new JLabel("Password", JLabel.LEFT);
adminIDLabel.setFont(new Font("TimesRoman", Font.BOLD, 16));
adminIDLabel.setForeground(Color.BLUE);
adminIDLabel.setBackground(Color.WHITE);
passwordLabel.setFont(new Font("TimesRoman", Font.BOLD, 16));
passwordLabel.setForeground(Color.BLUE);
passwordLabel.setBackground(Color.WHITE);
final JTextField adminID = new JTextField(15);
final JPasswordField password = new JPasswordField(15);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
buttonPanel.setOpaque(false);
JButton back = new JButton("Back");
JButton signIn = new JButton("Sign in");
buttonPanel.add(back);
buttonPanel.add(signIn);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(3, 3, 3, 3);
gbc.anchor = GridBagConstraints.FIRST_LINE_END;
loginPanel.add(adminIDLabel, gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
loginPanel.add(adminID, gbc);
gbc.gridwidth = 1;
loginPanel.add(passwordLabel, gbc);
gbc.gridwidth = GridBagConstraints.REMAINDER;
loginPanel.add(password, gbc);
loginPanel.add(buttonPanel, gbc);
GridBagConstraints gbcFiller = new GridBagConstraints();
gbcFiller.weightx = 1.0;
gbcFiller.weighty = 1.0;
gbcFiller.fill = GridBagConstraints.BOTH;
loginPanel.add(Box.createGlue(), gbcFiller);
frame.pack();
frame.setVisible(true);
}
/**
* #param args
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new TestLoginGridBagLayout().initUI();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
}
I also took the liberty of:
Rename your variables to meaningful names (it makes your code easier to read for others)
Replace your custom background image panel with a JLabel
Move your buttons to a nested panel with another LayoutManager
Take another background image since I don't have yours.
If you want it explicitly to be in the top left I'd rather use the NORTHWEST anchor. FIRST_LINE_END for text flowing left to right would also put the text on the right corner and the other way around for right to left.
Also, switch gridx and gridy to start at 0 instead of 1. And increment from as needed from there.
So for example:
g2.anchor=GridBagConstraints.NORTHWEST;
g2.gridx=0;
g2.gridy=0;
p2.add(l2,g2);
g2.gridx=1;
g2.gridy=0;
p2.add(t1,g2);
/*And so on for the rest of the block*/
Use FIRST_LINE_START as anchor value.
g2.anchor=GridBagConstraints.FIRST_LINE_START;
Related
I tried make a java application which simply add two numbers and display the sum on my frame when button is clicked.
Can anyone help me? ,to get rid out of it.
I simply implement frame by extending JFrame class and do the coding in my class default constructor.
Here is my code
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import java.awt.event.*;
public class mySwing extends JFrame {
JTextField t1;
JTextField t2;
mySwing(){
JLabel l1 = new JLabel("Enter 1st No.");
l1.setBounds(100, 50, 100, 30);
JLabel l2 = new JLabel("Enter 2nd No.");
l2.setBounds(100, 100,100, 30);
JTextField t1 = new JTextField();
t1.setBounds(300, 50,100, 30);
JTextField t2 = new JTextField();
t2.setBounds(300, 100,100, 30);
JButton b1 = new JButton("Click");
b1.setBounds(250, 200, 50, 50);
b1.addActionListener(new myAction());
add(l1);
add(l2);
add(t1);
add(t2);
add(b1);
setVisible(true);
setSize(600,600);
setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
class myAction implements ActionListener{
public void actionPerformed(ActionEvent e){
int a = Integer.parseInt(t1.getText());
int b = Integer.parseInt(t2.getText());
int sum=a+b;
JLabel l3 = new JLabel("Result is " +sum);
l3.setBounds(100, 300,100, 30);
add(l3);
}
}
public static void main(String[] args) {
mySwing s = new mySwing();
}
}
enter code here
null or "pixel perfect" layouts are an illusion. There are so many factors which go into determining how best a component should be presented and so much time and effort has already gone into solving the issue, you're just going to make life way more difficult for yourself.
Instead, take the time and make the effort to better learn the layout system available in Swing, see Laying Out Components Within a Container.
Now, your UI could be built using multiple panels, making use of different layouts (AKA compound layout), but in this case, I'd just use a GridBagLayout
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBorder(new EmptyBorder(16, 16, 16, 16));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.LINE_END;
gbc.insets = new Insets(4, 4, 4, 4);
add(new JLabel("Entre 1st No."), gbc);
gbc.gridy++;
add(new JLabel("Entre 2nd No."), gbc);
gbc.gridx++;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.LINE_START;
add(new JTextField(10), gbc);
gbc.gridy++;
add(new JTextField(10), gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.CENTER;
add(new JButton("Click"), gbc);
}
}
}
Also, try and avoid extending from JFrame, you're not adding any new functionality to the class and you're just tying yourself into a single use case corner
But what was the actual cause of the problem!?
Okay, this is a little more complicated than it might seem. Essentially, JFrame uses a BorderLayout by default, but BorderLayout only allows a single component to reside at each it's 5 available locations, so by default, all the components are getting added to the CENTER position, but only the last one will be used by BorderLayout (ie, your button).
You then call setVisible which causes the frame to perform a layout pass, but it's size is 0x0, so your button's size is set 0x0. Then you set the size of the frame, causing a new paint pass and then set the layout to null...
So, it's complicated 🤨
So after a day of studying layout managers and reading some swing refrences, this is what i come up with...
import java.awt.*;
import javax.swing.*;
public class Flags {
public static void startup() {
GridLayout Layout = new GridLayout(6,4);
JFrame menu = new JFrame("Flag Menu");
menu.setResizable(false);
menu.setSize(600,400);
JButton tailand = new JButton("Tailand");
JButton norway = new JButton("Norway");
JPanel panel = new JPanel();
panel.setLayout(Layout);
panel.add(norway);
panel.add(tailand);
menu.add(panel);
panel.setBackground(Color.LIGHT_GRAY);
tailand.setBackground(Color.WHITE);
norway.setBackground(Color.WHITE);
menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menu.setLocationRelativeTo(null);
;
menu.setVisible(true);
}
}
The problem is that i want my buttons to start at the bottom left and be equally spaced between the 4 other buttons i want to make.
There's a number of ways you "might" achieve this and the solution will ultimately depend on what you are trying to achieve.
Personally, I'd start with GridBagLayout - while not the friendliness of layout managers, it is by far the most flexible.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Flags {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Flags().startup();
}
});
}
public static void startup() {
GridLayout Layout = new GridLayout(6, 4);
JFrame menu = new JFrame("Flag Menu");
// menu.setResizable(false);
// menu.setSize(600, 400);
menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton tailand = new JButton("Tailand");
JButton norway = new JButton("Norway");
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.SOUTH;
panel.add(norway, gbc);
gbc.weighty = 0;
panel.add(tailand, gbc);
menu.add(panel);
panel.setBackground(Color.LIGHT_GRAY);
tailand.setBackground(Color.WHITE);
norway.setBackground(Color.WHITE);
menu.pack();
menu.setLocationRelativeTo(null);
menu.setVisible(true);
}
}
Another choice might be to use compound layouts, so that the "button" panel is placed at the SOUTH position of a BorderLayout and the "content" placed in the CENTER
So I'm creating a GUI that represents a vending machine. I'm just running into some problems trying to get the layout to work the way I want it. My thought was to insert an image into a JLabel, and then overlay that image with transparent JButtons in specific locations so that when you click on the image in certain locations, it will trigger the JButton. I haven't gotten to the transparency yet as I'm currently stuck on how to get the JButtons precisely where they need to be.
I've tried setLocation and setBounds with no luck. Any help on how to exactly position the jbuttons over the possible vending machine choices would be great.
import javax.swing.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
public class vendMachine extends JFrame
{
//Frame Dimensions
private static final int FRAME_HEIGHT = 800;
private static final int FRAME_WIDTH = 800;
private JPanel totalGUI, imagePanel, coinPanel;
public vendMachine()
{
createComponents();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setTitle("Vending Machine");
}
private void createComponents()
{
try
{
BufferedImage machineImg = ImageIO.read(new File("images/pepsivend.jpg"));
JLabel machineImgLabel = new JLabel(new ImageIcon(machineImg));
machineImgLabel.setLayout(new FlowLayout());
JButton test = new JButton("TEST BUTTON");
machineImgLabel.add(test);
//test.setBounds(0,0,0,0);
ImageIcon pennyIcon = new ImageIcon("images/coins/penny.jpg");
JButton pennyButton = new JButton(pennyIcon);
ImageIcon nickelIcon = new ImageIcon("images/coins/nickel.jpg");
JButton nickelButton = new JButton(nickelIcon);
ImageIcon dimeIcon = new ImageIcon("images/coins/dime.jpg");
JButton dimeButton = new JButton(dimeIcon);
ImageIcon quarterIcon = new ImageIcon("images/coins/quarter.jpg");
JButton quarterButton = new JButton(quarterIcon);
coinPanel = new JPanel();
coinPanel.setLayout(new GridLayout(4,1));
coinPanel.add(pennyButton);
coinPanel.add(nickelButton);
coinPanel.add(dimeButton);
coinPanel.add(quarterButton);
totalGUI = new JPanel();
totalGUI.setLayout(new BorderLayout());
totalGUI.add(machineImgLabel, BorderLayout.CENTER);
totalGUI.add(coinPanel, BorderLayout.EAST);
}
catch (IOException e)
{
e.printStackTrace();
}
add(totalGUI);
}
}
In the above Image I would like some help on how to get the test button, to overlay on top of the pepsi selection. From there I can go about making it transparent and removing the borders and text.
Edited to add: none of the buttons do anything yet. Simply trying to get the layout going before adding in anything else
It's unclear as to what your actually problem, however, I'll start with the layout...
No single layout will ever do everything you want, some times, you'll need to use multiple layouts and compound them. This example uses a BorderLayout and a GridBagLayout to set up the basic layout...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new VendingMachinePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class VendingMachinePane extends JPanel {
public VendingMachinePane() {
setLayout(new BorderLayout());
JLabel label = new JLabel("Cover");
// Demonstration purpose only
label.setPreferredSize(new Dimension(200, 400));
label.setOpaque(true);
label.setBackground(Color.BLUE);
add(label);
JPanel optionsPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.NORTH;
optionsPane.setBackground(Color.DARK_GRAY);
optionsPane.add(new JLabel("Coin Slot"), gbc);
optionsPane.add(makeButton("Pepsi"), gbc);
optionsPane.add(makeButton("Diet Pepsi"), gbc);
optionsPane.add(makeButton("Slice"), gbc);
optionsPane.add(makeButton("Dr Pepper"), gbc);
optionsPane.add(makeButton("Lipton"), gbc);
optionsPane.add(makeButton("Mountain Dew"), gbc);
optionsPane.add(makeButton("Schweppes"), gbc);
gbc.weighty = 1;
optionsPane.add(makeButton("Pepsi"), gbc);
add(optionsPane, BorderLayout.LINE_END);
}
protected JButton makeButton(String text) {
JButton btn = new JButton(text);
btn.setBorderPainted(false);
btn.setContentAreaFilled(false);
btn.setMargin(new Insets(4, 4, 4, 4));
btn.setOpaque(false);
return btn;
}
}
}
As to your "overlay buttons" issue, to me, that doesn't make sense, since a JButton has a icon property, why not just use a JButton to start with?
You make buttons transparent simply by changing their borderPainted contentAreaFilled and opaque properties
// You can pass a `Icon` instead of a `String` to the constructor
JButton btn = new JButton(text);
btn.setBorderPainted(false);
btn.setContentAreaFilled(false);
btn.setMargin(new Insets(4, 4, 4, 4));
btn.setOpaque(false);
Don't forget to setup an ActionListener ;)
Updated, based on the updated requirements...
You Could...
Break the image down in segments, making each element it's own image and simply applying those to the buttons, using a similar approach above
You Could...
Map hot spots on the image, and using a MouseListener monitor where the mouseClicked events occur - you do lose the advantage of keyboard input though
You Could...
Map out the hot spots of the image and using a GridBagLayout or custom layout manager, map the buttons onto the image.
I have a simple GUI and I just want to have some text fields stacked on top of each other, with each box being a JPanel. I'm currently using FlowLayout for both the JFrame and JPanel but it changes from being stacked to being in a row when I maximize. Ideally I'd like the text fields to stay in the center of the window even if its maximized. I was looking at using a BoxLayout but was having some trouble getting that to work.
public static Component textbox(String x){
JPanel panel = new JPanel(new FlowLayout(5,5,5));
JLabel lbltAm= new JLabel(x);
JTextField tftAm = new JTextField(10);
lbltAm.setFont(new Font("Serif", Font.PLAIN, 14));
lbltAm.setForeground(Color.white);
panel.add(lbltAm, BorderLayout.NORTH);
panel.add(tftAm, BorderLayout.CENTER);
panel.setBackground(Color.DARK_GRAY);
Border lowerbevel = BorderFactory.createBevelBorder(BevelBorder.LOWERED);
panel.setBorder(lowerbevel);
return panel;
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Tip Calculator");
//Add Textbox
frame.setLayout(new BoxLayout(frame, BoxLayout.Y_AXIS));
String Label = "Tip Calculator";
JLabel header = new JLabel(Label);
header.setFont(new Font("Serif", Font.BOLD, 18));
frame.add(header);
frame.add(textbox("Total"));
frame.add(textbox("Tip %"));
frame.add(textbox("People"));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.gray);
frame.setPreferredSize(new Dimension(300, 400));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
It's a matter of opinion, but for flexibility, I prefer to use GridBagLayout
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(textbox("Total"), gbc);
add(textbox("Tip %"), gbc);
add(textbox("People"), gbc);
}
public Component textbox(String x) {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(5, 5, 5, 5);
JLabel lbltAm = new JLabel(x);
JTextField tftAm = new JTextField(10);
lbltAm.setFont(new Font("Serif", Font.PLAIN, 14));
lbltAm.setForeground(Color.white);
panel.add(lbltAm, gbc);
panel.add(tftAm, gbc);
panel.setBackground(Color.DARK_GRAY);
Border lowerbevel = BorderFactory.createBevelBorder(BevelBorder.LOWERED);
panel.setBorder(lowerbevel);
return panel;
}
}
}
Or if your wanted the "boxes" to occupy the whole area when expanded, you could use something like...
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(textbox("Total"), gbc);
add(textbox("Tip %"), gbc);
add(textbox("People"), gbc);
Which results in something like...
Have a look at Laying Out Components Within a Container and How to Use GridBagLayout for more details
Firstly, I don't know why you're adding components to the JPanel with a method that is for BorderLayout after you've set the layout of panel as FlowLayout.
If you want to keep the components centered at all times (even if the screen is maximized), FlowLayout is probably not the best option for you to work with, as FlowLayout continues to position components horizontally until they fill the width of the frame (one row) and then, it begins the next row. Therefore, if the screen size is maximized, there will be more components per row and they won't be stacked. I would suggest using a GridLayout with one column like so:
frame.setLayout(new GridLayout(3 *(number of rows/components)*, 1));
You can do the same with the JPanel. After that, set the horizontal alignment of each component as centered like so:
component.setHorizontalAlignment(componentName.CENTER);
Hope this helps!
Try to use GridLayout instead of BoxLayout in createAndShowGUI.
frame.setLayout(new GridLayout(4,1));
I would like to make a layout using Java Swing which looks like the following drawing.
(source: braun-abstatt.de)
On the left is a JPanel which is drawn through paintComponent() in a way that the graphics automatically scale when the window is resized. (The question isn't about that panel. That one's already done.)
Now I need some buttons (the black boxes, added in Photoshop for the drawing) to the right of the JPanel mentioned before. The height of the reddish areas at the top and bottom, next to which there should be just empty space, is calculated along the lines of CONSTANT_FACTOR * getHeight(). Next to each compartment on the left, there should be a group of buttons, lined up to the center of the respective compartment (see the blue lines).
The JPanel containing the buttons knows about the CONSTANT_FACTOR and the number of compartments, so it should be possible to feed this information into a layout manager.
Which layout manager would I best use to achieve this layout? I've read about all the different layout managers, but I can't quite figure out which one or which combination of them best fits in this case.
For example, by use of a different LayoutManager, a very easy and simple container, takes no more than 15-20 minutes:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class ThinLineFrame {
private JFrame frame = new JFrame();
private JScrollPane scrollPane;
private JPanel panel = new JPanel();
private JPanel panelNorth = new JPanel();
private JPanel panelCenter = new JPanel();
private JPanel panelCenterCh1 = new JPanel();
private JPanel panelCenterCh2 = new JPanel();
private JPanel panelCenterCh3 = new JPanel();
private JPanel panelCenterCh4 = new JPanel();
private JPanel panelCenterCh5 = new JPanel();
private JPanel panelSouth = new JPanel();
public ThinLineFrame() {
panelNorth.setBackground(Color.red.darker());
panelNorth.setPreferredSize(new Dimension(80, 30));
//
panelCenter.setBackground(Color.darkGray);
panelCenter.setLayout(new GridLayout(5, 1, 2, 2));
//
panelCenterCh1.setLayout(new BorderLayout());
JButton panelCenterCh1Button = new JButton();
panelCenterCh1.add(panelCenterCh1Button, BorderLayout.CENTER);
//
JButton panelCenterCh2Button1 = new JButton();
JButton panelCenterCh2Button2 = new JButton();
panelCenterCh2.setLayout(new GridLayout(2, 1, 2, 2));
panelCenterCh2.add(panelCenterCh2Button1);
panelCenterCh2.add(panelCenterCh2Button2);
//
JButton panelCenterCh3Button1 = new JButton();
JButton panelCenterCh3Button2 = new JButton();
panelCenterCh3.setLayout(new GridLayout(2, 1, 2, 2));
panelCenterCh3.add(panelCenterCh3Button1);
panelCenterCh3.add(panelCenterCh3Button2);
//
JButton panelCenterCh4Button1 = new JButton();
JButton panelCenterCh4Button2 = new JButton();
panelCenterCh4.setLayout(new GridLayout(2, 1, 2, 2));
panelCenterCh4.add(panelCenterCh4Button1);
panelCenterCh4.add(panelCenterCh4Button2);
//
panelCenterCh5.setLayout(new BorderLayout());
JButton panelCenterCh5Button = new JButton();
panelCenterCh5.add(panelCenterCh5Button, BorderLayout.CENTER);
//
panelCenter.add(panelCenterCh1);
panelCenter.add(panelCenterCh2);
panelCenter.add(panelCenterCh3);
panelCenter.add(panelCenterCh4);
panelCenter.add(panelCenterCh5);
//
panelSouth.setBackground(Color.red.darker());
panelSouth.setPreferredSize(new Dimension(80, 30));
//
panel.setLayout(new BorderLayout(2, 2));
panel.add(panelNorth, BorderLayout.NORTH);
panel.add(panelCenter, BorderLayout.CENTER);
panel.add(panelSouth, BorderLayout.SOUTH);
//
scrollPane = new JScrollPane(panel);
frame.add(scrollPane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(80, 600));
frame.setLocation(100, 150);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ThinLineFrame dlg = new ThinLineFrame();
}
});
}
}
You should try looking at MigLayout. It's a super flexible LayoutManager that is also very simple.
The code would look something like:
MigLayout layout = new MigLayout("flowy");
panel.setLayoutManager(layout);
panel.add(button1);
panel.adD(button2);
etc..
Try adding debug, flowy to the constructor to get a visual idea of what is going on.
GBC without an anchor, just with plain vanilla GridBagConstraints and preferred size.
Centered JButton with fixed size:
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MainWithFixSize {
public static void main(String[] argv) throws Exception {
JFrame frame = new JFrame();
Container container = frame.getContentPane();
GridBagLayout gbl = new GridBagLayout();
container.setLayout(gbl);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
JButton component = new JButton();
component.setPreferredSize(new Dimension(25, 25));
gbl.setConstraints(component, gbc);
container.add(component);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(40, 90));
frame.pack();
frame.setVisible(true);
}
private MainWithFixSize() {
}
}