Why does my gui layout change when uploading a photo? - java

My programs user interface currently uses a grid bag layout, I want it to be a fixed size however when i upload a picture to the label the whole interface changes in dimensions.
Below is code for my layout manager
public SearchService() throws Exception {
setSize(600, 600);
setResizable(false);
JPanel mainPanel = new JPanel();
JPanel templatePanel = new JPanel();
JPanel toolPanel = new JPanel();
JLabel picLabel = new JLabel();
JLabel tools = new JLabel("Tools");
JLabel templates = new JLabel("Templates");
JButton upload = new JButton("Upload");
JButton search = new JButton("Search");
JButton save = new JButton("Save");
//Main panel
GridBagLayout GBPanel = new GridBagLayout();
GridBagConstraints GBC = new GridBagConstraints();
mainPanel.setLayout( GBPanel );
//Template panel
GBC.gridx = 0;
GBC.gridy = 0;
GBC.gridwidth = 1;
GBC.gridheight = 3;
GBC.fill = GridBagConstraints.BOTH;
GBC.weightx = 1;
GBC.weighty = 0;
GBC.anchor = GridBagConstraints.WEST;
GBPanel.setConstraints( leftPanel, GBC );
leftPanel.add(templates);
mainPanel.add( leftPanel );
//Picture label
GBC.gridx = 1;
GBC.gridy = 0;
GBC.gridwidth = 2;
GBC.gridheight = 1;
GBC.fill = GridBagConstraints.BOTH;
GBC.weightx = 0;
GBC.weighty = 1;
GBC.anchor = GridBagConstraints.CENTER;
GBPanel.setConstraints( picLabel, GBC );
mainPanel.add( picLabel );
//Tool panel
GBC.gridx = 4;
GBC.gridy = 0;
GBC.gridwidth = 1;
GBC.gridheight = 3;
GBC.fill = GridBagConstraints.BOTH;
GBC.weightx = 1;
GBC.weighty = 0;
GBC.anchor = GridBagConstraints.EAST;
GBPanel.setConstraints( rightPanel, GBC );
rightPanel.add(tools);
mainPanel.add( rightPanel );
//Upload button
GBC.gridx = 1;
GBC.gridy = 1;
GBC.gridwidth = 1;
GBC.gridheight = 1;
GBC.fill = GridBagConstraints.BOTH;
GBC.weightx = 1;
GBC.weighty = 0;
GBC.anchor = GridBagConstraints.PAGE_START;
GBPanel.setConstraints( upload, GBC );
mainPanel.add( upload );
//Save button
GBC.gridx = 2;
GBC.gridy = 1;
GBC.gridwidth = 1;
GBC.gridheight = 1;
GBC.fill = GridBagConstraints.BOTH;
GBC.weightx = 1;
GBC.weighty = 0;
GBC.anchor = GridBagConstraints.PAGE_START;
GBPanel.setConstraints( save, GBC );
mainPanel.add( save );
//Search button
GBC.gridx = 1;
GBC.gridy = 2;
GBC.gridwidth = 2;
GBC.gridheight = 1;
GBC.fill = GridBagConstraints.BOTH;
GBC.weightx = 1;
GBC.weighty = 0;
GBC.anchor = GridBagConstraints.PAGE_START;
GBPanel.setConstraints( search, GBC );
mainPanel.add( search );
add(mainPanel);
and below is code that adds the picture
upload.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser("C:\\Users);
FileNameExtensionFilter filter = new FileNameExtensionFilter("Image", "jpg", "png", "bmp");
chooser.setFileFilter(filter);
int result = chooser.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {
File selectedFile = chooser.getSelectedFile();
BufferedImage bi;
userPhoto = chooser.getSelectedFile().getPath();
try {
bi = ImageIO.read(selectedFile);
Image dimg = bi.getScaledInstance(picLabel.getWidth(), picLabel.getHeight(), Image.SCALE_SMOOTH);
picLabel.setIcon(new ImageIcon(dimg));
}
catch(IOException IOe) {
IOe.printStackTrace();
}
System.out.println(userPhoto);
}
}
});
I' ve added two photos to show the results with my program. This is how it looks when i first run and how i want the layout to stay
and this is how layout looks after uploading an image
as you can see the left and right panels get shrunk and the picture doesn't even take up the whole picture label.
I also added this line System.out.println(picLabel.getWidth()); in the action listener and saw that when the button is first hit the size is set to 299 but if i hit the button again it changes and does so for each time. I want to know if its possible to make the image stay at a width of 299.

GBC.gridwidth = 5;
GBC.gridheight = 20
You can't just randomly assign gridwith/height to a component. You actually need 20 other components if you want to component to span the same height as the other components.
as you can see the left and right panels get shrunk and the picture doesn't even take up the whole picture label.
If you don't want the layout to change then use a different layout manager or nested panels with different layout managers.
For example you start with the BorderLayout.
Then you can add panels to the LINE_START and LINE_END.
Then you need another panel in the CENTER. Again you could use a BorderLayout. You add your picture to the CENTER and then another panel with the buttons at the PAGE_END.
Now all the components except the image are fixed in size. The space available to the image will vary depending on the size of the frame.
So the basic code is:
JPanel buttonPanel = new JPanel(...);
JLabel image = new JLabel(...);
JPanel center = new JPanel( new BorderLayout() );
center.add(image, BorderrLayout.CENTER);
center.add(buttonPanel, BorderLayout.PAGE_END);
JPanel leftPanel = new JPanel(...);
JPanel rightPanel = new JPanel(...);
frame.add(leftPanel, BorderLayout.LINE_START);
frame.add(center, BorderLayout.CENTER);
frame.add(rightPanel, BorderLayout.LINE_END);
Far less confusing than trying to play with all the constraints of the GridBagLayout.
Now the child panels (left, right, buttons) can use appropriate layout managers.

Related

Positioning in javax swing with gridbaglayout

I've been self teaching myself swing for a few days for a project and right now I'm trying to figure out how to position components with a grid bag layout. I got most of it except a few small issues. If anyone could help, it would be very appreciated. I've tried this so many different ways D:
...
titlePanel.setLayout(new GridBagLayout());
titlePanel.setBackground(BLUE);
header = new JLabel ("Gradebook");
header.setLocation(200,400);
header.setFont(new Font("Serif", Font.BOLD, 50));
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.CENTER;
titlePanel.add(header,gbc);
date = new Date();
currentDate = new JLabel (fmt.format(date));
currentDate.setFont(new Font("Serif", Font.PLAIN, 14));
ActionListener updateTime = new ActionListener() {
public void actionPerformed (ActionEvent e) {
date = new Date();
currentDate.setText(fmt.format(date));
}
};
Timer timer = new Timer (1000, updateTime);
timer.start();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.CENTER;
titlePanel.add(currentDate, gbc);
JLabel userName = new JLabel ("Username: ");
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.EAST;
titlePanel.add(userName, gbc);
JTextField username = new JTextField (10);
gbc.gridx = 1;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.WEST;
titlePanel.add(username, gbc);
JLabel password = new JLabel ("Password: ");
gbc.gridx = 0;
gbc.gridy = 3;
gbc.anchor = GridBagConstraints.EAST;
titlePanel.add(password, gbc);
JPasswordField Password = new JPasswordField (10);
gbc.gridx = 1;
gbc.gridy = 3;
gbc.anchor = GridBagConstraints.WEST;
titlePanel.add(Password, gbc);
JButton login = new JButton ("Login");
gbc.gridx = 0;
gbc.gridy = 4;
gbc.anchor = GridBagConstraints.CENTER;
titlePanel.add(login, gbc);
JButton newAccount = new JButton ("Create New Account");
gbc.gridx = 0;
gbc.gridy = 5;
gbc.anchor = GridBagConstraints.CENTER;
titlePanel.add(newAccount, gbc);
mainFrame.add(titlePanel);
So when I run the code for the login screen, it comes up with this
I need a way to center the username and password so they match up with everything else and also add some blank vertical space between the 2 buttons at the bottom. Sorry if this is a dumb question :|
Your username/password contains two components in two different columns. So if you want all the components centered you have two options:
Create a separate panel for each of the label/text field components. Then you can add the panel as a single component which means it will be placed in the first column with all the other components.
Have all the other component "span" two columns. So now they will take up the same width as the label/text field components. In this case you will need to specify the gridWidth constraint.
Read the section from the Swing tutorial on How to Use GridBagLayout for more information on the various constraints used by GridBagLayout.
also add some blank vertical space between the 2 buttons at the bottom
Again, look at the constraints. You could use the insets constraint.

