Java 预计算屏幕外部件尺寸?

Java 预计算屏幕外部件尺寸?,java,swing,boxlayout,Java,Swing,Boxlayout,我有一个JScrollPane,它有一个定制的可滚动视图来匹配它的宽度,只允许/需要垂直滚动。它填充了不同数量的jlabel,由于它们的长度,几乎总是换行。我使用BoxLayout来确保它们始终是全宽的,垂直排列的,并且基本上是有效的 一个主要的设计要求是精确地知道这些jlabel中的每一个在哪里,以便可以通过编程将滚动条移动到中心位置。如果你使用过NetBeans,你应该熟悉这个想法;在Chrome中查找,虽然它不会跳转到那里,但也会指示事物的位置 我遇到的问题是,在某一点上,布局只是放弃了。

我有一个JScrollPane,它有一个定制的可滚动视图来匹配它的宽度,只允许/需要垂直滚动。它填充了不同数量的jlabel,由于它们的长度,几乎总是换行。我使用BoxLayout来确保它们始终是全宽的,垂直排列的,并且基本上是有效的

一个主要的设计要求是精确地知道这些jlabel中的每一个在哪里,以便可以通过编程将滚动条移动到中心位置。如果你使用过NetBeans,你应该熟悉这个想法;在Chrome中查找,虽然它不会跳转到那里,但也会指示事物的位置

我遇到的问题是,在某一点上,布局只是放弃了。你可以通过滚动条在滚动过程中跳跃的方式来判断它实际上还没有计算出所有内容。因此,报告的
getY
值是无用的

我添加了以下调试代码

this.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
        public void adjustmentValueChanged(AdjustmentEvent evt) {
            //getVerseBlock grabs a component from the view, with sanity checks:
            System.out.println(ChapterTab.this.getVerseBlock(255).getY());
            System.out.println(ChapterTab.this.getVerseBlock(255).getHeight());
        }
    });
正如预期的(但不是期望的)随着面板的滚动,最后一个(或任何其他)元素的Y位置继续增加,因为越来越多的JLabel正确地计算了它们的大小。
getHeight()
检查确实显示,它们被设置在一行的高度,不知道它们需要换行,直到它们接近可见为止

一旦整个面板被滚动浏览,它就很高兴了。。。暂时。当这些jlabel返回到视图之外时,它不会取消计算。但它也不会在调整窗口大小时重新计算,导致值再次变得无用。(顺便说一句,破坏数学;渲染区域上方过高的组件也会报告不正确的高度,可能会增加到远大于其容器新高度的高度!)

因此,我非常简单地寻求一种方法,以确保此容器中的每个组件始终具有完全准确的当前尺寸和位置值。尽管这看起来只是事情应该做的事情——一个神经过敏的滚动条有多不专业我还没有找到实现这一目标的任何资源

编辑:不知道答案的人认为这只是因为他们看不到代码,这让我非常困扰。没关系!你不可能什么都知道;如果你以前没有遇到并解决过这个问题,那也不会让你成为一个程序员,我也不希望你回答。但是,我已设法将问题缩减为一个非常基本的文件:

package jscrolltest;


import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;

public class JScrollTest {

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {

        JFrame frame = new JFrame("JScrollTest");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BorderLayout());

        ScrollableView view = new ScrollableView();
        view.setLayout(new BoxLayout(view, BoxLayout.Y_AXIS));

        JScrollPane pnlScroll = new JScrollPane(view);
        pnlScroll.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        pnlScroll.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        view.add(new JLabel("<html>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis sapien sed tempor scelerisque."));
        view.add(new JLabel("<html>Donec ut leo nec ligula tempus eleifend. Proin in porttitor velit."));
        view.add(new JLabel("<html>Sed a facilisis orci. Nunc a diam feugiat, suscipit nunc nec, porttitor velit."));
        view.add(new JLabel("<html>Maecenas sagittis, est et bibendum luctus, tortor orci hendrerit enim, vitae rhoncus augue libero sit amet est. Phasellus a neque et magna gravida euismod dignissim ac elit."));
        view.add(new JLabel("<html>Ut neque urna, ultrices fermentum quam et, tristique tempus nulla. Curabitur non feugiat leo."));
        view.add(new JLabel("<html>Aenean eu viverra ligula, eu tempor turpis. Suspendisse eu nunc ac urna blandit egestas quis id augue. "));
        view.add(new JLabel("<html>Suspendisse a pulvinar est. Maecenas id congue neque. Donec eleifend nisi quis nisl faucibus sollicitudin."));
        view.add(new JLabel("<html>Aliquam rutrum nulla neque, sit amet sollicitudin massa ultrices quis. Interdum et malesuada fames ac ante ipsum primis in faucibus."));
        view.add(new JLabel("<html>Praesent ut auctor nisl, eget convallis neque. Quisque et vestibulum massa."));
        view.add(new JLabel("<html>Quisque consectetur ex cursus risus interdum, tristique imperdiet ante viverra. Sed et nulla eget sem dapibus fringilla."));

