简体   繁体   English

如何在JTextPane中为文本设置StrikeThrough和Underline样式选项?

[英]How do I set both StrikeThrough and Underline styling options for text inside a JTextPane?

I have a JTextPane component and I am trying to style the text that will be typed by the user to be both underline and strikethrough at the same time. 我有一个JTextPane组件,我正在尝试将用户键入的文本设置为同时加下划线和删除线。

The relevant snippet of code that that should set the strikethrough attribute of the next typed character to true is this: 应该将下一个类型字符的删除线属性设置为true的相关代码片段如下:

JEditorPane editor = getEditor(e);
if (editor != null) {
     StyledEditorKit kit = getStyledEditorKit(editor);
     MutableAttributeSet attr = kit.getInputAttributes();            
     SimpleAttributeSet sas = new SimpleAttributeSet();
     StyleConstants.setStrikeThrough(sas, true);                
     setCharacterAttributes(editor, sas, false);
}

This does style the text as strikethrough, but if it was already styled as underline, it loses the underline styling information. 这样可以将文本设置为删除线,但如果它已经设置为下划线,则会丢失下划线样式信息。 Taking a close look at the actual code behind StyleConstants.setStrikeThrough(...) I have noticed that the CSS styling tag for both underline and strikethrough attributes will be the same (ie "text-decoration") and when the value is updated in the hashtable holding the attributes, it will be overriden. 仔细看看StyleConstants.setStrikeThrough(...)背后的实际代码我注意到下划线和删除线属性的CSS样式标签将是相同的(即“文本装饰”)并且当值更新时保存属性的哈希表,它将被覆盖。

This means that code like: 这意味着代码如下:

StyleConstants.setStrikeThrough(sas, true);
StyleConstants.setUnderlineThrough(sas, true);

will result in the next typed character being underlined without a strikethrough. 将导致下一个键入的字符加下划线而没有删除线。 I've checked the attribute values and for the "text-decoration" attribute the value is "underline", whereas I was expecting "line-through,underline". 我检查了属性值,对于“text-decoration”属性,值是“下划线”,而我期待“直通,下划线”。

Does anyone know how to achieve this in a clean Swing compliant way? 有谁知道如何以一个干净的Swing兼容方式实现这一目标? Is there something wrong in my approach? 我的方法有问题吗? Is there an underlying assumption at the core of JTextPane styling that text should not be strikethrough and underline at the same time? 在JTextPane样式的核心是否存在一个潜在的假设,即文本不应该同时删除并强调下划线?

Why not working with StyledDocument and using two Style : primary and secondary , where primary is parent style of secondary : 为什么不使用StyledDocument并使用两个Styleprimarysecondary ,其中primarysecondary父样式:

在此输入图像描述

  StyledDocument styleDocument =  jTextPane1.getStyledDocument();
  Style primaryStyle = styleDocument.addStyle("Primary", null);
  Style secondaryStyle = styleDocument.addStyle("Secondary", primaryStyle);


  StyleConstants.setFontFamily(primaryStyle, "American Captain");
  StyleConstants.setFontSize(primaryStyle, 24);

//  StyleConstants.setFontFamily(secondaryStyle, "Bira PERSONAL USE ONLY");
  StyleConstants.setFontSize(secondaryStyle, 20);
  StyleConstants.setForeground(primaryStyle, new Color(0x552AFF));
  StyleConstants.setForeground(secondaryStyle, Color.black);
  StyleConstants.setStrikeThrough(secondaryStyle, true);
  StyleConstants.setUnderline(primaryStyle, true);

  try {
      styleDocument.insertString(0, "Title with American Captain font\n\n", primaryStyle);
      styleDocument.insertString(styleDocument.getLength(), "Font demonstration with JTextPane. "
              + "Seriously, it is powerful and has the power to do all kind of styling with text. "
              + "check it out, check its mighty power and be embrassed\n", secondaryStyle);
   } catch (BadLocationException ex) {
                Logger.getLogger(JTextPaneTest.class.getName()).log(Level.SEVERE, null, ex);
   }

Edit: 编辑:

