How to make a checkbox with an hyperlink
Asked Answered
N

2

6

Question :

I'm try to create an check-box in Java that contains in the text an hyper-link.

But, I couldn't make the link clickable, and only the link, not the whole text.

enter image description here

Here my sample code :

public class TestClickLinkInCheckBox implements MouseListener {

    private JFrame frame1;
    private JFrame frame2;
    private String linkedText = "I have checked the data set I have selected, and agree to sign it following <a href=\"http://www.google.com\">the conditions of use of the service, defined in the policies of signature and certification</a> that I attest having read.";
    private JLabel label;

    public TestClickLinkInCheckBox() {
        justCheckBox();
        checkBoxWithLabel();
    }

    private void justCheckBox() throws HeadlessException {
        frame1 = new JFrame();
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50));
        JCheckBox checkBox = new JCheckBox(prettyText(linkedText, 300, "left"));
        panel.add(checkBox);
        frame1.add(panel);
    }

    private void checkBoxWithLabel() {
        frame2 = new JFrame();
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50));

        JCheckBox checkBox = new JCheckBox();
        panel.add(checkBox);

        label = new JLabel(prettyText(linkedText, 300, "left"));
        label.addMouseListener(this);
        panel.add(label);

        frame2.add(panel);
    }

    private void display() {
        frame1.setVisible(true);
        frame1.pack();
        frame2.setVisible(true);
        frame2.pack();
    }

    public static String prettyText(String badText, int length, String textAlign) {
        return "<html><body width='" + String.valueOf(length) + "px'><div style=\"text-align: " + textAlign + ";\">"+ badText.replace("|||", "<br>") + "</html>";
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getSource() == label) {
            JOptionPane.showConfirmDialog(frame2, "Clicked");
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {}
    @Override
    public void mouseReleased(MouseEvent e) {}
    @Override
    public void mouseEntered(MouseEvent e) {}
    @Override
    public void mouseExited(MouseEvent e) {}

    public static void main(String[] args) {
        TestClickLinkInCheckBox test = new TestClickLinkInCheckBox();
        test.display();
    }
}

The frame1 show a simple check-box and the whole text is clickable and check/uncheck the box. That's why I made the frame2, made by the composition of a check box and and a JLabel. It work well, but it's all the text that is clickable.

Are there any way to have only the link clickable ?

Thanks

Luffy


[EDIT] Reponse :

Thanks to @camickr to give me a piece of response.

Here the solution, that is not so easy to do at the end :

public class TestClickLinkInCheckBox implements HyperlinkListener {

    private JFrame frame;
    private String linkedText = "I have checked the data set I have selected, and agree to sign it following <b><u><a href=\"http://www.google.com\" style=\"color: #0000ff\">the conditions of use of the service, defined in the policies of signature and certification</a></u></b> that I attest having read.";
    private JTextPane textPane;

    public static void main(String[] args) {
        TestClickLinkInCheckBox test = new TestClickLinkInCheckBox();
        test.display();
    }

    public TestClickLinkInCheckBox() {
        checkboxWithJEditorPanel();
    }

    private void checkboxWithJEditorPanel() {
        frame = new JFrame();
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50));

        JCheckBox checkBox = new JCheckBox();
        panel.add(checkBox);

        textPane = new JTextPane();
        textPane.setContentType("text/html");
        textPane.setOpaque(false);
        textPane.setDocument(new HTMLDocument());
        textPane.setText(prettyText(linkedText, 300, "left"));
        textPane.setEditable(false);
        textPane.addHyperlinkListener(this);

         setFontSize(16);

        panel.add(textPane);

        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void setFontSize(int size) {
        MutableAttributeSet attrs = textPane.getInputAttributes();
         StyleConstants.setFontSize(attrs, size);
         StyledDocument document = textPane.getStyledDocument();
         document.setCharacterAttributes(0, document.getLength() + 1, attrs, false);
    }

    private void display() {
        frame.setVisible(true);
        frame.pack();
    }

    public static String prettyText(String badText, int length, String textAlign) {
        return "<html><body width='" + String.valueOf(length) + "px'><div style=\"text-align: " + textAlign + ";\">"+ badText.replace("|||", "<br>") + "</html>";
    }

    @Override
    public void hyperlinkUpdate(HyperlinkEvent e) {
        if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
            System.out.println(e.getURL());
        }
    }
}

Some explanations to understand :

  • I have use the JtextPane in place of the JEditorPane because the text doesn't wrap in the text editor and I could do it with my html tag.
  • I have modified the text provided to add the bold and underline tags <b><u> and also I have change the color to the hyperlink to be as a normal link. In other case, you will have the link, but it will have the same color of your text.
  • Pay attention at the HyperlinkListener that generate an event each time your mouse is over the link, that why I have filtered the event with HyperlinkEvent.EventType.ACTIVATED that correspond to a 'click'
  • Chang the font size/style/color to the whole text it's really tricky, you need to use my technics, the methods setFont doesn't work here

Enjoy :)


[EDIT2] Something to know :

  • In the case you are using the Nimbus Look&Feel :

    try {
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    

There are a bug and you will have a white background. So you need to fix it by adding this piece of code instead of a setBackground() method :

    Color bgColor = panel.getBackground();
    UIDefaults defaults = new UIDefaults();
    defaults.put("TextPane[Enabled].backgroundPainter", bgColor);
    textPane.putClientProperty("Nimbus.Overrides", defaults);
    textPane.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
    textPane.setBackground(bgColor);

Same for a JEditorPane but change the line

    defaults.put("EditorPane[Enabled].backgroundPainter", bgColor);
Nomadic answered 14/12, 2015 at 15:58 Comment(0)
C
5

The only way I know how to make a hyperlink clickable in the base JDK is to use a JEditorPane.

So you could create a JPanel with two components:

  1. a JCheckBox (with no text)
  2. a JEditorPane with your hyperlink

You can easily customize the JEditorPane to be transparent and without a Border so it looks like the two components are a single component.

Canthus answered 14/12, 2015 at 16:10 Comment(1)
Hi @camickr, thanks for your response. Better than JEditorPane I took the JTextPane that fit better for my problem. I have edited my question to provide the response.Nomadic
V
0

This is not a very dynamic or pretty solution but you could use multiple Labels like this:

private String beforeLinkText = "I have checked the data set I have selected, and agree to sign it following";
private String linkedText = " <a href=\"http://www.google.com\">the conditions of use of the service, defined in the policies of signature and certification</a> ";
private String afterLinkText = "that I attest having read.";

private void checkBoxWithLabel() {
        frame2 = new JFrame();
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50));

        JCheckBox checkBox = new JCheckBox();
        panel.add(checkBox);

        label = new JLabel(prettyText(linkedText, 400, "left"));
        label.addMouseListener(this);

        JPanel cbTextPanel = new JPanel (new FlowLayout(FlowLayout.LEFT));
        cbTextPanel.setPreferredSize(new Dimension(500,70));
        cbTextPanel.add(new JLabel(beforeLinkText));
        cbTextPanel.add(label);
        cbTextPanel.add(new JLabel(afterLinkText));
        panel.add(cbTextPanel);


        frame2.add(panel);
}
Vickivickie answered 14/12, 2015 at 17:11 Comment(1)
Yeah, it should work, but it will not have the property of coming back to line, etc.Nomadic

© 2022 - 2024 — McMap. All rights reserved.