Why is setting setPreferredSize () on a JFrame bad?

Sets the preferred size JFrame

using setPreferredSize()

what is considered bad?

If this is bad, then there is a good way to resize the window JFrame

to the size I need.

I know how to compose the components to reflect the final JFrame dimension that I need. But if I use a shortcut to change the preferred size with a call setPreferredSize()

just before the call pack()

to change the final size JFrame

, is that bad? If so, why?

For example, I have a sample form:

enter image description here

This is displayed without setting the preferred size.

Now I can resize the form with call setPreferredSize()

before call pack()

.

enter image description here

This is displayed when called: setPreferredSize(new Dimension(500, 300));

I can have a similar effect when adjusting the size of the components when installing it. But what is the disadvantage of setting the frame size with just a call setPreferredSize()

.

I might think that the preferred size can be changed by manually resizing the displayed window with the mouse after it is displayed. Is not it?

code:

import java.awt.Dimension;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class MyFrame extends JFrame {
    private static final long serialVersionUID = 1L;

    private JTextField fullNameTextField = new JTextField();
    private JTextField emailIDTextField = new JTextField();
    private JTextArea addressTextArea = new JTextArea();
    private JButton submitButton = new JButton("Submit");
    private JButton cancelButton = new JButton("Cancel");

    public MyFrame(){
        super("MyFrame");

        layoutComponents();

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationByPlatform(true);

        setPreferredSize(new Dimension(500, 300));

        pack();
    }

    private void layoutComponents(){
        GroupLayout layout = new GroupLayout(getContentPane());
        getContentPane().setLayout(layout);

        JLabel fullNameLabel = new JLabel("Full Name:");
        JLabel emailIDLabel = new JLabel("Email ID:");
        JLabel addressLabel = new JLabel("Address:");

        JScrollPane addressScrollPane = new JScrollPane(addressTextArea);

        layout.setHorizontalGroup(
                layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addGap(10)
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                                .addGroup(layout.createSequentialGroup()
                                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                                                .addComponent(fullNameLabel)
                                                .addComponent(emailIDLabel)
                                                .addComponent(addressLabel)
                                            )
                                        .addGap(15)
                                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                                                .addComponent(fullNameTextField, 10, 200, Short.MAX_VALUE)
                                                .addComponent(emailIDTextField)
                                                .addComponent(addressScrollPane)
                                                .addGroup(layout.createSequentialGroup()
                                                        .addGap(0, 0, Short.MAX_VALUE)
                                                        .addComponent(submitButton)
                                                        .addGap(10)
                                                        .addComponent(cancelButton)
                                                    )
                                            )
                                    )
                            )
                        .addGap(10)
                    )
            );

        layout.setVerticalGroup(
                layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                        .addGap(10)
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                .addComponent(fullNameLabel)
                                .addComponent(fullNameTextField)
                            )
                        .addGap(5)
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                .addComponent(emailIDLabel)
                                .addComponent(emailIDTextField)
                            )
                        .addGap(5)
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                .addComponent(addressLabel)
                                .addComponent(addressScrollPane, 20, 60, Short.MAX_VALUE)
                            )
                        .addGap(15)
                        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                .addComponent(submitButton)
                                .addComponent(cancelButton)
                            )
                        .addGap(10)
                    )
            );

        layout.linkSize(submitButton, cancelButton);

        getRootPane().setDefaultButton(submitButton);
    }

    public static void main(String [] args){
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MyFrame().setVisible(true);
            }
        });
    }
}

      

+3


source to share


2 answers


The main reason this would be considered bad (a bad, probably too strong word, unreasonably might be better) is the use of unknown (magic) numbers, not empirical meanings.

Each platform (and even a similar OS running on different hardware and setups) has its own content rendering facility, which can alter the amount of space required by individual components.

For text boxes and text areas, you can make suggestions for the number of columns (and rows for text areas) that can be used to change the final frame size using setColumns

and setRows

for example ...

So using the following code ...

