我有一个关于如何在给定固定宽度的情况下轻松计算 JTextPane 的首选大小/高度的问题。到目前为止,我所做的是将我的 JTextPane 放入 JScrollPane 中,每当我更新文本时,我都会更新 JScrollPane 的大小。现在,这很好用(虽然我发现我的代码有点扭曲,但它可以工作)但是当我添加一个新行时,我更新滚动窗格高度的代码需要调用两次:一次立即调用,第二次使用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);
}
});
}
}
真的不介意所有剩下的东西,我尝试了一堆东西