您正在使用null
布局,所以没有什么可以按应有的方式工作。Swing 的核心设计是利用布局管理器。
您RefreshablePanel
没有可辨别的大小,这意味着当您添加到滚动窗格时,滚动窗格可能会简单地认为它的大小应该0x0
。 RefreshablePanel
需要向滚动窗格提供某种大小提示,最好通过getPreferredSize
方法
您可以使用JLabel
(文本包装在 html 中)或不可编辑JTextArea
来实现相同的结果
更新
快速检查您的代码。您将x
andy
值声明为static
并且您正在增加方法y
中的值paintComponent
static int x=10;
static int y=11;
protected void paintComponent(Graphics g){
super.paintComponent(g);
for (String line : description.split("\n"))
g.drawString(line, x, y += g.getFontMetrics().getHeight());
}
这意味着两件事。
- 如果您有多个实例,
RefreshablePanel
它们都将共享相同的x
/y
值并更新它们
y
不断更新到新位置,因此如果面板被绘制两次,在第二次绘制时,该y
位置将从第一次调用退出时的最后位置开始。
请记住,您无法控制绘画过程。绘制周期可以在系统决定它需要的任何时候执行...
将x
/y
值局部变量设置为paintComponent
方法...
更新
如果可用空间允许,滚动窗格将尝试匹配组件的首选大小。这可能意味着在您调整窗口大小之前可能不会出现滚动条...但是您使用的null
布局对您不起作用...
要影响滚动窗格的大小,您可以改用Scrollable
界面...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Scrollable01 {
public static void main(String[] args) {
new Scrollable01();
}
public Scrollable01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
RefreshablePanel pane = new RefreshablePanel();
pane.updateDescription("1. You're using null layouts, so nothing is going to work the way it should. Swing is designed at the core to utilise layout managers.");
pane.updateDescription("2. You're RefreshablePanel has no discernible size, meaning that when you add to the scroll pane, the scroll pane is likely to simply think it's size should 0x0. RefreshablePanel needs to provide some kind of size hint back to the scrollpane, preferably via the getPreferredSize method");
pane.updateDescription("3. You could use a JLabel (with text wrapped in html) or a non-editable JTextArea to achieve the same results");
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(pane));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class RefreshablePanel extends JPanel implements Scrollable {
public String description = "";
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 1010);
}
@Override
protected void paintComponent(Graphics g) {
int x = 10;
int y = 11;
super.paintComponent(g);
for (String line : description.split("\n")) {
g.drawString(line, x, y += g.getFontMetrics().getHeight());
}
}
void updateDescription(String dataToAppend) {
description = description.concat("\n").concat(dataToAppend);
System.out.println("The description is " + description);
repaint();
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(400, 400);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}