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

我有一个JTextPane组件,我正在尝试将用户键入的文本设置为同时加下划线和删除线。

应将下一个类型字符的删除线属性设置为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); } 

这样可以将文本设置为删除线,但如果它已经设置为下划线,则会丢失下划线样式信息。 仔细看看StyleConstants.setStrikeThrough(…)背后的实际代码我注意到下划线和删除线属性的CSS样式标签将是相同的(即“文本装饰”),当值更新时保存属性的哈希表,它将被覆盖。

这意味着代码如下:

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

将导致下一个键入的字符加下划线而没有删除线。 我检查了属性值,对于“text-decoration”属性,值是“下划线”,而我期待“直通,下划线”。

有谁知道如何以一个干净的Swing兼容方式实现这一目标? 我的方法有问题吗? 在JTextPane样式的核心是否存在一个潜在的假设,即文本不应该同时删除并强调下划线?

为什么不使用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); } 

编辑:

想象你有4个切换按钮 – 斜体,粗体,下划线和删除线。 每当其中一个被按下或未按下时,我需要根据下一个要键入的角色调整样式。

是的,答案仍然在于使用DefaultStyleDocument并扩展它的偏好。 上面的示例应该让我们了解在使用styleDocument.insertString(int offs, String str, AttributeSet a)方法插入字符串时样式的Style是如何工作的。 当我们使用KeyBoard插入数据或copy-paste ,总是会调用关联的StyleDocumentinsertString函数。

因此,要像文本编辑器一样设置样式,您所要做的就是扩展DefaultStyleDocument并覆盖此insertString函数并传递所需的特定样式属性。

满足您的完整要求的演示示例应该清楚地说明这一点。

在此处输入图像描述

 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") //  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(); }//  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 }