GridBagLayout not applying gridy changes

I'm trying to create a personal DnD character sheet program. The main idea is to have 4 large panels that each contain one of the major sections of a basic character sheet. I'm currently working on the first panel that has stats and saving throws. I'm trying to get more comfortable with GridBagLayout while making this, but I've run into a problem with setting gridy. I've already visited the GridBagLayout not obeying gridx and gridy and (unless I'm just stupid), that didn't help me. I used GridBagLayout with GridBagConstraints for statsPanel() and gridy worked fine.
Here's the problem: whenever I set gridy to the next grid in proficinciesAndSkillsPanel(), it's treated like I just changed gridx. My goal is to have one column with many rows, not one row with many columns. Thank you for your time
//this builds the jframe and sets the primary jpanel
private void buildComponents()
{
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mp = (JPanel)getContentPane();
mp.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
mp.add(panelA(), gbc);
gbc.gridx = 1;
mp.add(new JButton("test"), gbc);
createMenuBar();
setVisible(true);
}
//this creates the first real panel that i'm currently working with
private JPanel panelA()
{
JPanel result = new JPanel();
result.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
//I left out the code for statsPanel() because that works fine
result.add(statsPanel(), gbc);
gbc.gridx = 1;
result.add(proficinciesAndSkillsPanel(), gbc);
return result;
}
//this builds the second half of the upper portion of panel A
private JPanel proficinciesAndSkillsPanel()
{
JPanel result = new JPanel();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = 1;
gbc.weighty = 1;
result.add(labeledTextField("Inspiration", inspirationField = new JTextField(2), null, 1), gbc);
gbc.gridx = 0;
gbc.gridy = 1;
result.add(labeledTextField("Proficiency bonus", proficiencyField = new JTextField(2), null, 1),gbc);
gbc.gridx = 0;
gbc.gridy = 2;
result.add(labeledRadioField("Strength", strSTField = new JTextField(2), strRB = new JRadioButton()),gbc);
return result;
}
//this creates a JTextField with the appropriate label and a sub-JTextField
private JPanel labeledTextField(String str, JTextField jtf, JTextField bonjtf, int space)
{
JPanel result = new JPanel();
JPanel subResult = new JPanel();
result.setLayout(new FlowLayout());
result.add(new JLabel(str));
result.add(Box.createHorizontalStrut(space));
subResult.add(jtf);
jtf.setHorizontalAlignment(JTextField.CENTER);
try
{
subResult.add(bonjtf);
bonjtf.setHorizontalAlignment(JTextField.CENTER);
bonjtf.setEditable(false);
bonjtf.setText("+0");
}catch(NullPointerException e){}
jtf.addKeyListener(new JTF_Listener(){
public void update() {
String str2 = "";
try
{
int result = (Integer.parseInt(jtf.getText())-10)/2;
if(result >=0)
{
str2 += "+"+Integer.toString(result);
}
else
{
str2 += Integer.toString(result);
}
}catch(NumberFormatException nfe){}
bonjtf.setText(str2);
}
});
result.add(subResult);
return result;
}
//this does the same as labeledTextField, just with a radioButton
private JPanel labeledRadioField(String str, JTextField jtf, JRadioButton jrb)
{
JPanel result = new JPanel();
result.setLayout(new FlowLayout());
result.add(jrb);
result.add(jtf);
result.add(new JLabel(str));
jtf.setHorizontalAlignment(JTextField.CENTER);
jtf.setText("+0");
jtf.addKeyListener(new JTF_Listener(){
public void update(){
String str2 = "";
try
{
int result = Integer.parseInt(jtf.getText());
str2+= "+" + Integer.toString(result);
}catch(NumberFormatException nfe){}
jtf.setText(str2);
}
});
return result;
}
Not sure that this is your problem since you've not posted a valid MCVE (please correct this!), but here:
private JPanel proficinciesAndSkillsPanel()
{
JPanel result = new JPanel(); // ******** here *********
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = 1;
gbc.weighty = 1;
result.add(labeledTextField("Inspiration", inspirationField = new JTextField(2), null, 1), gbc);
gbc.gridx = 0;
gbc.gridy = 1;
result.add(labeledTextField("Proficiency bonus", proficiencyField = new JTextField(2), null, 1),gbc);
gbc.gridx = 0;
gbc.gridy = 2;
result.add(labeledRadioField("Strength", strSTField = new JTextField(2), strRB = new JRadioButton()),gbc);
return result;
}
You're treating this result JPanel as if it uses GridBagLayout when in fact it's not, it's using JPanel's default FlowLayout
One confusing bit: you've got many JPanel variables that have been given the same name, result. In your code you do in fact call result.setLayout(new GridBagLayout()), but not for the JPanel that I show above, and this might be confusing you. I suggest that you avoid using the same variable names in your code as you're doing to avoid this confusion.
If you need more specific help, then you first, please tell us more of the details and show us your pertinent code as a valid minimal example program or MCVE. If you're sitting in our shoes, and are trying to understand someone else's confusing code, it makes a huge difference if they put the effort in to make that code compilable and runnable for us.

