简体   繁体   English

重绘BorderPane(javaFx)

[英]Repaint BorderPane (javaFx)

I have an application that can create a rectangle that decreases in size for example a lapse of time of 10 sec, but here is when I try to shrink the rectangle, the window bug (nothing is displayed in the scene) and wait until the countdown is finished to stop bugging (and then display the rectangle not diminished). 我有一个可以创建尺寸减小的矩形的应用程序,例如经过10秒的时间,但是这里是当我尝试缩小矩形时,出现窗口错误(场景中未显示任何内容)并等待倒计时完成以停止错误检查(然后显示未缩小的矩形)。 I tried to find on the Internet the equivalent of repaint in Swing but not average: / this.requestLayout () -> I found this on the internet but it does not work. 我试图在Internet上找到与Swing中的重绘等效的功能,但不是平均水平:/ this.requestLayout()->我在Internet上找到了此功能,但是它不起作用。 Here is my code of my countdown: 这是我的倒计时代码:

public class Compteur {

    DemoBorderPane p ;

    public DemoBorderPane getPan() {
        if(p==null) {
            p = new DemoBorderPane();
        }
        return p;
    }

    public Compteur() {

    }

    public void lancerCompteur() throws InterruptedException {


       int leTempsEnMillisecondes=1000;

        for (int i=5;i>=0;i--) {
            try {
                Thread.sleep (leTempsEnMillisecondes);
            } 
            catch (InterruptedException e) {
                System.out.print("erreur");
            }
            System.out.println(i);
            getPan().diminuerRect(35);
        }
    }
}

There is my Borderpane code : 有我的Borderpane代码:

public class DemoBorderPane extends BorderPane {

    private Rectangle r;

    public Rectangle getRect() {
        if(r==null) {
            r = new Rectangle();
             r.setWidth(350);
                r.setHeight(100);
                r.setArcWidth(30);
                r.setArcHeight(30);
                r.setFill( //on remplie notre rectangle avec un dégradé
                        new LinearGradient(0f, 0f, 0f, 1f, true, CycleMethod.NO_CYCLE,
                            new Stop[] {
                                new Stop(0, Color.web("#333333")),
                                new Stop(1, Color.web("#000000"))
                            }
                        )
                    );
        }

        return r;
    }

    public void diminuerRect(int a) {
        getRect().setWidth(getRect().getWidth()-a);
        int c= (int) (getRect().getWidth()-a);
        System.out.println(c);
        this.requestLayout();
        //this.requestFocus();
    }


    public DemoBorderPane() {
        this.setBottom(getRect());

    }
}

There is my Main code : 有我的主要代码:

public class Main extends Application {
    private DemoBorderPane p;

    public DemoBorderPane getPan() {
        if(p==null) {
            p = new DemoBorderPane();
        }
        return p;
    }

    @Override
    public void start(Stage primaryStage) {
        Compteur c = new Compteur();
        try {

            //Group root = new Group();
            Scene scene = new Scene(getPan(),800,600);
            //scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            //root.getChildren().add(getPan());
            primaryStage.setScene(scene);
            primaryStage.show();



        } catch(Exception e) {
            e.printStackTrace();
        }

        try {
            c.lancerCompteur();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        launch(args);


        /*Son s = null;
        try {
            s = new Son();
        } catch (LineUnavailableException | IOException | UnsupportedAudioFileException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        s.volume(0.1);
        s.jouer();
        c.lancerCompteur();
        s.arreter();*/

    }
}

Thank ;) 谢谢 ;)

As long as you keep the JavaFX application thread busy it cannot perform layout/rendering. 只要您使JavaFX应用程序线程处于繁忙状态,它就无法执行布局/渲染。 For this reason it's important to make sure any methods that run on the application thread, like eg Application.start or event handlers on input events return fast. 因此,确保在应用程序线程上运行的任何方法(例如Application.start或输入事件的事件处理程序)快速返回非常重要。

lancerCompteur however blocks the application thread for 5 seconds so the only result you see is the final one after the method completes. 但是, lancerCompteur阻塞应用程序线程5秒钟,因此您看到的唯一结果是方法完成后的最后一个结果。

In general you can run code like this on a different thread and use Platform.runLater to update the ui. 通常,您可以在其他线程上运行这样的代码,并使用Platform.runLater更新ui。

In this case you could take advantage of the Timeline class which allows you to trigger an event handler on the application thread after a given delay: 在这种情况下,您可以利用Timeline类,该类允许您在给定的延迟后触发应用程序线程上的事件处理程序:

@Override
public void start(Stage primaryStage) {
    Scene scene = new Scene(getPan(), 800, 600);

    Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), event -> {
        getPan().diminuerRect(35);
    }));
    timeline.setCycleCount(5);
    timeline.play();

    primaryStage.setScene(scene);
    primaryStage.show();
}

  • You also use different instances of DemoBorderPane in your Main class and the Compteur class; 您还可以在Main类和Compteur类中使用DemoBorderPane不同实例; the Rectangle shown in the scene was never subject to an update. 场景中显示的Rectangle永远不会进行更新。
  • there's no need to call requestLayout in diminuerRect . 无需在diminuerRect调用requestLayout This happens automatically when the Rectangle 's size is modified. 修改Rectangle的大小时,这会自动发生。
  • Lazy initialisation is pointless, if you know for sure the getter will be invoked during the object's creation. 如果您确定在对象创建期间将调用getter,则延迟初始化是没有意义的。 DemoBorderPane.getRect is invoked from it's constructor so moving the initialisation to the constructor would allow you to get rid of the if check without affecting functionality. DemoBorderPane.getRect是从其构造函数调用的,因此将初始化移至构造函数将使您摆脱if检查,而不会影响功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM