JavaFX - ключевые события прерываются кнопками - PullRequest
0 голосов
/ 06 октября 2019

Я учусь в ООП / Java-классе второго уровня. У нас было задание создать простой интерфейс JavaFX, который позволяет пользователю рисовать на панели с помощью клавиш со стрелками. Это напоминает мне о Etch-a-Sketch. Эта программа работала нормально, но я хотел добавить кнопки внизу, чтобы очистить экран, чтобы пользователь мог начать все заново, не закрывая программу и кнопку выхода, хотя это немного избыточно с правым верхним X на панели. При тестировании нажатие клавиши со стрелкой вниз передается на панель HBox кнопок, вызывая кнопку и прерывая функцию рисования. После этого нажатие клавиши со стрелкой вверх не возвращает курсор на панель рисования. Кроме того, нажатие стрелок влево или вправо (после нажатия кнопок) перемещает фокус между кнопками. Я ищу способ ограничить ключевые события на панели рисования. Я вставил приведенный ниже код без импортированных библиотек, но есть 15 из них, включая LineTo, MoveTo, Button, Path ... Я могу вставить в случае необходимости.

**** отредактировал код вотразить изменения, предложенные Slaw, которые сработали. Теперь я знаю, что код кнопки btClear не очищает панель и не позволяет пользователю начать рисование с чистого листа. ****

public class LineToDrawPath extends Application {
private double bX = 100.0, bY = 100.0;
private double segment = 20.0;


@Override
public void start(Stage primaryStage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));

    Pane pane = new Pane();
    HBox hBox = new HBox();
    hBox.setPadding(new Insets(15,12,15,12));
    hBox.setSpacing(20);
    hBox.setAlignment(Pos.CENTER);
    Button btClear = new Button("Clear");
    btClear.setFocusTraversable(false); // effective solution
    Button btExit = new Button ("Exit");
    btExit.setFocusTraversable(false); // effective solution
    hBox.getChildren().addAll(btClear, btExit);
    // Creating a Path object
    Path path = new Path(new MoveTo(bX, bY));

    path.setStrokeWidth(1.7);
    path.setStroke(Color.CHOCOLATE);

    pane.getChildren().add(path);

    path.setOnKeyPressed(e ->{
        if (e.getCode().isArrowKey()){
            switch (e.getCode()){
                case DOWN: bY += segment; break;
                case UP: bY -= segment; break;
                case LEFT: bX -= segment; break;
                case RIGHT: bX += segment; break;
            }
            path.getElements().add(new LineTo (bX, bY));
        }
    });

    BorderPane borderPane = new BorderPane();
    borderPane.setCenter(pane);
    borderPane.setBottom(hBox);
    BorderPane.setAlignment(pane, Pos.CENTER);

    btClear.setOnAction(e -> {
        pane.getChildren().clear();
        pane.getChildren().add(path);
    });

    btExit.setOnAction(e ->
        System.exit(0)
    );



    // Create the scene object
    Scene scene = new Scene(borderPane, 400, 400); // places the pane in the scene
    primaryStage.setTitle("Draw a line with arrow keys");
    primaryStage.setScene(scene); // places the scene in the stage
    primaryStage.show(); // shows the window
    path.requestFocus();
    primaryStage.setResizable(false); // prevent user from resizing the window

}


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

}

1 Ответ

0 голосов
/ 15 октября 2019

Вот контроллер рисования для моего Etch-A-Sketch

