Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having a Left and Right Aligned Label inside a JCheckBox

I'll start with what I want then go from there:

+------------------------------------------+
|[] jCheckBox                       jLabel |
+------------------------------------------+

Basically I would like to have a JCheckBox with 2 segments of text, 1 left aligned and 1 right aligned. I would like the entire box to be clickable and act exactly like a JCheckBox(As in if I press my mouse down it highlights the box ect.).

Now I have tried:

  • Using HTML inside the text box, with a table along the lines of: <html><table width=100%><tr width=100%><td>Left Text</td><td align=right>Right Text</td></tr></table>. This produces [] Left TextRightText without any visual alignment.

  • Adding both the JCheckBox and the JLabel to a panel, however this would require me to implement all the mouse events and call the correct respective methods on the JCheckBox. I put this aside - however I am willing to reconsider if this is the only option

  • Adding the JLabel to the JCheckBox

    • Firstly this caused the JCheckBox to decide to change the font, so that had to be 'adjusted'
    • Secondly, the baselines were off by 1 or 2 pixels, This was fixed by implementing a LayoutManager that placed the JLabel on the baseline.
    • Thirdly, the JLabel overlapped with the JCheckBox text so I ad to adjust my layout manager, however the JCheckBox did not give a correct result from getPreferedSize()(of [1,1]).

So, basically my question is: How should I implement this?

like image 900
Opal Avatar asked Dec 20 '12 08:12

Opal


2 Answers

  • create parent JLabel, JLabel haven't implemented any LayoutManager, then to set there proper LayoutManager, I think that GridLayout (with 2 segments of text, 1 left aligned and 1 right aligned)

  • add there two JLabels with proper alignment (JLabel.setHorizontalAlignment(javax.swing.SwingConstants.XXX);)

  • put together JCheckBox with parent JLabel (JLabel.setLabelFor(JCheckBox);)

  • the same way for MultiIcon in the JLabel

like image 133
mKorbel Avatar answered Sep 22 '22 08:09

mKorbel


This is how I managed to implement it using a JCheckBox as a parent class. This is missing methods for setting the label's text and color.

package mock.dlect;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.LayoutManager;
import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.JLabel;

public class LeftRightCheck extends JCheckBox {

    private final static JCheckBox DEFAULT_CHECK_BOX = new JCheckBox();
    private final JLabel rightLabel;

    public LeftRightCheck(String leftText, String rightText, Icon icon,
            boolean selected) {
        super(leftText, icon, selected);
        rightLabel = new JLabel(rightText, TRAILING);
        // TODO figure out how to make the font work right on OSX
        this.setLayout(new BaseLineSingleElementLayoutManager(10));
        this.add(rightLabel);
    }

    @Override
    public final void setFont(Font font) {
        font = font.deriveFont(DEFAULT_CHECK_BOX.getFont().getSize2D());
        super.setFont(font);
        if (rightLabel != null) {
            rightLabel.setFont(font);
        }
    }

    private class BaseLineSingleElementLayoutManager implements LayoutManager {

        private int hgap;
        private Component component;

        public BaseLineSingleElementLayoutManager(int hgap) {
            this.hgap = hgap;
        }

        @Override
        public void addLayoutComponent(String name, Component comp) {
            // Do Nothing
        }

        @Override
        public void removeLayoutComponent(Component comp) {
            // Do Nothing
        }

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            if (parent != null && parent instanceof JCheckBox) {
                JCheckBox cc = (JCheckBox) parent;
                // These 2 lines will add the size of the checkbox to the
                // preferred size
                Dimension parentSize = DEFAULT_CHECK_BOX.getPreferredSize();
                parentSize.width += cc.getFontMetrics(cc.getFont()).
                        stringWidth(cc.getText()) + hgap;
                if (checkComponent(cc)) {
                    Dimension childSize = this.component.getPreferredSize();
                    parentSize.height = Math.max(parentSize.height,
                            childSize.height);
                    parentSize.width += childSize.width;
                }
                return parentSize;
            }
            return new Dimension();
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return preferredLayoutSize(parent);
        }

        @Override
        public void layoutContainer(Container parent) {
            if (!checkComponent(parent)) {
                return;
            }
            this.component.setSize(parent.getSize());
            this.component.setLocation(0, getBaseline(parent)
                    - getBaseline(this.component));
        }

        private int getBaseline(Component c) {
            return c.getBaseline(c.getWidth(), c.getHeight());
        }

        protected boolean checkComponent(Container parent) {
            if (parent == null) {
                return false;
            } else if (parent.getComponentCount() >= 1
                    && parent.getComponent(0).isVisible()) {
                this.component = parent.getComponent(0);
                return true;
            } else {
                return false;
            }
        }
    }
}
like image 22
Opal Avatar answered Sep 20 '22 08:09

Opal