Java ScrollPane未刷新其内容 简历

Java ScrollPane未刷新其内容 简历,java,javafx,mouse,viewport,scrollpane,Java,Javafx,Mouse,Viewport,Scrollpane,大家好 一段时间以来,我一直在尝试开发一个程序,使用户能够在某个区域中放置对象,并允许鼠标移动该区域。对于这种类型的程序,我决定使用滚动窗格,因为用户可以在我称之为画布的区域中添加各种内容。由于某种原因,我的程序中发生了一些奇怪的事情 程序说明 我基本上是创建一组对象,并将该组定义为滚动窗格内容。在组中,添加了一个矩形对象作为画布边界。该对象具有更大的尺寸(例如1500 x 1000),并用于防止节点移动超出其限制的计算中。这只是我的程序中现有大矩形背后的逻辑,但实际上,没有鼠标移动的节点对象。

大家好

一段时间以来,我一直在尝试开发一个程序,使用户能够在某个区域中放置对象,并允许鼠标移动该区域。对于这种类型的程序,我决定使用滚动窗格,因为用户可以在我称之为画布的区域中添加各种内容。由于某种原因,我的程序中发生了一些奇怪的事情

程序说明 我基本上是创建一组对象,并将该组定义为滚动窗格内容。在组中,添加了一个矩形对象作为画布边界。该对象具有更大的尺寸(例如1500 x 1000),并用于防止节点移动超出其限制的计算中。这只是我的程序中现有大矩形背后的逻辑,但实际上,没有鼠标移动的节点对象。存在的是形状对象按矩形区域的随机分布

对于ScrollPane的滚动条被移动,我使用了这些方法。不幸的是,出于我的目的,此方法不会使用像素值更改滚动窗格视口的位置​​, 但是价值观​​在0f和1f之间的范围内。所以我可以用鼠标移动视口,我使用了一个称为“规则3”(Rule of 3,我知道在我的国家是这样)的等式,我们将其值相等​​和交叉乘法

例如,假设我想用鼠标水平移动滚动窗格的视口,并且我的画布区域的宽度为2000像素。要知道鼠标从一个点拖到另一个点的距离(以像素为单位),我需要知道这个值在0f到1f的范围内是如何表示的。假设我将鼠标拖入3个像素,我可以通过以下比较找到0f到1f的表示:

2000 px ---- 1f
   3 px ---- xf
乘以crossed,我将得到以下结果:

xf = 3 / 2000
xf = 0.0015
注意:我相信你们都知道这一点。我没有教任何人数学, 我只是想解释一下我问题的逻辑

源代码 这是我的课程:

import testes.util.TestesUtil;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;

