Reputation: 5322
I've tried my best to fix a JLabel's size, but it keeps changing and that causes other items in the GUI to move around.
I have specified both the sizing and the spacing of components. According to GridBagLayout's documentation, ipadx
and ipady
"Specifies the internal padding: how much to add to the size of the component." According to this post, setMinimumSize
and setMaximumSize
allows you to the set the actual size of the component. Since I have fixed both the size and the spacing, how is it possible that the components keep jumping around whenever text appears in the JLabel?
I was able to solve this in practice by adding a space into the empty text, but this keeps bugging me. What is it that I don't understand about this?
Here is a SSCCE demonstrating the problem. It has elements arranged in a GridBagLayout and changing the contents of one JLabel in one cell causes all items to move.
import javax.swing.*;
import java.awt.*;
import java.io.*;
public class F {
public static void main(String[] args) throws IOException, InterruptedException {
JFrame frame = new JFrame();
JPanel mainView = new JPanel();
mainView.setPreferredSize(new Dimension(300, 300));
mainView.setLayout(new GridBagLayout());
JPanel contents = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(1,3,3,3);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.ipady = 2;
gbc.anchor = GridBagConstraints.EAST;
JLabel text1 = new JLabel("Some text: ");
contents.add(text1, gbc);
gbc.gridy++;
JLabel text2 = new JLabel("More text: ");
contents.add(text2, gbc);
gbc.gridy++;
JLabel text3 = new JLabel("Third line: ");
contents.add(text3, gbc);
gbc.gridx++;
gbc.gridy = 0;
JTextField textField1 = new JTextField(10);
contents.add(textField1, gbc);
gbc.gridx++;
gbc.gridy++;
gbc.gridx--;
JTextField textField2 = new JTextField(10);
contents.add(textField2, gbc);
gbc.gridy++;
JLabel sitePass = new JLabel("");
sitePass.setMaximumSize(new Dimension(100, 15));
sitePass.setMinimumSize(new Dimension(100, 15));
//sitePass.setPreferredSize(new Dimension(100, 15)); // <-- this line fixes the problem
contents.add(sitePass, gbc);
mainView.add(contents);
frame.add(mainView);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
while (true) {
Thread.sleep(1000);
sitePass.setText("Pushup time");
Thread.sleep(1000);
sitePass.setText("");
}
}
}
Upvotes: 0
Views: 2329
Reputation: 168815
One way to solve the problem. Change:
JLabel sitePass = new JLabel("");
To:
JTextField sitePass = new JTextField("", 12);
sitePass.setOpaque(false);
sitePass.setBorder(null);
Explanation: A JTextField
has a default size determined by the number of columns, combined with the font and font size. The two statements following ensure it has the look of a JLabel
.
An improvement would be to also make the text field act like a label, which might be something along the lines of:
sitePass.setEditable(false);
sitePass.setFocusable(false);
Upvotes: 4
Reputation: 9808
There is another way to use a dummy whitespace like JComboBox
.
//javax.swing.plaf.basic.BasicComboBoxUI#getDefaultSize()
/**
* Return the default size of an empty display area of the combo box using
* the current renderer and font.
*
* @return the size of an empty display area
* @see #getDisplaySize
*/
protected Dimension getDefaultSize() {
// Calculates the height and width using the default text renderer
Dimension d = getSizeForComponent(getDefaultListCellRenderer()
.getListCellRendererComponent(listBox, " ", -1, false, false));
return new Dimension(d.width, d.height);
}
import java.awt.*;
import java.util.Objects;
import javax.swing.*;
public class DummyWhiteSpaceTest {
public JComponent makeUI(String dummy) {
JPanel mainView = new JPanel(new GridBagLayout());
JPanel contents = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(1, 3, 3, 3);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.ipady = 2;
gbc.anchor = GridBagConstraints.EAST;
/* Text labels. */
JLabel text1 = new JLabel("Some text: ");
contents.add(text1, gbc);
gbc.gridy++;
JLabel text2 = new JLabel("More text: ");
contents.add(text2, gbc);
gbc.gridy++;
JLabel text3 = new JLabel("Third line: ");
contents.add(text3, gbc);
gbc.gridx++;
gbc.gridy = 0;
JTextField textField1 = new JTextField(10);
contents.add(textField1, gbc);
gbc.gridx++;
gbc.gridy++;
gbc.gridx--;
JTextField textField2 = new JTextField(10);
contents.add(textField2, gbc);
gbc.gridy++;
//@see javax.swing.plaf.basic.BasicComboBoxUI#getDefaultSize()
//JLabel sitePass = new JLabel(" ");
JLabel sitePass = new JLabel(dummy);
sitePass.setFont(new Font("Monospaced", Font.PLAIN, 14));
contents.add(sitePass, gbc);
mainView.add(contents);
(new Timer(1000, e -> {
if (Objects.equals(sitePass.getText(), dummy)) {
sitePass.setText("Pushup time");
} else {
sitePass.setText(dummy);
}
})).start();
return mainView;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
DummyWhiteSpaceTest test = new DummyWhiteSpaceTest();
JPanel p = new JPanel(new GridLayout(1, 2));
p.add(test.makeUI(""));
p.add(test.makeUI(" "));
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(p);
f.setSize(640, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
Upvotes: 1
Reputation: 14572
Swing use the preferredSize
for some Layout.
Setting it will correct your label.
I am used to fixe a JComponent
by setting minimum
, maximum
and preferred
size just to be sure ;)
PS : I will try to add more information about how to use it.
Upvotes: 1