JFrame center components

I was wondering how to center my components, I found the gridBagLayout but I couldn't find a way to have it bigger than it is : my buttons are too small.
Part of my code :
private void addMainButtons() {
JPanel container = new JPanel() {
private static final long serialVersionUID = -424395301619105440L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension dim = this.getSize();
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
Date date = new Date();
g.setFont(new Font("TimesRoman", Font.PLAIN, 20));
g.setColor(Color.BLACK);
String s = format.format(date);
g.drawString(s, (int) ((dim.getWidth() - s.length() - 80) / 2), 20);
}
};
container.setBackground(new Color(109, 69, 60));
JButton productsButton = new JButton("Produits");
productsButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cl.show(frame, pages[1]);
}
});
productsButton.setAlignmentY(Component.CENTER_ALIGNMENT);
productsButton.setAlignmentX(Component.CENTER_ALIGNMENT);
// Creating grid
container.setPreferredSize(new Dimension(400, 600));
container.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
container.add(productsButton, gbc);
gbc.gridy = 1;
gbc.gridwidth = 1;
container.add(new JButton("Entrée"), gbc);
gbc.gridx = 1;
container.add(new JButton("Sortie"), gbc);
mainPage.setLayout(new BorderLayout());
mainPage.add(container, BorderLayout.CENTER);
// End of main page
}
GridBagLayout is really difficult to use, is there another way to center components ? I could use NestedLayouts but I don't know how.
You can use weightx and/or weighty to effect the amount of space the components will occupy, for example, if I do
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.weightx = 1;
gbc.weighty = 1;
container.add(productsButton, gbc);
gbc.gridy = 1;
gbc.gridwidth = 1;
container.add(new JButton("Entrée"), gbc);
gbc.gridx = 1;
container.add(new JButton("Sortie"), gbc);
I can generate this...
You could use two containers, one holding a JLabel which shows the date and one which contains the buttons, but I doubt that's what you're really after.
You can use ipadx and ipady which adds the amount to the components preferred size
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.ipadx = 40;
gbc.ipady = 40;
container.add(productsButton, gbc);
gbc.gridy = 1;
gbc.gridwidth = 1;
container.add(new JButton("Entrée"), gbc);
gbc.gridx = 1;
container.add(new JButton("Sortie"), gbc);
which, when included with your existing constraints, allows you to "grow" the buttons a bit.
Try below code for increasing size of button while adding every components to gridbagconstraints. Change the value of weightx/weighty as you want.
gbc.weightx = 1.0;
gbc.weighty = 1.0;
To give more spaces between components, use below code while adding every components to gridbagconstraints.
gbc.insets = new Insets(2, 2, 2, 2);
According to my knowledge, you used correct way to center components. It can also be done by other layout but it may be little bit difficult.

Java GridBagLayout components centering when background filled

