【问题标题】:ImageViews MouseEvent not working on a javaFX applicationImageViews MouseEvent 在 javaFX 应用程序上不起作用
【发布时间】:2021-04-17 19:21:28
【问题描述】:

我有一个带有 ImageView 的 javaFX 应用程序,我需要做的是能够拖动一个 ImageView,将它放到另一个 ImageView 上,然后用另一个 ImageView 替换它们。 我的问题是我设置的事件对某些 ImageView 工作得很好,但对其他人则不行。

示例:example,我可以将红色箭头图像拖放到绿色上,但不能将绿色拖放到红色上,我不能将绿色拖放到其他(两个轴和木头)上

我正在从 FXML 文件加载 GUI,这是我的控制器类:

public class PartieGUI {

    @FXML
    Pane gamePane;

    static ArrayList<ElementGUI> elements = new ArrayList<>() {{
        add( new ElementGUI( "OAK_LOG" ) );
        add( new ElementGUI( "STONE_AXE" ) );
        add( new ElementGUI( "IRON_AXE" ) );
        add( new ElementGUI( "DIAMOND_ORE" ) );
        add( new ElementGUI( "DIAMOND_PICKAXE" ) );
    }};

    private static final int HEIGHT = 100;
    private static final int WIDTH = 100;

    @FXML
    public void initialize() {

        gamePane.setOnDragOver( event -> { // for moving the dragged ImageView
            if( event.getGestureSource() instanceof ImageView ) {
                ImageView draggedImageView = ( (ImageView) event.getGestureSource() );
                draggedImageView.setX( event.getX() - WIDTH / 2 );
                draggedImageView.setY( event.getY() - HEIGHT / 2 );
            }
        } );

        for( ElementGUI elementGUI : elements ) {
            setEvents( elementGUI );
            gamePane.getChildren().add( elementGUI.imageView );
        }

    }

    private void setEvents( ElementGUI elementGUI ) {
        ImageView imageView = elementGUI.imageView;

        imageView.setOnDragDetected( event -> {
            Dragboard db = imageView.startDragAndDrop( TransferMode.ANY );
            ClipboardContent content = new ClipboardContent();
            content.putImage( imageView.getImage() );
            content.putString( elementGUI.ID ); ;
            db.setContent( content );
        } );

        imageView.setOnDragOver( event -> {
            Dragboard db = event.getDragboard();
            if( db.hasImage() && !db.getString().equals( elementGUI.ID ) 
                    && event.getGestureSource() instanceof ImageView ) {
                ImageView draggedImageView = ( (ImageView) event.getGestureSource() );
                if( imageView != draggedImageView ) { // prevent that  it drag and drop on itself
                    System.out.println( "dragging over" );
                    event.acceptTransferModes( TransferMode.ANY );
                }
            }
        } );

        imageView.setOnDragDropped( event -> {
            Dragboard db = event.getDragboard();
            if( db.hasImage() && !db.getString().equals( elementGUI.ID ) 
                    && event.getGestureSource() instanceof ImageView ) {
                ImageView draggedImageView = ( (ImageView) event.getGestureSource() );
                if( imageView == draggedImageView )
                    return;
                elements.removeIf( element -> element.imageView == draggedImageView );
                elements.removeIf( element -> element.imageView == imageView );
                ElementGUI newElement = new ElementGUI( "DIAMOND", imageView.getX(), imageView.getY() );
                setEvents( newElement );
                elements.add( newElement );
                refreshGamePane();
            }
        } );
    }

    public void refreshGamePane() {
        gamePane.getChildren().clear();
        for( ElementGUI elementGUI : elements )
            gamePane.getChildren().add( elementGUI.imageView );
    }

    private static class ElementGUI {

        protected String ID;
        protected ImageView imageView;

        ElementGUI( String ID ) {
            this.ID = ID;
            this.imageView = new ImageView(
                      new Image( PartieGUI.class.getResource( "/Textures/" + ID + ".png" )
                    .toString(), 100, 100, false, false )
            );
            this.imageView.setX( new Random().nextInt( 500 ) ); // tmp
            this.imageView.setY( new Random().nextInt( 200 ) );
        }

        public ElementGUI( String ID, double x, double y ) {
            this.ID = ID;
            this.imageView = new ImageView(
                      new Image( PartieGUI.class.getResource( "/Textures/" + ID + ".png" )
                    .toString(), 100, 100, false , false )
            );
            this.imageView.setX( x );
            this.imageView.setY( y );
        }

    }

}

我的应用程序类,后面是FXML文件,如果你想测试(不要问为什么Pane在BorderPane中,我需要它是这样的)

public class Executor extends Application {
    
    public static void main( String[] args ) {
        launch();
    }

    @Override
    public void start( Stage primaryStage ) throws IOException {
        primaryStage.setScene( new Scene( FXMLLoader.load( 
                Executor.class.getResource( "/GUIs/PartieGUI.fxml" ) 
        ) ) ); // load FXML file
        primaryStage.show();
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>

<BorderPane prefHeight="400.0" prefWidth="800.0" style="-fx-background-color: dedddd;" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="PartieGUI">
   <center>
      <Pane fx:id="gamePane" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
   </center>
</BorderPane>

由于有人说所有这些信息都不足以用于“最小可重现示例”,因此这是我使用的图像:https://imgur.com/a/sb3nmKC

还有 build.gradle(我有没有集成 javaFX 库的 JDK 11,所以我必须使用 gradle):

plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.9'
    id "com.github.johnrengelman.shadow" version "6.1.0"
}

repositories {
    mavenCentral()
}

mainClassName = 'Executor'
archivesBaseName = 'MoriaMines'

shadowJar {
    archiveFileName = archivesBaseName + ".jar"
    manifest {
        attributes 'Main-Class': mainClassName
    }
}

javafx {
    version = "15.0.1"
    modules = ['javafx.controls', 'javafx.fxml']
}

【问题讨论】:

  • @kleopatra 我在帖子末尾添加了所有其他信息,我在代码中找不到其他任何内容,没有其他类
  • 我可以重现您所描述的内容 - 感觉很明显......但我没有看到它;)
  • 在 dragDetected 中调用 imageView.toBack 似乎可以解决它.. 不太明白为什么,但可能是我们需要把它排除在外(都有一个可能会干扰的处理程序)
  • 哦,是的,它现在工作得很好,不明白为什么太 x)。您可以将其发布为答案,以便我接受吗?
  • 你可以回答你自己的问题:)

标签: java events javafx drag-and-drop mouseevent


【解决方案1】:

kleopatra 的回答:在 setOnDragDetected 中调用 imageView.toBack(); 修复了它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    相关资源
    最近更新 更多