imagine you have 4 toggle buttons - italic, bold, underline and strikethrough. 想象你有4个切换按钮 - 斜体,粗体,下划线和删除线。 Each time one of those is pressed or unpressed I need to adjust the styling as necessary for the character that will be typed next. 每次按下或未按下其中一个时,我需要根据下一个要键入的角色调整样式。

Yes, the answer still lies in the preference of using DefaultStyleDocument and extending it. 是的,答案仍然在于使用DefaultStyleDocument并扩展它的偏好。 The above example should give an idea how styling with Style works while inserting string with styleDocument.insertString(int offs, String str, AttributeSet a) method. 上面的示例应该让我们了解在使用styleDocument.insertString(int offs, String str, AttributeSet a)方法插入字符串时样式的Style是如何工作的。 When we are inserting data using KeyBoard or copy-paste the associating StyleDocument 's insertString function always gets called. 当我们使用KeyBoard插入数据或copy-paste ,总是会调用关联的StyleDocumentinsertString函数。

So, to style like a text editor as you are wanting, all you have to do is to extends the DefaultStyleDocument and override this insertString function and pass the specific style attribute you want. 因此,要像文本编辑器一样设置样式,您所要做的就是扩展DefaultStyleDocument并覆盖此insertString函数并传递所需的特定样式属性。

A Demo example satisfying your complete requirement should make this things clear. 满足您的完整要求的演示示例应该清楚地说明这一点。

在此输入图像描述

class CStyleDocument extends DefaultStyledDocument
{
    private  Style primaryStyle;

    public CStyleDocument() {
        super();
         primaryStyle = this.addStyle("Primary", null);
    }
    public Style getAttrStyle()
    {
        return primaryStyle;
    }

    @Override
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        super.insertString(offs, str, primaryStyle); 

    }

}

public class JTextPaneTest extends javax.swing.JFrame {

    CStyleDocument styleDocument;

    public JTextPaneTest() {
        initComponents();

        styleDocument = new CStyleDocument();
        jTextPane1.setDocument(styleDocument);

}

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTextPane1 = new javax.swing.JTextPane();
        jPanel1 = new javax.swing.JPanel();
        boldSelButton = new javax.swing.JToggleButton();
        ulSelButton = new javax.swing.JToggleButton();
        strkSelButton = new javax.swing.JToggleButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setMinimumSize(new java.awt.Dimension(400, 200));

        jScrollPane1.setViewportView(jTextPane1);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

        boldSelButton.setText("Bold");
        boldSelButton.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                boldSelButtonStateChanged(evt);
            }
        });
        jPanel1.add(boldSelButton);

        ulSelButton.setText("Under Lined");
        ulSelButton.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                ulSelButtonStateChanged(evt);
            }
        });
        jPanel1.add(ulSelButton);

        strkSelButton.setText("Strike Through");
        strkSelButton.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                strkSelButtonStateChanged(evt);
            }
        });
        jPanel1.add(strkSelButton);

        getContentPane().add(jPanel1, java.awt.BorderLayout.PAGE_START);

        pack();
    }// </editor-fold>                        

    private void boldSelButtonStateChanged(javax.swing.event.ChangeEvent evt) {                                           
             StyleConstants.setBold(styleDocument.getAttrStyle(), ((JToggleButton)evt.getSource()).isSelected());
             jTextPane1.requestFocus();




    }                                          

    private void ulSelButtonStateChanged(javax.swing.event.ChangeEvent evt) {                                         
        StyleConstants.setUnderline(styleDocument.getAttrStyle(), ((JToggleButton)evt.getSource()).isSelected());
        jTextPane1.requestFocus();
    }                                        

    private void strkSelButtonStateChanged(javax.swing.event.ChangeEvent evt) {                                           
       StyleConstants.setStrikeThrough(styleDocument.getAttrStyle(), ((JToggleButton)evt.getSource()).isSelected());
       jTextPane1.requestFocus();
    }                                          


    public static void main(String args[]) {

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JTextPaneTest();
                frame.setVisible(true);

            }
        });
    }
    // Variables declaration - do not modify                     
    private javax.swing.JToggleButton boldSelButton;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextPane jTextPane1;
    private javax.swing.JToggleButton strkSelButton;
    private javax.swing.JToggleButton ulSelButton;
    // End of variables declaration                   
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM