如何制作带有超链接的复选框
How to make a checkbox with an hyperlink
问题:
我尝试在 Java 中创建一个复选框,在文本中包含一个超 link。
但是,我无法使 link 可点击,只有 link,而不是整个文本。
这是我的示例代码:
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();
}
}
frame1
显示一个简单的复选框,整个文本都是可点击的,check/uncheck 框。
这就是为什么我制作了frame2
,由一个复选框和一个JLabel 组成。
它运行良好,但它是所有可单击的文本。
有什么方法可以只让 link 可点击吗?
谢谢
路飞
[编辑] 回复:
感谢@camickr 给我的回复。
这里是解决方案,最后不是那么容易做到:
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());
}
}
}
一些理解的解释:
- 我使用 JtextPane 代替 JEditorPane,因为文本不会在文本编辑器中换行,我可以使用我的 html 标签来完成。
- 我已经修改了提供的文本以添加粗体和下划线标记
<b><u>
并且我已经将 hyperlink 的颜色更改为正常颜色 link。在其他情况下,您将拥有 link,但它的颜色与您的文本相同。
- 注意
HyperlinkListener
每次鼠标悬停在 link 上时都会生成一个事件,这就是为什么我用 HyperlinkEvent.EventType.ACTIVATED
过滤了对应于 'click'
- 把字体size/style/color改成全文真的有技巧,要用我的技术,方法
setFont
这里不行
尽情享受吧:)
[EDIT2] 要知道的事情:
如果您使用的是 Nimbus Look&Feel
:
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
有一个错误,你将有一个白色的背景。所以你需要通过添加这段代码而不是 setBackground()
方法来修复它:
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);
与 JEditorPane 相同,但更改行
defaults.put("EditorPane[Enabled].backgroundPainter", bgColor);
我知道如何在基础 JDK 中使超链接可点击的唯一方法是使用 JEditorPane。
因此您可以创建一个包含两个组件的 JPanel
:
- a
JCheckBox
(无文字)
- a
JEditorPane
与您的超链接
您可以轻松地将 JEditorPane
自定义为透明且没有 Border
,这样看起来这两个组件是一个组件。
这不是一个非常动态或漂亮的解决方案,但您可以像这样使用多个标签:
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);
}
问题:
我尝试在 Java 中创建一个复选框,在文本中包含一个超 link。
但是,我无法使 link 可点击,只有 link,而不是整个文本。
这是我的示例代码:
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();
}
}
frame1
显示一个简单的复选框,整个文本都是可点击的,check/uncheck 框。
这就是为什么我制作了frame2
,由一个复选框和一个JLabel 组成。
它运行良好,但它是所有可单击的文本。
有什么方法可以只让 link 可点击吗?
谢谢
路飞
[编辑] 回复:
感谢@camickr 给我的回复。
这里是解决方案,最后不是那么容易做到:
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());
}
}
}
一些理解的解释:
- 我使用 JtextPane 代替 JEditorPane,因为文本不会在文本编辑器中换行,我可以使用我的 html 标签来完成。
- 我已经修改了提供的文本以添加粗体和下划线标记
<b><u>
并且我已经将 hyperlink 的颜色更改为正常颜色 link。在其他情况下,您将拥有 link,但它的颜色与您的文本相同。 - 注意
HyperlinkListener
每次鼠标悬停在 link 上时都会生成一个事件,这就是为什么我用HyperlinkEvent.EventType.ACTIVATED
过滤了对应于 'click' - 把字体size/style/color改成全文真的有技巧,要用我的技术,方法
setFont
这里不行
尽情享受吧:)
[EDIT2] 要知道的事情:
如果您使用的是
Nimbus Look&Feel
:try { for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (Exception e) { e.printStackTrace(); }
有一个错误,你将有一个白色的背景。所以你需要通过添加这段代码而不是 setBackground()
方法来修复它:
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);
与 JEditorPane 相同,但更改行
defaults.put("EditorPane[Enabled].backgroundPainter", bgColor);
我知道如何在基础 JDK 中使超链接可点击的唯一方法是使用 JEditorPane。
因此您可以创建一个包含两个组件的 JPanel
:
- a
JCheckBox
(无文字) - a
JEditorPane
与您的超链接
您可以轻松地将 JEditorPane
自定义为透明且没有 Border
,这样看起来这两个组件是一个组件。
这不是一个非常动态或漂亮的解决方案,但您可以像这样使用多个标签:
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);
}