        frame.getContentPane().add(pnlScroll, BorderLayout.CENTER);

        pnlScroll.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
            public void adjustmentValueChanged(AdjustmentEvent evt) {
                System.out.println(view.getComponent(9).getY());
                System.out.println(view.getComponent(9).getHeight());
            }
        });

        frame.setSize(200, 100);
        frame.setVisible(true);
    }

    public static class ScrollableView extends JPanel implements Scrollable {

        public Dimension getPreferredScrollableViewportSize() {
            return getPreferredSize();
        }

        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 10;
        }

        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
            return ((orientation == SwingConstants.VERTICAL) ? visibleRect.height : visibleRect.width) - 10;
        }

        public boolean getScrollableTracksViewportWidth() {
            return true;
        }

        public boolean getScrollableTracksViewportHeight() {
            return false;
        }
    }
}
package-jscrolltest;
导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.Rectangle;
导入java.awt.event.AdjustmentEvent;
导入java.awt.event.AdjustmentListener;
导入javax.swing.BoxLayout;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.Scrollable;
导入javax.swing.SwingConstants;
公共类JScrollTest{
公共静态void main(字符串[]args){
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
私有静态void createAndShowGUI(){
JFrame=新JFrame(“JScrollTest”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(新的BorderLayout());
ScrollableView=新的ScrollableView();
view.setLayout(新的BoxLayout(视图,BoxLayout.Y_轴));
JScrollPane pnlScroll=新的JScrollPane(视图);
pnlScroll.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HorizontalScrollBar\uNever);
pnlScroll.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL\u SCROLLBAR\u ALWAYS);
视图。添加(新的JLabel(“Lorem ipsum dolor sit amet,concetetur adipising elit.Nunc convallis sapien sed tempor scelerisque”);
视图。添加(新JLabel(“Donec ut leo nec ligula tempus eleifend.Proin in in porttitor velit”);
视图。添加(新JLabel(“Sed a facilisis orci.Nunc a diam feugiat,suscipit Nunc nec,porttitor velit”);
视图。添加(新JLabel(“sagittis Maecenas sagittis,est et bibendum luctus,tortor orci hendrerit enim,Vita rhoncus augue libero sit amet.Phasellus a neque and magna Gradida euismod Dignessim ac Elite.”);
视图。添加(新的JLabel(“Ut neque urna,ultrices fentum quam et,tristique tempus nulla.Curabitur non feugiat leo”);
视图。添加(新的JLabel(“Aenean eu viverra ligula,eu Temporal turpis.Suspendisse eu nunc ac urna blandit egestas quis id augue”);
视图。添加(新的JLabel(“Suspendisse a pulvinar est.Maecenas id congue neque.Donec eleifend nisi quis nis faucibus sollicitudin.”);
视图。添加(新的JLabel(“Aliquam rutrum nulla neque,sit amet sollicitudin massa ultrices quis.Interdum and malesuada faucibus”中的第一同侧前的著名人物”);
视图。添加(新JLabel(“Praesent ut auctor nisl,eget convallis neque.Quisque et vestibulum massa”);
视图。添加(新的JLabel(“内部曲线的连续性,对维韦拉的不安全性,以及对边缘的不安全性”);
frame.getContentPane().add(pnlScroll,BorderLayout.CENTER);
pnlScroll.getVerticalScrollBar().addAdjustmentListener(新的AdjustmentListener()){
公共无效调整值已更改(调整事件evt){
System.out.println(view.getComponent(9.getY());
System.out.println(view.getComponent(9.getHeight());
}
});
框架设置尺寸(200100);
frame.setVisible(true);
}
公共静态类ScrollableView扩展了JPanel实现可滚动{
公共维度getPreferredScrollableViewportSize(){
返回getPreferredSize();
}
公共int getScrollableUnitIncrement(矩形visibleRect、int方向、int方向){
返回10;
}
公共整数
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;

public class JScrollTest {

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {

        JFrame frame = new JFrame("JScrollTest");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BorderLayout());

        final ScrollableView view = new ScrollableView();
        view.setLayout(new BoxLayout(view, BoxLayout.Y_AXIS));

        JScrollPane pnlScroll = new JScrollPane(view);
        pnlScroll.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        pnlScroll.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        view.add(new JLabel("<html>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis sapien sed tempor scelerisque."));
        view.add(new JLabel("<html>Donec ut leo nec ligula tempus eleifend. Proin in porttitor velit."));
        view.add(new JLabel("<html>Sed a facilisis orci. Nunc a diam feugiat, suscipit nunc nec, porttitor velit."));
        view.add(new JLabel("<html>Maecenas sagittis, est et bibendum luctus, tortor orci hendrerit enim, vitae rhoncus augue libero sit amet est. Phasellus a neque et magna gravida euismod dignissim ac elit."));
        view.add(new JLabel("<html>Ut neque urna, ultrices fermentum quam et, tristique tempus nulla. Curabitur non feugiat leo."));
        view.add(new JLabel("<html>Aenean eu viverra ligula, eu tempor turpis. Suspendisse eu nunc ac urna blandit egestas quis id augue. "));
        view.add(new JLabel("<html>Suspendisse a pulvinar est. Maecenas id congue neque. Donec eleifend nisi quis nisl faucibus sollicitudin."));
        view.add(new JLabel("<html>Sed a facilisis orci. Nunc a diam feugiat, suscipit nunc nec, porttitor velit."));
        view.add(new JLabel("<html>Maecenas sagittis, est et bibendum luctus, tortor orci hendrerit enim, vitae rhoncus augue libero sit amet est. Phasellus a neque et magna gravida euismod dignissim ac elit."));
        view.add(new JLabel("<html>Ut neque urna, ultrices fermentum quam et, tristique tempus nulla. Curabitur non feugiat leo."));
        view.add(new JLabel("<html>Aenean eu viverra ligula, eu tempor turpis. Suspendisse eu nunc ac urna blandit egestas quis id augue. "));
        view.add(new JLabel("<html>Suspendisse a pulvinar est. Maecenas id congue neque. Donec eleifend nisi quis nisl faucibus sollicitudin."));
        view.add(new JLabel("<html>Aliquam rutrum nulla neque, sit amet sollicitudin massa ultrices quis. Interdum et malesuada fames ac ante ipsum primis in faucibus."));
        view.add(new JLabel("<html>Praesent ut auctor nisl, eget convallis neque. Quisque et vestibulum massa."));
        view.add(new JLabel("<html>123Quisque consectetur ex cursus risus interdum, tristique imperdiet ante viverra. Sed et nulla eget sem dapibus fringilla."));

        frame.getContentPane().add(pnlScroll, BorderLayout.CENTER);

        pnlScroll.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
            public void adjustmentValueChanged(AdjustmentEvent evt) {
                System.out.println(view.getComponent(14).getY());
                System.out.println(view.getComponent(14).getHeight());
            }
        });

        frame.setSize(300, 200);
        frame.setVisible(true);
    }

    public static class ScrollableView extends JPanel implements Scrollable, ComponentListener {

        public ScrollableView()
        {
            addComponentListener( this );
        }

        public Dimension getPreferredScrollableViewportSize() {
            return getPreferredSize();
        }

        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 10;
        }

        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
            return ((orientation == SwingConstants.VERTICAL) ? visibleRect.height : visibleRect.width) - 10;
        }

        public boolean getScrollableTracksViewportWidth() {
            return true;
        }

        public boolean getScrollableTracksViewportHeight() {
            return false;
        }

        //  Implement ComponentListener

        public void componentResized(ComponentEvent e)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    int width = getParent().getSize().width;

                    if (width == 0) return;

                    BufferedImage bi = new BufferedImage(width, 600, BufferedImage.TYPE_INT_RGB);
                    Graphics g = bi.getGraphics();

                    for (Component c: getComponents())
                    {
                        c.paint(g);
                    }

                    revalidate();
                    repaint();
                }
            });
        }

        public void componentHidden(ComponentEvent e) {}

        public void componentMoved(ComponentEvent e) {}

        public void componentShown(ComponentEvent e) {}

    }
}