JavaFX 2:在添加内容后使ScrollPane自动滚动到边缘 [英] JavaFX 2: Making a ScrollPane automatically scroll to the edge after adding content

查看:185
本文介绍了JavaFX 2:在添加内容后使ScrollPane自动滚动到边缘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用JavaFX 2,我有一个 ScrollPane 的基本示例,其中包含 HBox 标签秒。我希望能够将 Label 添加到 HBox ,同时滚动到<$的右边缘c $ c> ScrollPane 以便可以看到新添加的标签。我当前的方法使用 setHvalue()来设置滚动位置和 getHmax()以获得允许的最大滚动距离。

Using JavaFX 2, I have a basic example of a ScrollPane that contains an HBox of Labels. I want to be able to add a Label to the HBox, and simultaneously scroll to the right edge of the ScrollPane so that the newly added Label is visible. My current method uses the setHvalue() to set the scroll position and getHmax() to get the maximum scrolling distance allowed.

问题在于,当我使用 getHmax()设置滚动位置时,就好像刚才-added 标签未在 ScrollPanel 的滚动宽度中计算。有没有办法可以在尝试 setHvalue 之前更新这个内部宽度?

The problem is that when I set the scroll position using getHmax(), it is as if the just-added Label is not computed in the ScrollPanel's scroll width. Is there a way that I can update this inner width before trying setHvalue?

请看这个简单的示例代码显示问题。

Please see this simple example code which exhibits the issue.

请特别注意 addChatItem(String item)方法,其中包含逻辑滚动到 ScrollPane的边缘

In particular, please notice the addChatItem(String item) method, which contains the logic for scrolling to the edge of the ScrollPane.

    import java.util.Timer;
    import java.util.TimerTask;

    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    import javafx.scene.control.ScrollPane;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.HBox;
    import javafx.scene.layout.StackPane;
    import javafx.scene.text.Font;
    import javafx.stage.Stage;

    public class ScrollPaneTest extends Application {   
        static int defaultFontSize = 30;

        ScrollPaneTest scrollPaneTest = this;

        ScrollPane chatBoxScrollPane = new ScrollPane();
        HBox chatBox = new HBox();
        Chatter chatter = new Chatter();

        public static void main(String[] args) {
            launch(args);//default
        }

        @Override
        public void stop() throws Exception {
            super.stop();
            System.exit(0);
        }

        @Override
        public void start(Stage primaryStage) {
            BorderPane borderPane = new BorderPane();       

            StackPane chatBoxStackPane = new StackPane();

            chatBoxScrollPane.setContent(chatBox);
            //chatBoxScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
            chatBoxScrollPane.setMaxHeight(50);

            chatBoxStackPane.getChildren().add(chatBoxScrollPane);

            borderPane.setCenter(chatBoxStackPane);


            Scene scene = new Scene(borderPane, 800, 600);
            primaryStage.setScene(scene);
            primaryStage.setTitle("Scroll Demo");
            primaryStage.show(); 


            new Thread("mainGameControlThread") {
                public void run() {
                    chatter.chatLoop(scrollPaneTest);
                }
            }.start();
        }

        public void addChatItem(String chatString) {
            Label title = new Label(chatString);        
            title.setFont(new Font("Verdana", defaultFontSize));

            chatBox.getChildren().add(title);

            chatBoxScrollPane.setHvalue(chatBoxScrollPane.getHmax());
        }

        class Chatter {
            public void chatLoop(final ScrollPaneTest test) {

                Timer closingCeremonyTimer = new Timer();
                closingCeremonyTimer.schedule(new TimerTask() {
                    public void run() {
                        Platform.runLater(new Runnable() {
                            @Override 
                            public void run() {
                                test.addChatItem("Hello World. ");
                            }
                        });
                        chatLoop(test);
                    }
                }, (long) (0.5*1000));
            }
        }
    }

这是一张问题图片,注意 ScrollPane 如何没有滚动到右边缘。

Here is an image of issue, notice how the ScrollPane has not scrolled to the right edge.

编辑:

我想出了一个解决方法,但它距离很远理想。我的解决方案是启动一个计时器,在经过 ScrollPane 的足够时间后,将使用 setHvalue()来发现其内容的真实宽度。我的 addChatItem()方法现在看起来像这样:

I've come up with a workaround but it is very far from ideal. My solution is to start a timer which will use setHvalue() after enough time has passed for the ScrollPane to discover the true width of its content. my addChatItem() method now looks like this:

public void addChatItem(String chatString) {
    Label title = new Label(chatString);        
    title.setFont(new Font("Verdana", defaultFontSize));

    chatBox.getChildren().add(title);

    Timer closingCeremonyTimer = new Timer();       
    closingCeremonyTimer.schedule(new TimerTask() {
        public void run() {
            chatBoxScrollPane.setHvalue(chatBoxScrollPane.getHmax());
        }
    }, (long) 50);
}

不幸的是,该方法中的数字50需要大于时间需要 ScrollPane 才能更新其内部内容的宽度,这似乎远非保证。

Unfortunately, the number 50 in that method needs to be greater than the time that it takes the ScrollPane to update its inner content's width, and that seems to be far from guaranteed.

推荐答案

你可以绑定到Hbox widthproperty chnages。

you can bind to Hbox widthproperty chnages .

示例代码:

   //in start method add this code
    DoubleProperty wProperty = new SimpleDoubleProperty();
    wProperty.bind(chatBox.widthProperty()); // bind to Hbox width chnages
    wProperty.addListener(new ChangeListener() {
        @Override
        public void changed(ObservableValue ov, Object t, Object t1) {
           //when ever Hbox width chnages set ScrollPane Hvalue
         chatBoxScrollPane.setHvalue(chatBoxScrollPane.getHmax()); 
        }
    }) ;

 // remove below line from your addChatItem() method   
 chatBoxScrollPane.setHvalue(chatBoxScrollPane.getHmax());

结果:是添加编号以获得乐趣;)

Result :yes added numbering for fun ;)

这篇关于JavaFX 2:在添加内容后使ScrollPane自动滚动到边缘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