Search code examples
javaimageswinglayout-managergridbaglayout

Why does my gui layout change when uploading a photo?


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 Before

and this is how layout looks after uploading an image

After

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.


Solution

  •     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.