Positioning Components in Swing GUIs

I have some questions about component positioning and some questions about text fields and text areas (Java Swing). Any help is appreciated.

I am currently trying to have two text fields next to each other with a different caption, above which this text field is described. To do this, I put them in GridLayout(2, 2) .

  • Is this the best way? This is the only way I know to have a shortcut directly above another component. Is there a better way? How about if there is only one label above one button. Is it possible to position this through GridLayout(2, 1) ? I have low vision, so I donโ€™t think that the position buttons only by their pixel position are an option if there is no easy way to place components with a relative number of pixels on another component.

  • This leads me to my next question. What is the best way to have the same interface as above, but with a different component (button) located beneath it. In fact, the user interface should consist of two fields with names with a calculation button. The way I did this is to put the above components in the panel and add this plus calculation button to the surrounding panel using GridLayout(2, 1) . The problem is that the button is getting as big as the panel above it (I guess). How can I customize this and still have a button fully aligned under the text fields / labels panel? Similar to labels over text areas. The label should be small, but it has more space for the text area.

  • (text box): Again, referring to the user interface above, if the user enters many characters into the first text box, will the letters go through the text box on the right? If so, how can I prevent this?

  • If I add text to the text area and is already filled, will it automatically scroll by the user? If not, what's the easy way to scroll through a text area?

  • Now I do not set the size of the text area. Does it only grow when I add text? Does the default size have the number of characters?

+4
source share
2 answers

There are several layout managers who can provide you with what you need.

For, GridBagLayout will be my choice (I am biased since I used this layout manager for the past 12 years;))

enter image description here

 public class TestLayout17 { public static void main(String[] args) { new TestLayout17(); } public TestLayout17() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); 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.gridx = 0; gbc.gridy = 0; gbc.insets = new Insets(2, 2, 2, 2); add(new JLabel("Label 1"), gbc); gbc.gridx++; add(new JLabel("Label 2"), gbc); gbc.gridx = 0; gbc.gridy++; gbc.fill = GridBagConstraints.HORIZONTAL; add(new JTextField(10), gbc); gbc.gridx++; add(new JTextField(10), gbc); gbc.gridx = 0; gbc.gridy++; gbc.fill = GridBagConstraints.NONE; gbc.gridwidth = 2; add(new JButton("Click"), gbc); } } } 

I also agree with Eng.Fouadโ€™s proposal to use composite containers to make your life easier in the long run.

You can find the Stacking Components in the container to read.

+9
source

Now I'm trying to have two text fields next to each other above each label that describes what this text field does. To do this, I placed them in GridLayout (2, 2). Is this the best way? This is the only way I know to have a shortcut directly above another component. Is there a better way? And if there is one shortcut over one button. Is it possible to position this through GridLayout (2, 1)?

I myself always do this through nested panels using BorderLayout . For instance:

enter image description here

 JFrame frame = new JFrame("The Title"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panOuter = new JPanel(new BorderLayout()); JPanel panLeft = new JPanel(new BorderLayout()); panLeft.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panRight = new JPanel(new BorderLayout()); panRight.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); panOuter.add(panLeft, BorderLayout.WEST); panOuter.add(panRight, BorderLayout.EAST); JLabel lblLeft = new JLabel("Label 1", JLabel.CENTER); JLabel lblRight = new JLabel("Label 2", JLabel.CENTER); JTextField txtLeft = new JTextField(10); JTextField txtLright = new JTextField(10); panLeft.add(lblLeft, BorderLayout.NORTH); panLeft.add(txtLeft, BorderLayout.CENTER); panRight.add(lblRight, BorderLayout.NORTH); panRight.add(txtLright, BorderLayout.CENTER); frame.setContentPane(panOuter); frame.pack(); frame.setVisible(true); 

Note that you can manipulate the gaps between components with setting empty borders. In addition, instead of BorderLayout.WEST and BorderLayout.EAST you can use BorderLayout.LINE_START and BorderLayout.LINE_END , and this will add support for RTL languages โ€‹โ€‹(for example, Arabic).


This leads me to the next question. What is the best way to get the same interface as above, but with a different component (button) centered under it. In fact, the user interface should be two fields with named text with a compute button at the bottom. So I did this by putting the components above in the panel, and adding that plus a calculation button to the surrounding panel with GridLayout (2, 1). The problem is that the button is getting as big as the panel above it (I guess). How can I adjust this and still adjust the button according to the text fields / shortcuts bar?

I would do it using the nested panels, as before, but now there is a FlowLayout layout manager on the bottom panel to get a good size for the button:

enter image description here

 JFrame frame = new JFrame("The Title"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panOuter = new JPanel(new BorderLayout()); JPanel panLeft = new JPanel(new BorderLayout()); panLeft.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panRight = new JPanel(new BorderLayout()); panRight.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panBottom = new JPanel(); // default is FlowLayout panBottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); panOuter.add(panLeft, BorderLayout.WEST); panOuter.add(panRight, BorderLayout.EAST); panOuter.add(panBottom, BorderLayout.SOUTH); JLabel lblLeft = new JLabel("Label 1", JLabel.CENTER); JLabel lblRight = new JLabel("Label 2", JLabel.CENTER); JTextField txtLeft = new JTextField(10); JTextField txtLright = new JTextField(10); JButton btnBottom = new JButton("Press it!"); panLeft.add(lblLeft, BorderLayout.NORTH); panLeft.add(txtLeft, BorderLayout.CENTER); panRight.add(lblRight, BorderLayout.NORTH); panRight.add(txtLright, BorderLayout.CENTER); panBottom.add(btnBottom); frame.setContentPane(panOuter); frame.pack(); frame.setVisible(true); 

Similarly over text boxes. The label should be small, but have more space for the text area.

I suggest you use a TitledBorder :

enter image description here

 JFrame frame = new JFrame("The Title"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panOuter = new JPanel(new BorderLayout()); JPanel panLeft = new JPanel(new BorderLayout()); panLeft.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panRight = new JPanel(new BorderLayout()); panRight.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panBottom = new JPanel(); // default is FlowLayout panBottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panInput = new JPanel(new BorderLayout()); panInput.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panConsole = new JPanel(new BorderLayout()); Border outsideBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5); Border insideBorder = BorderFactory.createTitledBorder("The Console"); Border theBorder = BorderFactory.createCompoundBorder(outsideBorder, insideBorder); panConsole.setBorder(theBorder); panInput.add(panLeft, BorderLayout.WEST); panInput.add(panRight, BorderLayout.EAST); panInput.add(panBottom, BorderLayout.SOUTH); panOuter.add(panInput, BorderLayout.NORTH); panOuter.add(panConsole, BorderLayout.CENTER); JLabel lblLeft = new JLabel("Label 1", JLabel.CENTER); JLabel lblRight = new JLabel("Label 2", JLabel.CENTER); JTextField txtLeft = new JTextField(10); JTextField txtLright = new JTextField(10); JButton btnBottom = new JButton("Press it!"); JTextArea txtConsole = new JTextArea(5, 10); panLeft.add(lblLeft, BorderLayout.NORTH); panLeft.add(txtLeft, BorderLayout.CENTER); panRight.add(lblRight, BorderLayout.NORTH); panRight.add(txtLright, BorderLayout.CENTER); panBottom.add(btnBottom); panConsole.add(txtConsole, BorderLayout.CENTER); frame.setContentPane(panOuter); frame.pack(); frame.setVisible(true); 

third (text box): again referring to the user interface above, if the user enters many characters in the first text box, will the letters cross the text box on the right? If so, how can I prevent this?

Try the code above and see how it works :)


Fourth: if I add text to the text area and it is already full, does it automatically allow the user to scroll? If not, is this an easy way to scroll through a text area?

You need to use something called JScrollPane :

enter image description here

 JFrame frame = new JFrame("The Title"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panOuter = new JPanel(new BorderLayout()); JPanel panLeft = new JPanel(new BorderLayout()); panLeft.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panRight = new JPanel(new BorderLayout()); panRight.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panBottom = new JPanel(); // default is FlowLayout panBottom.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panInput = new JPanel(new BorderLayout()); panInput.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); JPanel panConsole = new JPanel(new BorderLayout()); Border outsideBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5); Border insideBorder = BorderFactory.createTitledBorder("The Console"); Border theBorder = BorderFactory.createCompoundBorder(outsideBorder, insideBorder); panConsole.setBorder(theBorder); panInput.add(panLeft, BorderLayout.WEST); panInput.add(panRight, BorderLayout.EAST); panInput.add(panBottom, BorderLayout.SOUTH); panOuter.add(panInput, BorderLayout.NORTH); panOuter.add(panConsole, BorderLayout.CENTER); JLabel lblLeft = new JLabel("Label 1", JLabel.CENTER); JLabel lblRight = new JLabel("Label 2", JLabel.CENTER); JTextField txtLeft = new JTextField(10); JTextField txtLright = new JTextField(10); JButton btnBottom = new JButton("Press it!"); JTextArea txtConsole = new JTextArea(5, 10); JScrollPane srcPane = new JScrollPane(txtConsole, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); panLeft.add(lblLeft, BorderLayout.NORTH); panLeft.add(txtLeft, BorderLayout.CENTER); panRight.add(lblRight, BorderLayout.NORTH); panRight.add(txtLright, BorderLayout.CENTER); panBottom.add(btnBottom); panConsole.add(srcPane, BorderLayout.CENTER); frame.setContentPane(panOuter); frame.pack(); frame.setVisible(true); 

I hope I answered all your questions :)

+7
source

All Articles