如何在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
并使用两个Style
: primary
和secondary
,其中primary
是secondary
父样式:
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
,总是会调用关联的StyleDocument
的insertString
函数。
因此,要像文本编辑器一样设置样式,您所要做的就是扩展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 }