Aligning single characters in Java BoxLayout on the y-axis off-center

It seems that the problem is with the alignment of certain characters in the center of BoxLayout along the y axis in Java. I do not know what can cause this, and I created SSCCE to demonstrate the effect. In the example, I use only the "a" character, and I draw a line down the straight middle of each JPanel to demonstrate how far away from each case is the center. The bold case seems to work well, but normal formatting and italics are too far from the center, despite using setAlignmentX and setHorizontalAlignment. Any help in understanding this effect is appreciated.

In the case where the problem is with Java on my particular computer, this is an image of what is displayed on my screen when I run SSCCE, which loads three different JPanels with BoxLayouts along the y axis and puts a centered JLabel with only the “a” character in each : enter image description here

& here is the code for SSCCE:

import javax.swing.*; import java.awt.*; import javax.swing.border.*; public class AlignmentTest extends JPanel { public AlignmentTest(char label, int style) { JLabel l = new JLabel(Character.toString(label)); setBorder(BorderFactory.createLineBorder(Color.BLACK,1)); setBackground(Color.WHITE); setLayout(new BoxLayout(this,BoxLayout.Y_AXIS)); setPreferredSize(new Dimension(300,50)); add(Box.createVerticalGlue()); add(l); l.setFont(l.getFont().deriveFont(style)); l.setAlignmentX(CENTER_ALIGNMENT); l.setHorizontalAlignment(JLabel.CENTER); add(Box.createVerticalGlue()); } public static void main(String[] args) { JFrame f = new JFrame("Alignment Test"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLayout(new GridLayout(1,0,5,5)); f.add(new AlignmentTest('a',Font.PLAIN)); f.add(new AlignmentTest('a',Font.BOLD)); f.add(new AlignmentTest('a',Font.ITALIC)); f.pack(); f.setVisible(true); } public void paintComponent(Graphics g) { super.paintComponent(g); g.drawLine(getWidth()/2,0,getWidth()/2,getHeight()); } } 
+6
source share
3 answers

Using JDK7 on Windows 7, none of the characters are centered.

I made some changes to display JTextField, and I played with JTextField (1, 3, 5) columns. As the columns grew, center alignment improved and was reasonable in columns 5 and above. So the problem is somehow related to the width of the component.

I would suggest that there is some strange rounding error in the layout. It seems to me a mistake.

If you are interested in a layout that provides some of the similar BoxLayout features, you can check the Relative layout . The changes in your example are minor:

 import javax.swing.*; import java.awt.*; import javax.swing.border.*; public class AlignmentTest extends JPanel { public AlignmentTest(char label, int style) { JLabel l = new JLabel(Character.toString(label)); setBorder(BorderFactory.createLineBorder(Color.BLACK,1)); setBackground(Color.WHITE); // setLayout(new BoxLayout(this,BoxLayout.Y_AXIS)); setLayout(new RelativeLayout(RelativeLayout.Y_AXIS)); setPreferredSize(new Dimension(300,50)); // add(Box.createVerticalGlue()); add(Box.createVerticalGlue(), new Float(1)); add(l); l.setFont(l.getFont().deriveFont(style)); l.setAlignmentX(CENTER_ALIGNMENT); l.setHorizontalAlignment(JLabel.CENTER); // add(Box.createVerticalGlue()); add(Box.createVerticalGlue(), new Float(1)); } public static void main(String[] args) { JFrame f = new JFrame("Alignment Test"); JScrollPane scroller = new JScrollPane(); JPanel panel = new JPanel(new GridLayout(1,0,5,5)); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLayout(new GridLayout(1,0,5,5)); f.add(new AlignmentTest('a',Font.PLAIN)); f.add(new AlignmentTest('a',Font.BOLD)); f.add(new AlignmentTest('a',Font.ITALIC)); f.pack(); f.setVisible(true); } public void paintComponent(Graphics g) { super.paintComponent(g); g.drawLine(getWidth()/2,0,getWidth()/2,getHeight()); } } 
+4
source

Another way to avoid "Box layout options: ... Any extra space appears to the right of the container", you need to override the JLabel#getMinimumSize() method to return the same Dimension as JLabel#getPreferredSize() .del>

I'm sorry, I did not understand.

As @camickr already said,

I would suggest that there is some strange rounding error in the layout. It seems to me a mistake.

quite correct.

Fixed example:

 //MinimumSize checkbox //selected true: set min width = 100px //selected false: set min width = 7px(default "a" width) //Here my attempt(I am running JDK 1.7.0_72 on Windows 7): import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; public class AlignmentTest4 extends JPanel { private static boolean FLAG = false; @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight()); } @Override public Dimension getPreferredSize() { return new Dimension(300, 80); } public static JLabel makeLabel(String label, int style) { JLabel l = new JLabel(label) { @Override public Dimension getPreferredSize() { return new Dimension(120, 30); } @Override public Dimension getMinimumSize() { Dimension d = super.getMinimumSize(); if (FLAG) { d.width = 100; } else { d.width = 7; } return d; //if (FLAG) { // return this.getPreferredSize(); //} else { // return super.getMinimumSize(); //} } }; l.setOpaque(true); l.setBackground(Color.ORANGE); l.setFont(l.getFont().deriveFont(style)); l.setAlignmentX(Component.CENTER_ALIGNMENT); l.setAlignmentY(Component.CENTER_ALIGNMENT); l.setVerticalAlignment(SwingConstants.CENTER); l.setVerticalTextPosition(SwingConstants.CENTER); l.setHorizontalAlignment(SwingConstants.CENTER); l.setHorizontalTextPosition(SwingConstants.CENTER); return l; } public static JComponent makePanel() { JPanel p = new JPanel(new GridLayout(0, 1, 5, 5)); JPanel p1 = new AlignmentTest4(); p1.setBorder(BorderFactory.createTitledBorder("BoxLayout.X_AXIS")); p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS)); p1.add(Box.createHorizontalGlue()); p1.add(makeLabel("a", Font.PLAIN)); p1.add(Box.createHorizontalGlue()); JPanel p2 = new AlignmentTest4(); p2.setBorder(BorderFactory.createTitledBorder("BoxLayout.Y_AXIS")); p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS)); p2.add(Box.createVerticalGlue()); p2.add(makeLabel("a", Font.PLAIN)); p2.add(Box.createVerticalGlue()); for (JPanel c : Arrays.asList(p1, p2)) { c.setBackground(Color.WHITE); p.add(c); } return p; } public static JComponent makeUI() { final JPanel p = new JPanel(new BorderLayout()); p.add(makePanel()); p.add(new JCheckBox(new AbstractAction("MinimumSize") { @Override public void actionPerformed(ActionEvent e) { FLAG = ((JCheckBox) e.getSource()).isSelected(); SwingUtilities.updateComponentTreeUI(p); } }), BorderLayout.SOUTH); return p; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } public static void createAndShowGUI() { JFrame f = new JFrame("Alignment Test"); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(makeUI()); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } } 
+5
source

The effect you are observing is an artifact of the BoxLayout path. Interpolation from How to use BoxLayout: Box layout options : "When BoxLayout exposes components from left to right, ... any additional space to the right of the container appears." When the initial size of the container container for the container is a small multiple of the label size (fixed), as shown below, the anomaly is minimal; stretch the frame horizontally to see how it grows. One of the tasks would be to minimize the extent to which the size of the container preferred by the container is artificially increased.

image

 import javax.swing.*; import java.awt.*; public class AlignmentTest extends JPanel { private final JLabel l; public AlignmentTest(String label, int style) { setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); setBackground(Color.WHITE); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); l = new JLabel(label, JLabel.CENTER); l.setFont(l.getFont().deriveFont(style)); l.setAlignmentX(CENTER_ALIGNMENT); l.setOpaque(true); l.setBackground(Color.cyan); add(Box.createVerticalGlue()); add(l); add(Box.createVerticalGlue()); } @Override public Dimension getPreferredSize() { int w = l.getPreferredSize().width; int h = l.getPreferredSize().height; return new Dimension(w * 3, h * 3); } public static void main(String[] args) { JFrame f = new JFrame("Alignment Test"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLayout(new GridLayout(1, 0, 5, 5)); f.add(new AlignmentTest("aMa", Font.PLAIN)); f.add(new AlignmentTest("aMa", Font.BOLD)); f.add(new AlignmentTest("aMa", Font.ITALIC)); f.pack(); f.setVisible(true); } public void paintComponent(Graphics g) { super.paintComponent(g); g.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight()); } } 
+4
source

Source: https://habr.com/ru/post/980555/


All Articles