【问题标题】:How to make a checkbox with an hyperlink如何制作带有超链接的复选框
【发布时间】:2016-03-20 04:34:52
【问题描述】:

问题:

我正在尝试在 Java 中创建一个复选框,其中包含文本中的超链接。

但是,我无法使链接可点击,只能点击链接,而不是整个文本。

这是我的示例代码:

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 显示一个简单的复选框,整个文本都可以单击并选中/取消选中该框。 这就是我制作frame2 的原因,它由一个复选框和一个JLabel 组成。 它工作得很好,但它是所有可点击的文本。

有什么办法只让链接可以点击吗?

谢谢

路飞


[编辑] 回复:

感谢@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 标记来完成。
  • 我已修改提供的文本以添加粗体和下划线标签&lt;b&gt;&lt;u&gt;,并且我已将超链接的颜色更改为正常链接。在其他情况下,您将拥有该链接,但它的颜色与您的文本相同。
  • 注意HyperlinkListener,每次鼠标悬停在链接上时都会生成一个事件,这就是为什么我用对应于“点击”的HyperlinkEvent.EventType.ACTIVATED过滤事件
  • 将字体大小/样式/颜色更改为整个文本真的很棘手,你需要使用我的技术,方法setFont在这里不起作用

享受:)


[EDIT2] 要知道的事情:

  • 如果您使用的是Nimbus Look&amp;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);

【问题讨论】:

    标签: java swing checkbox hyperlink jtextpane


    【解决方案1】:

    这不是一个非常动态或漂亮的解决方案,但您可以像这样使用多个标签:

    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);
    }
    

    【讨论】:

    • 是的,应该可以,但是不会有回线等属性。
    【解决方案2】:

    我知道如何在基本 JDK 中使超链接可点击的唯一方法是使用 JEditorPane。

    因此您可以创建一个包含两个组件的JPanel

    1. JCheckBox(无文字)
    2. 带有超链接的JEditorPane

    您可以轻松地将JEditorPane 自定义为透明且没有Border,因此这两个组件看起来像是一个组件。

    【讨论】:

    • 嗨@camickr,感谢您的回复。比 JEditorPane 更好我采用了更适合我的问题的 JTextPane。我已经编辑了我的问题以提供答复。
    猜你喜欢
    • 2019-12-10
    • 2014-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多