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.
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 withHyperlinkEvent.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);