public class ScrollTest4 extends Application
{
// #########################################################################################################
//                                                                                                      MAIN
// #########################################################################################################

public static void main(String[] args) 
{
    Application.launch(args);
}

// #########################################################################################################
//                                                                                                INSTÂNCIAS
// #########################################################################################################

// OUTSIDE

private BorderPane root;
private Button but_moreH;
private Button but_lessH;
private Button but_moreV;
private Button but_lessV;

// LOG

private VBox vbox_south;
private Label lab_hValue;
private Label lab_vValue;
private Label lab_viewport;

// INSIDE

private Rectangle rec_canvas;
private ScrollPane scroll;
private Group grp_objects;

// MOUSE

private double mouse_x = 0;
private double mouse_y = 0;

// MISC

private AnimationTimer timer;

// EDITED - 08/02/2014
private boolean moreH = false;
private boolean moreV = false;  // Purposely unused.
private boolean lessH = false;
private boolean lessV = false;  // Purposely unused.

// #########################################################################################################
//                                                                                                 INÍCIO FX
// #########################################################################################################

@Override public void start(Stage estagio) throws Exception 
{
    this.iniFX();
    this.confFX();
    this.adFX();
    this.evFX();

    Scene cenario = new Scene(this.root , 640 , 480);

    estagio.setScene(cenario);
    estagio.setTitle("Programa JavaFX");
    estagio.show();
}

protected void iniFX()
{
    // OUTSIDE

    this.root = new BorderPane();
    this.but_moreH = new Button();
    this.but_lessH = new Button();
    this.but_moreV = new Button();
    this.but_lessV = new Button();

    // LOG

    this.vbox_south = new VBox();
    this.lab_hValue = new Label();
    this.lab_vValue = new Label();
    this.lab_viewport = new Label();

    // INSIDE

    this.scroll = new ScrollPane();
    this.grp_objects = new Group();
    this.rec_canvas = new Rectangle();

    // MISC

    this.timer = new AnimationTimer()
    {
        @Override public void handle(long now) 
        {
            // EDITED - 08/02/2014
            if(but_moreH.isArmed() || moreH)
            {
                // scroll.hvalueProperty().set(scroll.hvalueProperty().get() + 0.003f);
                scroll.setHvalue(scroll.getHvalue() + 0.003f);
            }
            // EDITED - 08/02/2014
            if(but_lessH.isArmed() || lessH)
            {
                // scroll.hvalueProperty().set(scroll.hvalueProperty().get() - 0.003f);
                scroll.setHvalue(scroll.getHvalue() - 0.003f);
            }
            if(but_moreV.isArmed())
            {
                scroll.setVvalue(scroll.getVvalue() + 0.003f);
            }
            if(but_lessV.isArmed())
            {
                scroll.setVvalue(scroll.getVvalue() - 0.003f);
            }
        }
    };
    this.timer.start();
}

protected void confFX() 
{
    // OUTSIDE

    this.but_moreH.setText("More H");
    this.but_moreH.setMaxHeight(Double.MAX_VALUE);

    this.but_lessH.setText("Less H");
    this.but_lessH.setMaxHeight(Double.MAX_VALUE);

    this.but_moreV.setText("More V");
    this.but_moreV.setMaxWidth(Double.MAX_VALUE);

    this.but_lessV.setText("Less V");
    this.but_lessV.setMaxWidth(Double.MAX_VALUE);

    // LOG

    this.updateHvalue();
    this.updateVvalue();
    this.updateViewport();

    // INSIDE

    this.rec_canvas.setWidth(1200);
    this.rec_canvas.setHeight(1000);
    this.rec_canvas.setFill(Color.INDIANRED);
    this.rec_canvas.setStroke(Color.RED);
    this.rec_canvas.setStrokeType(StrokeType.INSIDE);
    this.rec_canvas.setStrokeWidth(1);
}

protected void adFX() 
{
    // LOG

    this.vbox_south.getChildren().add(this.but_moreV);
    this.vbox_south.getChildren().addAll(this.lab_hValue , this.lab_vValue , this.lab_viewport);

    // OUTSIDE

    this.root.setCenter(this.scroll);
    this.root.setTop(this.but_lessV);
    this.root.setBottom(this.vbox_south);
    this.root.setRight(this.but_moreH);
    this.root.setLeft(this.but_lessH);

    // INSIDE

    this.grp_objects.getChildren().add(this.rec_canvas);
    this.scroll.setContent(this.grp_objects);

    // MISC

    StrokeType[] strokes = {StrokeType.CENTERED , StrokeType.INSIDE , StrokeType.OUTSIDE};

    for(int cont = 0 ; cont < 20 ; cont++)
    {
        Rectangle node = new Rectangle(Math.random() * 100 + 50 , Math.random() * 100 + 50);
        node.setFill(TestesUtil.getCorAleatoria(false));
        node.setStroke(TestesUtil.getCorAleatoria(false));
        node.setStrokeType(strokes[(int) (Math.random() * 2)]);
        node.setStrokeWidth(Math.random() * 9 + 1);
        node.setRotate(Math.random() * 360);
        node.setMouseTransparent(true);

        // EDITED - 08/02/2014
        TestsUtil.putRandomlyIn(
                node , 
                rec_canvas.getBoundsInParent().getMinY() ,
                rec_canvas.getBoundsInParent().getMinY() + rec_canvas.getBoundsInParent().getHeight() , 
                rec_canvas.getBoundsInParent().getMinX() + rec_canvas.getBoundsInParent().getWidth() , 
                rec_canvas.getBoundsInParent().getMinX() );

        this.grp_objects.getChildren().add(node);
    }
}

protected void evFX() 
{
    // ##########################
    //     SCROLL PROPERTIES
    // ##########################

    this.scroll.hvalueProperty().addListener(new ChangeListener<Number>()
    {
        @Override public void changed(ObservableValue<? extends Number> observable,Number oldValue, Number newValue) 
        {
            updateHvalue();
            updateViewport();
        }
    });

    this.scroll.vvalueProperty().addListener(new ChangeListener<Number>()
    {
        @Override public void changed(ObservableValue<? extends Number> observable,Number oldValue, Number newValue) 
        {
            updateVvalue();
            updateViewport();
        }
    });

    this.scroll.setOnKeyPressed(new EventHandler<KeyEvent>()
    {
        @Override public void handle(KeyEvent e) 
        {
            if(e.getCode() == KeyCode.RIGHT)
            {
                moreH = true;
            }
            else if(e.getCode() == KeyCode.LEFT)
            {
                lessH = true;
            }
        }
    });

    this.scroll.setOnKeyReleased(new EventHandler<KeyEvent>()
    {
        @Override public void handle(KeyEvent e) 
        {
            if(e.getCode() == KeyCode.RIGHT)
            {
                moreH = false;
            }
            else if(e.getCode() == KeyCode.LEFT)
            {
                lessH = false;
            }
        }
    });

    // ##########################
    //          CANVAS
    // ##########################

    this.rec_canvas.setOnMousePressed(new EventHandler<MouseEvent>() 
    {
        @Override public void handle(MouseEvent e) 
        {
            // The XY distance from the upper left corner of the canvas.
            mouse_x = e.getX();
            mouse_y = e.getY();
        }
    });

    this.rec_canvas.setOnMouseDragged(new EventHandler<MouseEvent>() 
    {
        @Override public void handle(MouseEvent e) 
        {
            // ##########################
            //           PIXELS 
            // ##########################

            // The distance between mouse movements (drag events).
            double xPixelsMoved = e.getX() - mouse_x;
            // double yPixelsMoved = e.getY() - mouse_y;

            // ##########################
            //           TO 1F
            // ##########################

            double h_of_1f = xPixelsMoved / rec_canvas.getBoundsInParent().getWidth();
            double h_of_1f_inverted = h_of_1f * -1;

            double currentH = scroll.getHvalue();
            scroll.setHvalue(currentH + h_of_1f);

            // scroll.hvalueProperty().set(scroll.getHvalue() + h_de_x);
            // scroll.vvalueProperty().set(scroll.getVvalue() + v_de_y);

            // ##########################
            //           DEBUG
            // ##########################

            System.out.printf("xPixelsMoved: %f , h_of_1f: %f , h_of_1f_inverted: %f %n", 
                    xPixelsMoved , h_of_1f , h_of_1f_inverted);

            // ##########################
            //        UPDATE FROM 
            //       EVENT TO EVENT
            // ##########################

            // Writes last mouse position to update on new motion event.
            mouse_x = e.getX();
            mouse_y = e.getY();
        }
    });
}

// #########################################################################################################
//                                                                                                     MISC.
// #########################################################################################################

protected void updateViewport()
{
    Bounds vport = this.scroll.getViewportBounds();
    this.lab_viewport.setText(String.format("Viewport - [X: %f , Y: %f , W: %f , H: %f]", 
            vport.getMinX() , vport.getMinY() , vport.getWidth() , vport.getHeight() ));
}

protected void updateHvalue()
{
    this.lab_hValue.setText("H value: " + this.scroll.getHvalue() );
}

protected void updateVvalue()
{
    this.lab_vValue.setText("V value: " + this.scroll.getVvalue() );
}
这里没有什么神秘之处。此方法仅从间隔计算值,并定义节点参数的LayoutXY属性。方法“fix…”只需将boundsInParent边界与参数中的点进行比较,然后调整node对象的layoutXYproperties。即使移除对象的随机分布,问题仍然会发生。所以我确信这个问题不是由这个引起的

原始帖子的源代码被更改,添加了使用箭头键移动滚动条的功能。即使它已经是ScrollPane的一个现有功能,添加它也可能会重现鼠标看到的错误(现在是箭头)。有些东西也被翻译成英语,以便社区更好地理解

求你了,我请求帮助。我感到头晕,不知道该怎么办。这种情况可能是因为JavaFX中的一些bug而发生的?啊。。。请有人帮帮我。:'(

无论如何,谢谢你的关注

编辑(2014年2月9日格林尼治标准时间上午10:50-3:00) 忘了提一下……我的程序最初是用JDK 8 b123编写和测试的。目前我安装了JDK 8 b128版本,但仍然遇到同样的问题。我的操作系统是Windows 7 64x

我几乎可以肯定这是一个错误。你们得到了和我一样的结果吗?或者我是唯一发现这种问题的人吗?如果这是一个错误,应该采取什么程序

谢谢你的关注

编辑(2014年2月10日格林尼治标准时间上午09:45-3:00)
悬赏开始了。

更新

JavaFX8U20现在已经修复了这个bug

错误描述

这是一个bug,可以通过使用JavaFx JRE 8执行以下代码来轻松验证:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

final ScrollPane sp = new ScrollPane();
final Image[] images = new Image[5];
final ImageView[] pics = new ImageView[5];
final VBox vb = new VBox();
final Label fileName = new Label();
final String [] imageNames = new String [] {"fw1.jpg", "fw2.jpg",
        "fw3.jpg", "fw4.jpg", "fw5.jpg"};

@Override
public void start(Stage stage) {
    VBox box = new VBox();
    Scene scene = new Scene(box, 180, 180);
    stage.setScene(scene);
    stage.setTitle("Scroll Pane");
    box.getChildren().addAll(sp, fileName);
    VBox.setVgrow(sp, Priority.ALWAYS);

    fileName.setLayoutX(30);
    fileName.setLayoutY(160);

    for (int i = 0; i < 5; i++) {
        images[i] = new Image(getClass().getResourceAsStream(imageNames[i]));
        pics[i] = new ImageView(images[i]);
        pics[i].setFitWidth(100);
        pics[i].setPreserveRatio(true);
        vb.getChildren().add(pics[i]);
    }

    sp.setVmax(440);
    sp.setPrefSize(115, 150);
    sp.setContent(vb);
    sp.vvalueProperty().addListener(new ChangeListener<Number>() {
        public void changed(ObservableValue<? extends Number> ov,
            Number old_val, Number new_val) {
                fileName.setText(imageNames[(new_val.intValue() - 1)/100]);
        }
    });

    stage.show();
}

public static void main(String[] args) {
    launch(args);
}
}
对听众:

    sp.vvalueProperty().addListener(new ChangeListener<Number>() {
        public void changed(ObservableValue<? extends Number> ov,
            Number old_val, Number new_val) {
                fileName.setText(imageNames[(new_val.intValue() - 1)/100]);
                sp.snapshot(new SnapshotParameters(), new WritableImage(1, 1));
        }
    });
