在JScrollPane的标题视图上多次调用paintComponent

时间:2018-08-13 05:00:47

标签: java swing jscrollpane jtextarea

我的应用程序随附了一个基于Swing的记录器,记录器应在日志输出的每一行旁边显示行号。

日志输出显示在JTextAreaJScrollPane中。

我在自定义视图中使用setRowHeaderView()来显示行号。

我遇到的问题是,在用于显示行号的自定义iew中,paintComponent()方法似乎每次更新都被调用两次,第二次有不正确的clipBounds。

创建TextArea:

public static void main(String[] args) {

    JFrame frame = new JFrame();

    JScrollPane scroll = new JScrollPane(new JTextArea(50, 150));
    scroll.setRowHeaderView(new MyHeaderView());

    frame.add(scroll);
    frame.pack();
    frame.setVisible(true);
}

然后

public class MyHeaderView extends JPanel {

    private final int pxPerLine;

    public MyHeaderView() {
        super();

        this.setPreferredSize(new Dimension(50, 10));

        FontMetrics fm = getFontMetrics(getFont());
        this.pxPerLine = (int) (fm.getHeight() / 2.0f) + 2;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Rectangle clip = g.getClipBounds();

        System.out.println(clip.toString());

        g.setColor(Color.BLACK);
        g.fillRect(clip.x, clip.y, clip.width, clip.height);

        int pxStart = clip.y;
        int stStart = pxStart / pxPerLine;
        int stCount = clip.height / pxPerLine;

        g.setColor(Color.YELLOW);
        for (int x = 0; x < stCount; x++) {
            String t = "" + (stStart + x);
            g.drawString(t, 5, pxStart + (pxPerLine * x));
        }
    }
}

无论我滚动到什么地方,结果都是这样的:

enter image description here

但是,如果我使用调试器并逐步完成paintComponent方法,则可以看到每次绘制数字时,该方法都会被调用两次。第一次g.getClipBounds()返回正确的值:

enter image description here

但是,第二次,剪辑边界始终返回到原点边界,从而仅绘制了前几行。

问题

当文本区域本身处于正确位置时,为什么通过paintComponent方法的最终时间以不正确的剪辑范围调用?

在上述代码中添加了一堆新行并在UI上滚动后:

java.awt.Rectangle[x=0,y=497,width=50,height=16]
java.awt.Rectangle[x=0,y=0,width=50,height=16]
java.awt.Rectangle[x=0,y=481,width=50,height=16]
java.awt.Rectangle[x=0,y=0,width=50,height=16]
java.awt.Rectangle[x=0,y=465,width=50,height=16]
java.awt.Rectangle[x=0,y=0,width=50,height=16]
java.awt.Rectangle[x=0,y=446,width=50,height=16]
java.awt.Rectangle[x=0,y=0,width=50,height=16]

请注意,更新从有效跳到原点,然后又返回原点,而秒更新总是使我重回原点。

为什么要两次更新?

0 个答案:

没有答案