public class ButtonDrawController implements Initializable {

@FXML private Pane paneMain,paneButtonDraw;
@FXML private ColorPicker colorpicker;
@FXML private Canvas canvasPaper;
@FXML private ChoiceBox<String> penSize;
@FXML private ChoiceBox<String> pickCircle;
@FXML private Label msg;
@FXML private ToggleButton tbnHelp;

public Stage stage;
GraphicsContext graphicsContext;
KeyCode keycode;
double X,Y;
double startAngle,arcExtent;
final Printer selectedPrinter = Printer.getDefaultPrinter();

@FXML
private void showHelp(ActionEvent e){
    if(tbnHelp.isSelected()){
        tbnHelp.setText("Hide Directions");
        tbnHelp.setStyle("-fx-background-color:darkgray;"
        +"-fx-border-style: solid outside;"
        +"-fx-border-width: 2;"
        +"-fx-border-color: blue;");

        String help = "\n\n" 
            +"                         These direction are for Draw with the Buttons\n\n" 
            +"To change Color or Pen Size see the Draw with the Mouse Directions.\n"
            +"When Drawing with Buttons if Color or Pen Size is changed it is best\n"
            +"to select a new draw position by clicking the Mouse on the paper.\n"
            +"ERASE and PRINT is covered in the Draw with Mouse Directions also.\n\n"
            +"Click the paper with the mouse to start drawing at that location.\n\n"
            +"To use the Pick Circle Type click the button and select the Circle Type.\n"
            +"To draw the Circle Type PRESS the Key Board 'A' key.\n"
            +"To draw a paint scattered type image PRESS the Key Board 'S' key.\n\n"
            +"                         Button Information for Drawing\n"
            +"-------------------------------------------------------------------------------------\n"
            +"To start drawing in the center of the paper PRESS the Key Board 'C' key.\n"
            +"To draw at other positions on the paper Click the Mouse at that location.\n\n"
            +"To draw a line UP - DOWN - LEFT - RIGHT  PRESS the Arrow Keys.\n\n"
            +"To draw a diagonal line PRESS the keys as described below.\n\n"
            +"UP and RIGHT"+"        "+"use the Numeric Key 9 or the Key Board 'H' key\n"
            +"UP and LEFT"+"           "+"use the Numeric Key 7 or the Key Board 'G' key\n"
            +"DOWN and RIGHT use the Numeric Key 3 or the Key Board 'N' key\n"
            +"DOWN and LEFT"+"     "+"use the Numeric Key 1 or the Key Board 'V' key\n\n";

        msg.setLayoutX(80);
        msg.setLayoutY(80);
        msg.setText(help);
        msg.setVisible(true);
        msg.toFront();
    }else{
        msg.setVisible(false);
        tbnHelp.setText("Show Directions");
        tbnHelp.setStyle("-fx-background-color:lightgray;"
        +"-fx-border-style: solid outside;"
        +"-fx-border-width: 2;"
        +"-fx-border-color: blue;"); 
    }
}

@FXML
private void onPrint(ActionEvent e){
    printDialogSetup();   
}

private void printDialogSetup(){
    int lMargin =  (int) 0.2;//Printer sets margins as inches
    int rMargin =  (int) 0.2;//Need to convert inches to pixels ?
    int tMargin =  (int) 0.2;
    int bMargin =  (int) 0.2;
    PrinterJob job = PrinterJob.createPrinterJob();
    //PageLayout pageLayout = selectedPrinter.createPageLayout(Paper.NA_LETTER,PageOrientation.PORTRAIT,Printer.MarginType.EQUAL);
    PageLayout pageLayout = selectedPrinter.createPageLayout(Paper.NA_LETTER, PageOrientation.PORTRAIT, lMargin, rMargin, tMargin, bMargin);

    JobSettings jobSettings = job.getJobSettings();
    jobSettings.setPageLayout(pageLayout);

    boolean printed = job.printPage(canvasPaper);
        if (printed) {
        // End the printer job
        job.endJob();
        } 
}

@FXML
private void onPickCircle(MouseEvent e){

   pickCircle.getSelectionModel().selectedIndexProperty().addListener((ChangeListener<? super Number>)(ov, old, newval) -> {
        Number idx = (Number)newval;

        switch(idx.intValue()){

        case 0: startAngle = 0;
                arcExtent = 0;
        break;
        case 1: startAngle = 0;// Circle
                arcExtent = 360;
        break;
        case 2: startAngle = 0;// N
                arcExtent = 180;
        break;
        case 3: startAngle = -90;// E
                arcExtent = 180;
        break;
        case 4: startAngle = 0;// S
                arcExtent = -180;
        break;
        case 5: startAngle = 90;//W
                arcExtent = 180;
        break;
        default: startAngle = 0;
                 arcExtent = 360;
        break;
        }
        });

    canvasPaper.requestFocus();
}

@FXML
private void onPenSize(MouseEvent e){

   penSize.getSelectionModel().selectedIndexProperty().addListener((ChangeListener<? super Number>)(ov, old, newval) -> {
        Number idx = (Number)newval;

        switch(idx.intValue()){

        case 0: graphicsContext.setLineWidth(1);
        break;
        case 1: graphicsContext.setLineWidth(2);
        break;
        case 2: graphicsContext.setLineWidth(3);
        break;
        case 3: graphicsContext.setLineWidth(4);
        break;
        case 4: graphicsContext.setLineWidth(5);
        break;
        case 5: graphicsContext.setLineWidth(8);//REAL big
        break;
        default: graphicsContext.setLineWidth(1);
        break;
        }
        graphicsContext.setLineCap(StrokeLineCap.ROUND);
        });
    canvasPaper.requestFocus();
}

@FXML 
private void onPickColor(ActionEvent e){
    // change cursor more exact placement on the screen
    // graphicsContext.getCanvas().cursorProperty().set(Cursor.CROSSHAIR);
    graphicsContext.setStroke(colorpicker.getValue());
    canvasPaper.requestFocus();
}

@FXML
private void onPressed(MouseEvent e){

    if(tbnHelp.isSelected()) {// Close the toggle button and HELP screen
        tbnHelp.setSelected(false);
        showHelp(null);
    }
    graphicsContext.getCanvas().cursorProperty().set(Cursor.CROSSHAIR);
    graphicsContext.beginPath();
    graphicsContext.moveTo(e.getX(), e.getY());
    graphicsContext.setStroke(colorpicker.getValue());
    X = e.getX();
    Y = e.getY();
} 

@FXML
private void onDraw(KeyEvent ev){

    keycode = ev.getCode();

    if(X == 0 && Y == 0 ){
    Alert alert = new Alert(AlertType.INFORMATION);
        alert.initStyle(StageStyle.UTILITY);
        alert.setTitle("Information");
        alert.setHeaderText("");
        alert.setContentText("CLICK ON THE PAPER TO START DRAWING");
        alert.showAndWait();
        return;
    }

    if(keycode == KeyCode.A){// Draws the Circle Type

        if(arcExtent == 0){
        Alert alert = new Alert(AlertType.INFORMATION);
            alert.initStyle(StageStyle.UTILITY);
            alert.setTitle("Information");
            alert.setHeaderText("");
            alert.setContentText("To Draw a Circle Type\n\n"
                                +"First Use Pick Circle Type");
            alert.showAndWait();   
            return;   
        }
        double XX = 120;
        graphicsContext.stroke();         
        graphicsContext.strokeArc(X, Y-60, XX, XX, startAngle, arcExtent, ArcType.OPEN);
    }

    if(keycode==KeyCode.S){

        graphicsContext.beginPath();
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+80, Y+80);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+40, Y+60);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+120, Y+20);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+180, Y+120);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X-180, Y-120);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X-80, Y+80);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X-40, Y+60);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X-120, Y+20);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X-80, Y-80);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X-40, Y-60);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X-120, Y-20);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+80, Y+80);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+40, Y+60);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+120, Y+20);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+20, Y-80);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+10, Y-60);
        graphicsContext.moveTo(X,Y);
        graphicsContext.lineTo(X+50, Y-120);
        graphicsContext.setStroke(colorpicker.getValue());
        graphicsContext.stroke();
    }

    if(keycode==KeyCode.C){// Center drawing position
        X = 296;
        Y = 381;
        graphicsContext.beginPath();
        graphicsContext.moveTo(X,Y);
        graphicsContext.setStroke(colorpicker.getValue());
    }

    if(keycode==KeyCode.NUMPAD9){// 9
        if(Y <= 21 || X >= 570){
            return;
        }
        X = X + 15.5;
        Y = Y - 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.H){// same as NUMPAD9
        if(Y <= 21 || X >= 570){
            return;
        }
        X = X + 15.5;
        Y = Y - 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.NUMPAD7){// 7
        if(Y <= 21 || X <= 19){
            return;
        }
        X = X - 15.5;
        Y = Y - 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.G){// same as NUMPAD7
        if(Y <= 21 || X <= 19){
            return;
        }
        X = X - 15.5;
        Y = Y - 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.NUMPAD1){// 1
        if(X <= 21 || Y >= 740){
            return;
        }
        X = X - 15.5;
        Y = Y + 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.V){// same as NUMPAD1
        if(X <= 21 || Y >= 740){
            return;
        }
        X = X - 15.5;
        Y = Y + 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }

    if(keycode==KeyCode.NUMPAD3){
        if(X >= 575 || Y >= 740){
            return;
        }
        X = X + 15.5;
        Y = Y + 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.N){// same as NUMPAD3
        if(X >= 575 || Y >= 740){
            return;
        }
        X = X + 15.5;
        Y = Y + 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.UP){
        if(Y <= 21){
            return;
        }
        X = X;
        Y = Y - 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.DOWN){
        if(Y >= 740){
            return;
        }
        X = X;
        Y = Y + 20;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke(); 
    }
    if(keycode==KeyCode.LEFT){
        if(X <= 21){
            return;
        }
        X = X - 20;
        Y = Y ;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
    if(keycode==KeyCode.RIGHT){
        if(X >= 570){
            return;
        }
        X = X + 20;
        Y = Y;
        graphicsContext.lineTo(X,Y);
        graphicsContext.stroke();
    }
}

