JTextPane固定宽度的首选大小

4
我有一个问题,如何在给定固定宽度的情况下轻松计算JTextPane的首选大小/高度。到目前为止,我已经将我的JTextPane放在JScrollPane中,并且每当我更新文本时,我都会更新JScrollPane的大小。现在,这很好用(尽管我觉得我的代码有些扭曲,但它可以工作),但是当我添加新行时,需要两次调用更新scrollpane高度的代码:一次立即调用,第二次使用invokeLater。我正在寻找一种避免invokeLater()的方法。任何方法都可以,包括在组件上分派事件、覆盖Swing方法等...
以下是说明所有内容的片段:
import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class Test {

    private static MyEventQueue queue;

    private static final class MyEventQueue extends EventQueue {

        public boolean log = false;

        @Override
        protected void dispatchEvent(AWTEvent event) {
            if (log) {
                System.err.println(event.getClass().getName() + " " + event.getSource());
            }
            super.dispatchEvent(event);
        }
    }

    public static class WrapApp extends JFrame {
        JTextPane edit = new JTextPane() {
            @Override
            public boolean getScrollableTracksViewportWidth() {
                return true;
            }

        };
        private JScrollPane comp;

        protected void updateVPSize() {
            updateSize(true);
        }

        protected void updateSize(boolean repeat) {
            edit.setSize(150, 1000);
            Dimension size = edit.getPreferredScrollableViewportSize();
            System.err.println("Before " + size);
            size.width = 150;
            comp.setSize(size);
            if (repeat) {
                queue.log = true;
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        queue.log = false;
                        updateSize(false);
                    }
                });
            }
        }

        public WrapApp() {
            super("Forced wrap/no wrap example");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            getContentPane().setLayout(null);
            edit.getDocument().addDocumentListener(new DocumentListener() {

                @Override
                public void removeUpdate(DocumentEvent e) {
                    updateVPSize();
                }

                @Override
                public void insertUpdate(DocumentEvent e) {
                    updateVPSize();
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    updateVPSize();
                }
            });
            comp = new JScrollPane(edit) {
                @Override
                public void setSize(int width, int height) {
                    super.setSize(width, height);
                };
            };
            comp.setBorder(null);
            comp.setLocation(0, 0);
            comp.setViewportBorder(null);
            comp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            edit.setText("Some long text that needs to be wrapped on several lines.\n\nBut this is not the end of it, it can go on and on and on and on...Some long text that needs to be wrapped on several lines.\n\nBut this is not the end of it, it can go on and on and on and on...");
            getContentPane().add(comp);
            setSize(300, 700);
            setLocationRelativeTo(null);
            updateVPSize();
        }
    }

    public static void main(String[] args) {
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(queue = new MyEventQueue());
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                WrapApp m = new WrapApp();
                m.setVisible(true);

            }
        });
    }

}

不要太在意里面剩下的东西,我尝试了很多东西。


请问为什么您想要设置JScrollPane,有重要的原因吗?顺便点个赞,这是一个有趣的问题。对不起,我不确定它是关于LayoutManager还是JTextComponent内容的问题。 - mKorbel
不,如果我可以在没有滚动窗格的情况下完成它,那对我来说就很好了。但是我需要JTextPane来包装其内容,到目前为止,这是我找到的一个丑陋但可行的解决方案。 - Guillaume Polet
1个回答

4

是的,我已经看到了那个链接,但不幸的是(我完全不知道为什么),这适用于 JEditorPane,但不适用于 JTextPane - Guillaume Polet
你设置相同的工具包吗?你不设置垂直大小吗?你是指使用JEditorPane而不是JTextPane进行工作吗?效果是什么? - StanislavL
很抱歉,我的评论部分是不正确的。它也适用于JTextPane,只是使用JEditorPane时,宽度和高度都是正确的,而使用JTextPane时,只有高度是正确的。如果您查看我的代码,您会发现它实际上是受到您链接中所示想法的启发。但是我想要的是在编辑JTextPane后获得正确的高度。不知何故,我必须进行两次传递,我希望它只是一种单通机制。 - Guillaume Polet
FYI,这不适用于文本/rtf JEditorPane,只适用于纯文本。 - Sam Barnum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接