【问题标题】:.getSize() is updated in a JScrollPane but not in a JPanel.getSize() 在 JScrollPane 中更新,但不在 JPanel 中更新
【发布时间】:2023-03-04 10:53:01
【问题描述】:

最初的问题是为什么 .getSize() 在组件调整大小后不返回 JCompnent 的实际大小:.getSize() isn't updated

相反,我在 JScrollPane 中添加了一个 JPanel,并使用 scrollRectToVisible() 来更新 getSize()。考虑这个小例子:

import java.awt.*;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.*;


public class Test extends JFrame implements MouseWheelListener{
    JPanel p,p2;
    JScrollPane js;

    Test(){
        setLayout(new FlowLayout());
        setPreferredSize(new Dimension(1000,1000));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

        p = new JPanel();
        p.setPreferredSize(new Dimension(200,200));

        p2=new JPanel();
        p2.setPreferredSize(new Dimension(20,20));
        p2.setBackground(Color.green);

        p.add(p2);
        js = new JScrollPane(p);

        add(js);

        addMouseWheelListener(this);
        pack();
    }
    public static void main(String args[]){
        new Test();
    }
    public void mouseWheelMoved(MouseWheelEvent e) {

        System.out.println(p2.getSize());

        p2.setPreferredSize(new Dimension(100,100));
        p2.revalidate();

        p2.scrollRectToVisible(new Rectangle(1,1,1,1));

        System.out.println(p2.getSize());
    }
}

滚动鼠标滚轮后,单击一下绿色方块的大小。该程序还会打印出正确的尺寸。但是,如果我删除了 scrollRectToVisible(1,1,1,1) 正方形被调整大小,但 它打印出错误的大小。问题是:

  1. 除了调用 scrollRectToVisible 来更新 getSize() 之外,还有其他方法吗?
  2. 如果在 jscollpane 中没有添加正方形怎么办,如.getSize() isn't updated 中的示例,是否有相应的更新函数?

【问题讨论】:

    标签: java swing jframe jpanel jscrollpane


    【解决方案1】:

    其实没有问题。问题是您调用支持 deferred 布局的revalidate()。见javadoc

    支持延迟自动布局。

    调用 invalidate 然后将此组件的 validateRoot 添加到列表中 需要验证的组件。验证将在之后发生 所有当前待处理的事件都已调度。 ...

    特别是在所有当前挂起的事件都被调度后才会发生验证

    这意味着 p2 的布局(以及它的大小更改)将在所有未决事件(包括当前的鼠标滚轮事件)被调度后执行。

    当您调用 scrollToVisibleRect 时,如果它无效,它会自动执行组件的布局,这就是调用 scrollToVisibleRect 会立即调整大小的原因。

    如果你真的需要立即调整大小,你可以在p2 的父容器上使用doLayout(),但我不推荐它,因为它可能更昂贵。 revalidate() 提供了像 repaint() 那样合并事件的可能性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 2016-07-05
      • 1970-01-01
      • 1970-01-01
      • 2014-12-06
      • 1970-01-01
      相关资源
      最近更新 更多