I'm trying to create a GridBagLayout, I have got the panels set out exactly how I want them. However I cannot set the background colour of each panel without also forcing all of the components to center.
Here the panels are coloured but all of the components center
http://i.imgur.com/BattBdw.png
Here all of the components snap to NORTHWEST as specified in the code but the background color does not fill the pane.
http://i.imgur.com/lvuEy4u.png
Sorry I cannot embed the pictures, my reputation is not high enough :(
GridBagConstraints GBC = new GridBagConstraints();
GBC.fill = GridBagConstraints.BOTH;
GBC.anchor = GridBagConstraints.NORTHWEST;
//green panel
GBC.gridx = 0;
GBC.gridy = 0;
GBC.weightx = 0.1;
GBC.weighty = 0.1;
JPanel panelGreen = new JPanel();
panelGreen.setBackground(Color.green);
//add button to green panel
JButton button = new JButton("Button");
panelGreen.add(button, GBC);
contentPane.add(panelGreen, GBC);
//blue panel
GBC.gridx = 1;
GBC.gridy = 0;
GBC.weighty = 0.1;
GBC.weightx = 0.9;
JPanel panelBlue = new JPanel();
panelBlue.setBackground(Color.blue);
contentPane.add(panelBlue, GBC);
//red panel
GBC.gridx = 0;
GBC.gridy = 1;
GBC.weighty = 0.8;
GBC.weightx = 0.1;
JPanel panelRed = new JPanel();
panelRed.setBackground(Color.red);
contentPane.add(panelRed, GBC);
//black panel
GBC.gridx = 0;
GBC.gridy = 2;
GBC.weighty = 0.1;
GBC.weightx = 0.1;
GBC.gridwidth =2;
JPanel panelBlack = new JPanel();
panelBlack.setBackground(Color.black);
contentPane.add(panelBlack, GBC);
//yellow panel
GBC.gridx = 1;
GBC.gridy = 1;
GBC.weighty = 0.8;
GBC.weightx = 0.9;
GBC.gridwidth =1;
JPanel panelYellow = new JPanel();
panelYellow.setBackground(Color.yellow);
contentPane.add(panelYellow, GBC);
Firstly, creating a JPanel() with the default constructor means it gets a FlowLayout - you need to tell your panels to use GridBagLayouts:
JPanel panelGreen = new JPanel(new GridBagLayout());
Other than that, you just need to have the "fill" property set to NONE when you add your JButton or it will expand to fill the whole pane. After you've added the button you can set it to BOTH for the panels themselves:
GBC.fill = GridBagConstraints.NONE;
JButton button = new JButton("Button");
panelGreen.add(button, GBC);
GBC.fill = GridBagConstraints.BOTH;
contentPane.add(panelGreen, GBC);

Buttons doesn't fill all available space when I use GridBagLayout in Java

I want to create an application with buttons arrayed into invisible table. The buttons should fill all the available space inside the imaginary cells even when I´ll resize the frame. I´m using Swing, GridBagLayout. I've read some articles and the solution was to add .weightx=1 and .weighty=1. Weightx works perfect and it fill the gaps but weighty doesn't. Buttons don´t extend into height of cell. Is there a problem with my code or is there something to add that solve my problem? Or should I use absolutely another layout?
public class NewClass {
public void NewClass(){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.add(panel);
GridBagLayout layout = new GridBagLayout();
panel.setLayout(layout);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.gridx = 0;
gbc.gridy = 0;
JButton B11 = new JButton("11");
panel.add(B11,gbc);
gbc.gridx = 1;
gbc.gridy = 0;
JButton B12 = new JButton("12");
panel.add(B12,gbc);
gbc.gridx = 0;
gbc.gridy = 1;
JButton B21 = new JButton("21");
panel.add(B21,gbc);
gbc.gridx = 1;
gbc.gridy = 1;
JButton B22 = new JButton("22");
panel.add(B22,gbc);
frame.pack();
frame.setSize(800,400);
frame.setVisible(true);
}}
You're using the wrong GridBagConstraints#fill field value, since the value you're using is telling the layout manager to fill the buttons horizontally only.
You need to change
gbc.fill = GridBagConstraints.HORIZONTAL;
to
// gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.fill = GridBagConstraints.BOTH;
if you want the buttons to fill both directions, both horizontally and vertically.

Categories