1
votes

I'm trying to make a sprite editor using JavaFX using buttons as the pixels. I am able to change the colour of each button on press, but I'm trying to get it so if I click and drag I can paint multiple pixels.

The problem I'm finding is that after clicking and holding onto a button, I am unable to select the new button when I move the mouse over new button to select that one too. If I click and drag re-entering that button I can get the "Paint Dragged Pixel" debug message, but not if I enter a new pixel with the mouse down, which is what I want. Also I can get the pixel button to print "Entered Pixel" when the mouse enters any button, but not for when I click and drag to a new pixel.

I think the problem is that when I click on one pixel I am locked in, and unable to select a new pixel by hovering over a new one. Is there a way to unbind this selection, or is the problem a different one.

Main Application:

public class Main extends Application {


boolean mousePressed = false;
public boolean isMousePressed() {
    return mousePressed;
}


@Override
public void start(Stage primaryStage) throws Exception{

    BorderPane borderPane = new BorderPane();
    primaryStage.setTitle("SpriteSheet");
    Group root = new Group();
    Scene scene = new Scene(borderPane, 500,200);
    scene.setFill(Color.BLACK);

    primaryStage.setScene(scene);
    GridPane gridPane = new GridPane();
    borderPane.setCenter(root);

    for(int x = 0; x < 10; x++)
    {
        for(int y = 0; y < 10; y++) {
            PixelButton button = new PixelButton();
            button.setParentMain(this);

            button.setOnMousePressed(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    mousePressed = true;
                    System.out.println("mouseDown");
                }
            });

            button.setOnMouseReleased(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event) {
                    mousePressed = false;
                    System.out.println("mouseUp");
                }
            });

            gridPane.add(button, x, y);
        }
    }

    root.getChildren().add(gridPane);

    primaryStage.show();
}


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

}

The class for the PixelButton.

public class PixelButton extends Button {

Main parentMain;
public void setParentMain(Main parent) {
    parentMain = parent;
}

public PixelButton() {

    this.setMinSize(10, 10);
    this.setPrefSize(10, 10);

    this.setOnMousePressed(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {

        }
    });
    this.setOnMouseEntered(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            System.out.println("Entered Pixel");

            if(parentMain.isMousePressed()){
                System.out.println("Paint Dragged Pixel");
            }
        }
    });
}

}

Thank you in advance.

1
hmm .. what do you mean by "select"? that's not part of a button's semantic (nor a mouse handlers, faiw) Anyway, whatever you try to do, the handler you register on each button in main will replace the handler (for the same event type) you had registered in the button itself. Either decide which you want or replace one registration by addEventHandler. Also note, that a released is delivered to the node that received the pressed - kleopatra
Hi, thanks for the response. By select I am referring to that it is not invoked. I believe this is the isarmed() property that only invokes when the mouse button is released. I've tried using fire() to invoke the button manually, but to no success so far. I've also tried disarming() the button. The overwrite is correct. setOnMousePressed() in PixelButton was overwritten. I've implemented it in the main for now, but its not fixing the press and drag issue. Its the OnMouseEnter() of Pixel button where I'm confused to why it does not work. If mouse enter and is pressed. It should in my mind. - Alistair

1 Answers

0
votes

Ok so I have been thinking about this one for a bit and have finally come up with a solution I simplified my solution a bit and used rectangles instead of buttons but you can transfer most of the code to the buttons as well so to start with this is not the exact functionality you were looking for but as close as I could get basically I fire an event on mouse press that releases the mouse click and as long as that event is not coming from the rectangle then dont flip the painting boolean paint and so you basically click to enter a "Paint Mode" and click again to get out of coloring tiles

public class Main extends Application {    

    private boolean mousePressed;

    @Override
    public void start(Stage primaryStage) throws Exception{
        BorderPane borderPane = new BorderPane();
        primaryStage.setTitle("SpriteSheet");
        Group root = new Group();
        Scene scene = new Scene(borderPane, 500,200);
        //        scene.setFill(Color.BLACK);

        primaryStage.setScene(scene);
        GridPane gridPane = new GridPane();
        borderPane.setCenter(root);

        for(int x = 0; x < 10; x++) {
            for(int y = 0; y < 10; y++) {
                Rectangle rectangle = new Rectangle(10, 10);
                rectangle.setOnMousePressed(event -> {
                    mousePressed = true;
                    System.out.println("mouseDown");
                    rectangle.fireEvent(new MouseEvent(MouseEvent.MOUSE_RELEASED,
                            rectangle.getLayoutX(), rectangle.getLayoutY(), rectangle.getLayoutX(), rectangle.getLayoutY(),
                            MouseButton.PRIMARY, 1,
                            false, false, false, false,
                            false, false, false, false,
                            false, false, null));
                });

                rectangle.setOnMouseReleased(event -> {
                    System.out.println(event.getSource());
                    if(!event.getSource().toString().equals("Rectangle[x=0.0, y=0.0, width=10.0, height=10.0, fill=0x000000ff]")) {
                        mousePressed = false;
                        System.out.println("mouseUp");
                    }
                });

                rectangle.setOnMouseMoved(event -> {
                    if(mousePressed) {
                        rectangle.setFill(Color.BLUE);
                    }
                });

                gridPane.add(rectangle, x, y);
            }
        }
        root.getChildren().add(gridPane);
        primaryStage.show();
    }
    public static void main(String[] args) { launch(args); }
}