Je souhaite créer une application de vidage à l'aide de JavaFX. J'ai utilisé Pane
pour montrer des formes en mouvement (circle, Rectange
) dessus. Le problème se produit lorsque je redimensionne la fenêtre à une plus grande zone. Lorsque je fais cela, la zone nouvellement créée ne montre pas correctement les formes en mouvement. Ce qui se passe dans cette nouvelle zone: les formes changent de couleur du noir au blanc et elles laissent une trace blanche.Le volet JavaFX ne dessine pas de formes sur une zone redimensionnée
Les formes sont déplacées à l'aide des méthodes setTranslateX
(et Y). J'ai également inclus un exemple de code sous les captures d'écran. Le code n'est pas le même que celui sur les écrans enregistrés, mais il produit le même problème.
fenêtre avec la taille originale
fenêtre redimensionnée avec une zone où les formes ne sont pas dessinés correctement
Le document FXML nommé view.fxml
<?import javafx.scene.shape.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.company.bouncer.Controller">
<center>
<Pane fx:id="paneField" prefHeight="344.0" prefWidth="600.0" BorderPane.alignment="CENTER" />
</center>
<top>
<HBox alignment="CENTER_LEFT" prefHeight="56.0" prefWidth="600.0" spacing="30.0" BorderPane.alignment="CENTER">
<children>
<Button fx:id="btnLaunch" mnemonicParsing="false" onAction="#handleBtn" text="Launch" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
<BorderPane.margin>
<Insets />
</BorderPane.margin>
<padding>
<Insets left="30.0" />
</padding>
</HBox>
</top>
</BorderPane>
classe principale qui étend l'application
package com.company.bouncer;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("/view.fxml"));
primaryStage.setTitle("Bouncer");
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
/**
* called when the window is closed
*/
@Override
public void stop() throws Exception {
Controller.stopExecutor();
super.stop();
}
}
** Contrôleur **
package com.company.bouncer;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
public class Controller implements Initializable {
@FXML
private Button btnLaunch;
@FXML
private Pane paneField;
private ShapePlatform shapeRunnable;
private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
@Override
public void initialize(URL location, ResourceBundle resources) {
shapeRunnable = new ShapePlatform();
paneField.setBackground(new Background(new BackgroundFill(Color.web("#aaaaaa"), CornerRadii.EMPTY, Insets.EMPTY)));
executor.scheduleAtFixedRate(shapeRunnable, 0, 10, TimeUnit.MILLISECONDS);
}
@FXML
private void handleBtn(){
shapeRunnable.generateShapeMover();
}
public static void stopExecutor(){
executor.shutdown();
}
public class ShapePlatform implements Runnable {
private List<ShapeMover> shapeList = new ArrayList<>();
/**
* Constructor
* @param parentPane Pane on which the shapes will be displayed
*/
public ShapePlatform(){
}
/**
* creates a new shape and adds it to the shapeList
*/
public void generateShapeMover(){
Shape newShape = new Rectangle(0, 0, 100, 80);
paneField.getChildren().add(newShape);
//position the object in some random location on the pane
newShape.setTranslateX(300);
newShape.setTranslateY(300);
//wrap it in shape mover
ShapeMover shapeMover = new ShapeMover(newShape);
shapeList.add(shapeMover);
}
/**
* executes one frame of moving objects
*/
private void moveAllOnce(){
shapeList.forEach(sm -> sm.move());
}
/**
* moves all objects, checks any intersections between objects
* and changes their direction if there is an intersection
*/
@Override
public void run() {
moveAllOnce();
}
public class ShapeMover {
private Shape shape;
private int xDir = 1;
private int yDir = 1;
private int periodSpeed = 1;
private int periodSpeedCountDown = periodSpeed;
/**
* constructs the object
* @param shape - shape to be moved
*/
public ShapeMover(Shape shape){
this.shape = shape;
}
/**
* moves object for one iteration
*/
public void move(){
if(periodSpeedCountDown == 0){
shape.setTranslateX(shape.getTranslateX() + xDir);
shape.setTranslateY(shape.getTranslateY() + yDir);
periodSpeedCountDown = periodSpeed;
} else {
periodSpeedCountDown--;
}
}
}
}
}
S'il vous plaît [modifier] votre question d'inclure un [MCVE]. –
J'ai ajouté du code au fil de discussion. Si vous créez un projet javaFX et avec Main.java et Controller.java + view.fxml, alors cela devrait fonctionner. Le paquet est nommé com.company.bouncer Le code n'est pas le même que celui des animations, mais il donne le même problème –
Vous essayez de mettre à jour l'interface utilisateur à partir d'un thread d'arrière-plan. Les résultats ne sont pas définis lorsque vous faites cela. Pourquoi ne pas utiliser un ['Animation'] (https://docs.oracle.com/javase/9/docs/api/javafx/animation/package-summary.html) pour votre animation, au lieu d'un fil de discussion? –