获取 JTextPane 中选中文本的属性

Get attributes of selected text in JTextPane

我正在尝试了解如何获取 JTextPane 中某些选定文本的属性。 我发现最好的解决方案是使用 getInputAttributes() 和 CaretListener 来实现,但是我在这个实现上遇到了一些问题。

这是我的解决方案,显示了插入符号最后位置的文本属性,而不是插入符号的实际位置。我究竟做错了什么?请。

这是我的 SSCCE:

public class Testovani{
static JTextPane pane;
static JLabel label;

public static void main(String[] args) throws BadLocationException {
    JFrame frame = new JFrame();
    frame.setSize(350, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new BorderLayout());
    
    pane = new JTextPane();
    label = new JLabel();
    pane.addCaretListener(new SelectionListener());
    
    MutableAttributeSet attrs = new SimpleAttributeSet();
    StyleConstants.setBold(attrs, true);
    pane.getDocument().insertString(0, "\n", null);
    pane.getDocument().insertString(0, "This is first row non bold", null);
    pane.getDocument().insertString(0, "\n", null);
    pane.getDocument().insertString(0, "This is second row bold", attrs);
    pane.getDocument().insertString(0, "\n", null);
    pane.getDocument().insertString(0, "This is third row bold", attrs);
    pane.getDocument().insertString(0, "\n", null);
    
    frame.add(pane);
    frame.add(label, BorderLayout.SOUTH);
    frame.setVisible(true);
}

private static class SelectionListener implements CaretListener{
    @Override
    public void caretUpdate(CaretEvent e) {
        AttributeSet attrs =((StyledEditorKit)pane.getEditorKit()).getInputAttributes();
        label.setText("Is bold: " + String.valueOf(StyleConstants.isBold(attrs)));
    }   
}}

我还有两个奖励问题。这种方法是用于选择还是仅用于插入符号的位置?还有什么 returns,如果有一个文本选择,其中一部分是粗体而第二部分不是?

其实选择属性是个复杂的问题,需要你了解业务需求。

假设选择了一段文本并且您需要选择字体大小。但 该片段有 3 段不同的文本,有 3 种不同的大小。

选择开始位置放在10pt文本的中间,然后一段12pt大小的文本和选择结束在14pt大小片段的中间。

您想要什么尺寸? 10、12、14 或(多个)?

最简单的方法是使用 inputAttributes。

默认情况下,属性是从插入符位置复制的,但当然您可以添加一个插入符侦听器,并在每次更新时根据您的业务逻辑检查并根据需要填充输入属性(处理具有不同属性的多个文本片段).

更新: 尝试将 AttributeSet attrs =((StyledEditorKit)pane.getEditorKit()).getInputAttributes(); 包装在 SwingUtilities.invokeLater() 调用

获取选区的属性没有预期的行为,只是因为选区可以包含具有不同属性的字符元素。

您必须了解,getInputAttributes returns textPane 为下一个输入计算的最佳属性与 getCharacterAttributes returns 当前插入符位置的属性。在选择的情况下,插入符号是您结束选择的位置。如果您从左到右或从右到左选择文本,它可以是给定的 getSelectionStartgetSelectionEnd

无论如何,我建议您获取 JTextPane 的 StyledDocument,然后遍历从 getSelectionStartgetSelectionEnd 的字符元素:

for(int i=jtp.getSelectionStart(); i<jtp.getSelectionEnd(); i++) {
    AttributeSet set = jtp.getStyledDocument().getCharacterElement(i).getAttributes();
    //here, combine, analyse, do whatever you like with your AttributeSet
    //You can use StyleConstants.xxx to analyse the attributes
}

我使用@Sharcoux 的解决方案并做了一处更改:我确保始终至少有一个字符可以迭代。当没有选择时,getSelectionStart() == getSelectionEnd()。出于这个原因,我会稍微改变一下:

int iStart = jtp.getSelectionStart();
int iEnd = jtp.getSelectionEnd();
if(iStart > 0) iStart--;
else if(iEnd < jtp.getDocument().getEndPosition().getOffset()) iEnd++;
for(int i = iStart; i < iEnd; i++) {
    AttributeSet set = jtp.getStyledDocument().getCharacterElement(i).getAttributes();
    //here, combine, analyse, do whatever you like with your AttributeSet
    //You can use StyleConstants.xxx to analyse the attributes
}

唯一没有改变的情况是文档完全为空时,在这种情况下 getInputAttributes 应该可以正常工作。