@FXML
private void onErase(ActionEvent e){

    X = 0;
    Y = 0;
    graphicsContext.clearRect(0, 0,
    graphicsContext.getCanvas().getWidth(),
    graphicsContext.getCanvas().getHeight());
    penSize.getSelectionModel().selectFirst();
    pickCircle.getSelectionModel().selectFirst();
    colorpicker.setValue(Color.RED);
}

@FXML
private void onBack(ActionEvent e) throws IOException{

    stage = (Stage)paneButtonDraw.getScene().getWindow();
    paneMain = FXMLLoader.load(getClass().getResource("etch.fxml"));
    Scene scene = new Scene(paneMain);
    stage.setScene(scene);
    stage.setTitle("Etch A Sketch"); 
    stage.show();
    stage.sizeToScene();
    stage.centerOnScreen();
}

private void Init(){

    graphicsContext = canvasPaper.getGraphicsContext2D();
    colorpicker.setValue(Color.RED);
    graphicsContext.setStroke(colorpicker.getValue());
    penSize.getItems().addAll("1","2","3","4","5","6");
    penSize.getSelectionModel().selectFirst();

    // Set values for Choice Box set here only needs to happen once
    pickCircle.getItems().addAll("Click to Select","Circle","Half Circle N","Half circle E","Half Circle S","Half Circle W");
    pickCircle.getSelectionModel().selectFirst();// Makes first value visable in Choice Box
    tbnHelp.setStyle("-fx-background-color:lightgray;"
        +"-fx-border-style: solid outside;"
        +"-fx-border-width: 2;"
        +"-fx-border-color: blue;");
}

@Override
public void initialize(URL location, ResourceBundle resources) {
    Init(); 
}

}

...