我无法使用javaFX中的键盘移动圆形形状

问题描述 投票:0回答:1

我正在开发一个挑战,每次用户按下按钮时,我都必须在屏幕上添加一个新圆圈。除了允许用户选择要添加的圆圈的大小和颜色之外。我成功开发了这个功能!

下一步是选择一个圆圈,将其从其他圆圈中突出显示,并允许您使用箭头键在界面中移动它。我设法开发的第一部分是,每次用户用鼠标选择一个圆圈时,它上面就会出现一个边框,突出显示它。但是,我无法开发移动功能。每当我单击箭头键时,圆圈不会移动,而是按钮之间的焦点发生变化。

你能帮我一下吗?

这是我的 FXMLDocumentController.java:

package addcircleapp;

import java.net.URL;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Slider;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.ResourceBundle;

public class FXMLDocumentController implements Initializable {
    
    @FXML
    private Pane containerPane;
    
    @FXML
    private Button addCircleButton;
    
    @FXML
    private ColorPicker colorPicker;
    
    @FXML
    private Slider sizeSlider;
    
    private List<Circle> circles = new ArrayList<>();
    private Circle selectedCircle = null;
    
    @FXML
    private void handleAddCircleButton(ActionEvent event) {
        
        Random rand = new Random();
        int x = rand.nextInt(500);
        int y = rand.nextInt(200);
        
        Color selectedColor = colorPicker.getValue();
        double selectedSize = sizeSlider.getValue();
        
        Circle circle = new Circle(x, y, selectedSize, selectedColor);
        
        circle.setOnMouseClicked((MouseEvent e) -> {
            handleCircleClick(circle);
        });
        
        circle.setOnKeyPressed((KeyEvent e) -> {
            handleCircleMovement(e, circle);
        });
        
        circles.add(circle);
        containerPane.getChildren().add(circle);
        
        System.out.println("New circle was created!");
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    

    private void handleCircleClick(Circle clickedCircle) {
        /*circles.forEach((circle) -> {
        circle.setStroke(Color.TRANSPARENT);
        });*/
        
        if(selectedCircle != null){
            selectedCircle.setStroke(Color.TRANSPARENT);
        }
        
        selectedCircle = clickedCircle;
        selectedCircle.setStroke(Color.BLACK);
        selectedCircle.setStrokeWidth(2.0);
    }
    
    private void handleCircleMovement(KeyEvent event, Circle circle){
        if(event.getCode() == KeyCode.LEFT){
            circle.setCenterX(circle.getCenterX() - 10);
        } else if(event.getCode() == KeyCode.RIGHT){
            circle.setCenterX(circle.getCenterX() + 10);
        } else if(event.getCode() == KeyCode.UP){
            circle.setCenterY(circle.getCenterY() - 10);
        } else if(event.getCode() == KeyCode.DOWN){
            circle.setCenterY(circle.getCenterY() + 10);
        }
    
    }    
        
        
}

这是我的 FXMLDocument.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ColorPicker?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.layout.Pane?>


<Pane fx:id="containerPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="addcircleapp.FXMLDocumentController">
   <children>
      <Button fx:id="addCircleButton" layoutX="345.0" layoutY="362.0" mnemonicParsing="false" onAction="#handleAddCircleButton" text="AddCircle" />
      <ColorPicker fx:id="colorPicker" layoutX="14.0" layoutY="361.0" />
      <Slider fx:id="sizeSlider" blockIncrement="1.0" layoutX="180.0" layoutY="367.0" min="1.0" value="50.0" />
   </children>
</Pane>

这是我的 AddCircleApp.java:

package addcircleapp;

import java.util.ArrayList;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class AddCircleApp extends Application {
    
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
    
}

这是界面截图: Interface

这是问题的 gif: Problem

我想在界面周围移动选定的圆圈,而不是更改界面中存在的输入之间的焦点。我已经尝试使用 ChatGPT 找到解决方案,但没有成功。

java javafx netbeans java-8 scenebuilder
1个回答
0
投票

键盘事件仅传递到具有键盘焦点的节点。所以当圆圈被选中时,需要请求圆圈具有焦点:

private void handleCircleClick(Circle clickedCircle) {
    /*circles.forEach((circle) -> {
    circle.setStroke(Color.TRANSPARENT);
    });*/
    
    if(selectedCircle != null){
        selectedCircle.setStroke(Color.TRANSPARENT);
    }
    
    selectedCircle = clickedCircle;
    selectedCircle.setStroke(Color.BLACK);
    selectedCircle.setStrokeWidth(2.0);

    selectedCircle.requestFocus();
}

此外,场景中的默认键盘处理程序会将焦点移动到某些按键的其他节点。因此,您可能希望使用正在处理的按键的事件,以防止键盘焦点移动:

private void handleCircleMovement(KeyEvent event, Circle circle){
    if(event.getCode() == KeyCode.LEFT){
        circle.setCenterX(circle.getCenterX() - 10);
        event.consume();
    } else if(event.getCode() == KeyCode.RIGHT){
        circle.setCenterX(circle.getCenterX() + 10);
        event.consume();
    } else if(event.getCode() == KeyCode.UP){
        circle.setCenterY(circle.getCenterY() - 10);
        event.consume();
    } else if(event.getCode() == KeyCode.DOWN){
        circle.setCenterY(circle.getCenterY() + 10);
        event.consume();
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.