Java 当一行更改为较大字体时,如何重新绘制JTextPane

Java 当一行更改为较大字体时,如何重新绘制JTextPane,java,swing,jtextpane,Java,Swing,Jtextpane,我有一个JTextPane,它的模型是DefaultStyledDocument。我注意到,如果显示文本,然后我使用setCharacterAttributes将一行中的每个字符更改为更大的字体,则该行中的字符的字体在显示中会如我所期望的那样发生更改,但其下的行不会移动,从而使行在显示中重叠 是否有办法强制JTextPane重新计算文本位置并重新显示自身(或其一部分)?我尝试使用changedUpdate设置一个DocumentListener,并且确实调用了changedUpdate,但是我找

我有一个
JTextPane
,它的模型是
DefaultStyledDocument
。我注意到,如果显示文本,然后我使用
setCharacterAttributes
将一行中的每个字符更改为更大的字体,则该行中的字符的字体在显示中会如我所期望的那样发生更改,但其下的行不会移动,从而使行在显示中重叠

是否有办法强制
JTextPane
重新计算文本位置并重新显示自身(或其一部分)?我尝试使用
changedUpdate
设置一个
DocumentListener
,并且确实调用了
changedUpdate
,但是我找不到方法让它重新绘制
JTextPane
<代码>重新验证()不起作用

编辑:在一个较小的测试用例中,行会自动移动,所以很明显我在程序中做的其他事情会干扰,但我还没有弄清楚是什么。无论如何,如果我无法确定是什么功能导致了问题以及如何解决问题,那么不使用
revalidate()
repaint()
就可以工作

编辑2:将JTextPane添加到JPanel,并使用
BoxLayout
BoxLayout.X_轴设置JPanel时,会出现问题。样本:

public class Demo extends JFrame {
    JPanel panel;
    JTextPane textPane;
    DefaultStyledDocument doc;

    SimpleAttributeSet smallText, bigText;

    public Demo() {
        super("Demo");
        doc = new DefaultStyledDocument ();
        textPane = new JTextPane(doc);
        panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
            // problem goes away if above line is removed
        panel.add(textPane);
        panel.setPreferredSize(new Dimension(1000, 500));
        textPane.setCaretPosition(0);
        textPane.setMargin(new Insets(5,5,5,5));
        getContentPane().add(panel, BorderLayout.CENTER);

        smallText = new SimpleAttributeSet();
        StyleConstants.setFontFamily(smallText, "SansSerif");
        StyleConstants.setFontSize(smallText, 16);

        bigText = new SimpleAttributeSet();
        StyleConstants.setFontFamily(bigText, "Times New Roman");
        StyleConstants.setFontSize(bigText, 32);

        initDocument();
        textPane.setCaretPosition(0);
    }

    protected void initDocument() {
        String initString[] =
                { "This is the first line.",
                  "This is the second line.",
                  "This is the third line." };

        for (int i = 0; i < initString.length; i ++) {
            try {
                doc.insertString(doc.getLength(), initString[i] + "\n",
                        smallText);
            } catch (BadLocationException e) {
            }
        }
    }

    private void createAndShowGUI() throws InterruptedException {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        new Demo().runMain();
    }

    private void runMain() throws Exception {
        SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                UIManager.put("swing.boldMetal", Boolean.FALSE);
                try {
                    createAndShowGUI();
                } catch (InterruptedException e) {
                }
            }
        });
        Thread.sleep(2000);
        doc.setCharacterAttributes(24, 24, bigText, false);
    }
}
公共类演示扩展了JFrame{
JPanel小组;
JTextPane textPane;
DefaultStyledDocument单据;
SimpleAttributeSet smallText、bigText;
公共演示(){
超级(“演示”);
doc=新的DefaultStyledDocument();
textPane=新的JTextPane(doc);
panel=新的JPanel();
panel.setLayout(新的BoxLayout(panel,BoxLayout.X_轴));
//若移除上面的线,问题就会消失
panel.add(文本窗格);
面板。设置首选尺寸(新尺寸(1000500));
textPane.setCaretPosition(0);
textPane.setMargin(新插图(5,5,5,5));
getContentPane().add(面板,BorderLayout.CENTER);
smallText=新的SimpleAttributeSet();
setFontFamily(smallText,“SansSerif”);
setFontSize(smallText,16);
bigText=新的SimpleAttributeSet();
setFontFamily(bigText,“Times New Roman”);
setFontSize(bigText,32);
initDocument();
textPane.setCaretPosition(0);
}
受保护的无效初始化文档(){
字符串initString[]=
{“这是第一行。”,
“这是第二行。”,
“这是第三行。”};
for(int i=0;i
调用
repaint()
它将重新绘制容器<代码>文档监听器
反映对文本文档的更改,因此在您的情况下是不合适的。您可以使用
DefaultStyledDocument.getStyle().addChangeListener()
来处理属性的更改。

我刚刚发现,向
JTextPane
添加
setMinimumSize
调用也可以:

        .......
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
            // problem goes away if above line is removed
        panel.add(textPane);
        textPane.setMinimumSize(new Dimension(1000, 500));  // NEW
        // These also work:
        // textPane.setMinimumSize(new Dimension(1, 1));   or
        // textPane.setMinimumSize(new Dimension(0, 0));
        panel.setPreferredSize(new Dimension(1000, 500));
        textPane.setCaretPosition(0);
        .......

这比将
JTextPane
包装在
JScrollPane
中的解决方案稍微好一点,因为后者即使在没有滚动条显示的情况下也会在边框附近显示一些额外的行。

没有SSCCEi的想法根本无法重现您的问题现在我正在尝试创建一个小示例,我也不能重现这个问题。我的较大示例使用了
DefaultStyledDocument
的子类和各种其他内容;我不确定是哪一个造成了问题。这需要一些研究才能弄清楚。我先把文本窗格放在滚动窗格中,这表明它在
BoxLayout
…@MadProgrammer中有问题。是的,这很有效!谢谢。好的,谢谢。有趣的是,在我尝试了
revalidate()
之后,我添加了
repaint()
,这样它就调用了
revalidate
,然后调用了
repaint
,但是没有用。但是调用
repaint
而不调用
revalidate
确实有效。我没有使用
样式
,因此您的其他建议没有帮助,而且无论如何,出于我的目的,我希望能够更改我想要更改的任何字符的字体,不仅仅是针对某个特定的
样式
。如果您没有使用某个样式,那么您所做的更改只会影响容器,唯一的方法是让它重新绘制自身,而不是特定的组件。我不认为这是真的。正如我在问题中所说,字体的变化反映在视图中;问题是它下面的线是否移动了。我已经了解了更多信息,将对问题进行编辑。它与
样式
文档侦听器反映对文本文档的更改无关,因此在您的情况下是不合适的。
-更改属性应视为更改。我相信这就是DocumentListener的
changedUpdate()
事件的目的。
Document
是模型,
JTextPane
是v