0
我想使用JavaFX创建一个保镖应用程序。我用Pane
来显示移动的形状(circle, Rectange
)。当我将窗口调整到更大的区域时,会发生问题。当我这样做时,新创建的区域不会正确显示移动的形状。在这个新领域会发生什么:形状从黑色变成白色,并留下白色痕迹。JavaFX窗格不会在调整大小的区域上绘制形状
使用setTranslateX
(和Y)方法移动形状。
我还在屏幕截图下方提供了一个示例代码。该代码与录制屏幕上的代码不同,但它会产生相同的问题。
,面积大小的窗口,其中形状不正确绘制
命名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>
的FXML文件
扩展应用程序的主类
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();
}
}
** **控制器
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--;
}
}
}
}
}
请编辑您的问题以包含[MCVE]。 –
我将代码添加到线程中。如果你创建一个javaFX项目并且使用Main.java和Controller.java + view.fxml,那么它应该可以工作。该软件包名为com.company.bouncer 该代码与动画中的代码不同,但它提供了相同的问题 –
您试图从后台线程更新UI。当你这样做的时候结果是不确定的。为什么不为动画使用['Animation'](https://docs.oracle.com/javase/9/docs/api/javafx/animation/package-summary.html),而不是线程? –