import java.awt.EventQueue;
import java.awt.FlowLayout;
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.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestLayout101 {

    public static void main(String[] args) {
        new TestLayout101();
    }

    public TestLayout101() {
        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 {

        private JTextField fullNameTextField = new JTextField(10);
        private JTextField emailIDTextField = new JTextField(10);
        private JTextArea addressTextArea = new JTextArea(10, 20);
        private JButton submitButton = new JButton("Submit");
        private JButton cancelButton = new JButton("Cancel");

        public TestPane() {

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.WEST;
            gbc.insets = new Insets(4, 4, 4, 4);

            add(new JLabel("Full Name: "), gbc);
            gbc.gridy++;
            add(new JLabel("Email ID: "), gbc);
            gbc.gridy++;
            gbc.anchor = GridBagConstraints.NORTHWEST;
            add(new JLabel("Address: "), gbc);

            gbc.gridx++;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.weightx = 1;

            add(fullNameTextField, gbc);
            gbc.gridy++;
            add(emailIDTextField, gbc);
            gbc.gridy++;
            gbc.weighty = 1;
            add(new JScrollPane(addressTextArea), gbc);

            JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT, 4, 4));
            buttons.add(submitButton);
            buttons.add(cancelButton);

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weighty = 0;
            add(buttons, gbc);
        }
    }
}

      

What produces ...

Compact

Now, changing just one line ...

private JTextArea addressTextArea = new JTextArea(10, 20);
                                // Only this value ---^

      



He produces it ...

Mini

And again...

private JTextArea addressTextArea = new JTextArea(10, 40);
                                // Only this value ---^

      

Luxury

I could change the number of lines for JTextArea

and also affect the window height.

The difference is that these values ​​are used in conjunction with the system font metrics to calculate the preferred size of components when the program starts up, so they will be different for different systems and platforms ...

The main thing in layouts is to spend your time intent and workflow rather than trying to get the perfect pixel solution because there just isn't such a thing ... talk to web developers, they have the same problems, much worse (multiple browsers in one system, all rendering is different)

+5


source


Personally, I think there is nothing wrong with using it frame.setPreferredSize()

to resize the window JFrame

. In fact, I think this is the most appropriate solution to change it.

But it's time to make a distinction between what some of the most common resizing methods do:

  • frame.pack()

    as explained here basically assumes preferred dimensions for each of the individual elements.

  • frame.setSize()

    resizes the window as expected, but only if the parent of the component does not have an explicitly defined layout manager. The use of this method is discussed here .

This does not provide any other method for determining the size of the window, so I believe that setting the preferred window size is the best option. I would still have to define setMinimumSize()

and setMaximumSize()

to ensure that in all cases the dimensions are resized correctly.

Edit:

Other posts in this thread got me thinking about using "magic constants" when configuring components. For example, in web development, it is generally frowned upon to use pixels as it varies widely by the system. I wanted to see if this is true with measurements. In short, my findings have come to the conclusion that this is not the case.

This was a JFrame with prefered size

of captured new Dimension(200, 300)

on my MacBook Pro with Retina display:



JFrame with a <code> prefered size </code>
      <br>
        <script async src=
of new Dimension (200, 300)

" data-src="/img/726caadb56af8775661a7bb604cc18cf.png" class=" lazyloaded" src="https://fooobar.com//img/726caadb56af8775661a7bb604cc18cf.png">

It was a JFrame with prefered size

of new Dimension(200, 300)

, captured on my Asus Windows tablet (no retina display):

JFrame with a <code> prefered size </code>
      <br>
        <script async src=
of new Dimension (200, 300)

" data-src="/img/2759f050dac9019d42333afc80a8334b.png" class=" lazyloaded" src="https://fooobar.com//img/2759f050dac9019d42333afc80a8334b.png">

These windows looked exactly the same, and although I could not find it posted, Dimenion is indeed already scaled in proportion, taking into account height, width and screen resolution, to produce almost accurate rendering across all devices. This, I think you could say makes sense, because this is the Java way.

That being said, here are some things that I think you need to watch out for:

  • The difference between UIManager LookAndFeel

    on different platforms as MadProgrammer pointed out

To be honest, I think the final decision is up to the programmer. After this testing, I pretty much still think that usage frame.setPreferredSize()

is one of the best things available unless you plan on implementing a semi-complex window manager. Even then, I think there will always be some unaccounted for variation.

+1


source







All Articles