0

我正在开发一个数据库程序,其中 GUI 有多个输入区域,其中一些是 JTextPanes,用户可以在其中设置粗体、下划线和斜体样式。例如,当用户将光标紧邻已经是粗体的区域时,我希望他们键入的下一个文本也同样是粗体。到目前为止,唯一发生的事情是在粗体文本之后立即键入的文本是粗体的,但我似乎无法使在粗体文本之前键入的文本也同样是粗体。

我不确定这一切都不会令人困惑,所以这里有一个例子:假设句子“Java有趣”。已经在其中一个 JTextPanes 中。

如果用户将光标放在“is”的左侧或右侧,我希望他们在旁边键入的任何内容也都是粗体。像这样,“Java fooisbar 的乐趣”。

到目前为止,我只得到“Java foo isbar fun”。

下面是我用来向 JTextPane 的插入符号添加样式检测功能的方法,以及我认为可以做到这一点的方法。

我也尝试StyledEditorKit.BoldAction().actionPerformed(null)在 boldButton.setSelected(true) 之前或之后添加一个额外的 new ,但这没有任何效果。我也尝试tp.getStyledDocument().setCharacterAttributes(caretPosition -1, 1, asPrev, true)过,虽然这确实使下一个文本输入粗体,但结果是不可预测的,随机换行和丢失字符发生。Changing boldButton.setSelected(true)toboldButton.doClick()没有任何效果,也没有使用我的 ButtonAction 类将文本设置为粗体。

        int lastCaretPosition;
        public void formatAndAddFunctions(Component c) {
            Font normalFont = new Font("Tahoma", Font.PLAIN, 11);
            c.setFont(normalFont);
            
            if (c instanceof JTextField) {
                ((JTextField) c).setAlignmentX(Component.LEFT_ALIGNMENT);
                ((JTextField) c).addFocusListener(new java.awt.event.FocusAdapter() {
                     @Override
                     public void focusGained(java.awt.event.FocusEvent evt) {
                         ((JTextField) c).selectAll();
                         activeComponent = c;
                     }
                });
                UndoTool.addUndoFunctionality((JTextField) c);
            }
            
            if (c instanceof JScrollPane) {
                ((JScrollPane) c).setAlignmentX(Component.LEFT_ALIGNMENT);
                JViewport vp = ((JScrollPane) c).getViewport();
                JTextPane tp = (JTextPane) vp.getView();
                tp.setContentType("text/html");
                tp.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true);
                tp.addFocusListener(new java.awt.event.FocusAdapter() {
                     @Override
                     public void focusGained(java.awt.event.FocusEvent evt) {
                         activeComponent = tp;
                     }
                });
                UndoTool.addUndoFunctionality(tp);
                
                //look at the character attibutes before and after the caret to see if they are
                //formatted bold, underline, and/or italic
                lastCaretPosition = -1;
                tp.addCaretListener((CaretEvent ce) -> {
                    int caretPosition = tp.getCaretPosition();
                    if(caretPosition != lastCaretPosition) {
                        lastCaretPosition = caretPosition;
                        
                        Element charElementPrev = tp.getStyledDocument().getCharacterElement(caretPosition - 1);
                        AttributeSet asPrev = charElementPrev.getAttributes();
                        Element charElementAfter = tp.getStyledDocument().getCharacterElement(caretPosition);
                        AttributeSet asAfter = charElementAfter.getAttributes();

                        if ((StyleConstants.isBold(asPrev) || StyleConstants.isBold(asAfter)) && !boldButton.isSelected()) {
                            boldButton.setSelected(true);
                        } else if((!StyleConstants.isBold(asPrev) && !StyleConstants.isBold(asAfter)) && boldButton.isSelected()) {
                            boldButton.setSelected(false);
                        }

                        if ((StyleConstants.isUnderline(asPrev) || StyleConstants.isUnderline(asAfter)) && !ulButton.isSelected()) {
                            ulButton.setSelected(true);
                        } else if ((!StyleConstants.isUnderline(asPrev) && !StyleConstants.isUnderline(asAfter)) && ulButton.isSelected()) {
                            ulButton.setSelected(false);
                        }

                        if ((StyleConstants.isItalic(asPrev) || StyleConstants.isItalic(asAfter)) && !itButton.isSelected()) {
                            itButton.setSelected(true);
                        } else if ((!StyleConstants.isItalic(asPrev) && !StyleConstants.isItalic(asAfter)) && itButton.isSelected()) {
                            itButton.setSelected(false);
                        }
                    }
                });

                tp.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_B, java.awt.event.InputEvent.CTRL_DOWN_MASK), "boldKeystroke");
                tp.getActionMap().put("boldKeystroke", new ButtonAction("bold"));

                tp.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_U, java.awt.event.InputEvent.CTRL_DOWN_MASK), "underlineKeystroke");
                tp.getActionMap().put("underlineKeystroke", new ButtonAction("underline"));

                tp.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_I, java.awt.event.InputEvent.CTRL_DOWN_MASK), "italicKeystroke");
                tp.getActionMap().put("italicKeystroke", new ButtonAction("italic"));
            }
        }

并且,作为参考,粗体按钮的代码:

boldButton = new JToggleButton();
            
boldButton.setIcon(allIcons[39]);
boldButton.setRolloverIcon(allIcons[40]);
boldButton.setSelectedIcon(allIcons[41]);
boldButton.setToolTipText("Bold");
boldButton.setBorderPainted(false);
boldButton.setContentAreaFilled(false);
boldButton.setFocusable(false);
boldButton.setBorder(null);
boldButton.setMargin(noInset);
boldButton.addActionListener((java.awt.event.ActionEvent e) -> {
    new StyledEditorKit.BoldAction().actionPerformed(e);
    activeComponent.requestFocusInWindow();
});

奇怪的是,如果我将光标设置在粗体文本之前,然后单击 UI 中的粗体切换按钮,下一个键入的文本会变为粗体。但我似乎无法以编程方式实现这一点。有任何想法吗?

4

0 回答 0