sp.vvalueProperty().addListener(新的ChangeListener()){

public void已更改(observeValueTesteSUtil类文件在您的project@Reegan我编辑了我的原始帖子。请检查。谢谢您的关注。:')我尝试了你的代码,并证实了Windows 7的这种奇怪行为:当使用JRE 8 b128 32位运行你的示例时,光标滚动会被禁用,如果你确实在屏幕上随机快速移动光标一段时间。调整帧大小后,它会突然再次工作。另一方面,使用JDK 1.7.051,你的示例工作正常。因此这当然是一个应该向JavaFX开发人员报告的错误。我只能建议在修复此错误之前使用JDK 7。祝你好运-顺便说一句:非常好的问题描述,付出了很多努力!@Balder谢谢你,Balder。我想这是我们程序员必须分享的东西,这样我们才能开发出更好的功能性应用程序ons。我已经有一个多星期的时间遇到这个问题了。我考虑了几个备选方案,所有这些都会导致一些工作做得不好和不可维护的问题。不幸的是,我需要使用JDK 8,因为我可以使用新的CSS API。我完全不知道如何通知JavaFX开发人员这个错误。实际上,我不知道这是否是一个错误。我相信它可以,但我不能说。如果这个问题实际上被认为是一个bug,我会认为是正确的答案,这表明这是一个错误,JavaFX开发者被通知。我真的希望这个问题在未来得到解决,因为我真的需要使用这个特性(我们所有人)。。JDK 8计划于2014年年中完成并交付。在此之前,我希望这一问题得到解决。但我再次说……我仍然不知道这是否是一个bug。有必要通知JavaFX开发人员。我还在Oracle社区创建了一个。到目前为止,什么都没有。我在JIRA系统中创建了一个新问题。我不知道我是否纠正了因为我真的不知道如何使用JIRA。我想问题还没有解决。你能告诉我我做得对吗?你可以
sp.snapshot(new SnapshotParameters(), new WritableImage(1, 1));
    sp.vvalueProperty().addListener(new ChangeListener<Number>() {
        public void changed(ObservableValue<? extends Number> ov,
            Number old_val, Number new_val) {
                fileName.setText(imageNames[(new_val.intValue() - 1)/100]);
                sp.snapshot(new SnapshotParameters(), new WritableImage(1, 1));
        }
    });