No detection of a touchScreen Button event in a mo

2019-09-17 21:24发布

问题:

I made a Javafx application that works fine on PC. Now, I try to transfer it to Android Smartphone. To do that, I use JavaFXPorts (Gluon), with Eclipse and Gradle.

Now, I am stuck with a very simple example:

void showPopUp() {
     Button button = new Button("Action do do")); 
     HBox.setMargin(button , new Insets(10, 30, 10, 30));

     button .setOnAction(e -> {
            actionToDo();
        });

     Scene scene = new Scene (button, 100, 200);
     Stage stage = new Stage();
     stage.initModality(Modality.APPLICATION_MODAL);
     stage.setScene(scene);
     stage.show();
}

Have you an idea of the reason?

Thanks

Here is the whole code with:

  • a periodic task (it works fine)

  • a delayed task (it works fine)

  • a button "btn" that displays the modal PopUp. The touchScreen on it works fine and allows to go to the PopUp

  • the PopUp with 2 buttons boutonPopUpA and boutonPopUpB that are added to the HBOX boutonsMenuPrincipal

  • and a stage with its scene "connected to" boutonsMenuPrincipal

In the popUp, boutonPopUpA and boutonPopUpB are displayed but inactive (No generated trace on a touchScreen)

 package com.gluonapplication;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;

public class GluonApplication extends Application {

    private int nbAppuiToucheSetOnAction = 0;
    private int nbAppuiTouchePopUp = 0;


    static long BDTapplication = 110;
    static long nbBDT = 0;
    static long t0 = System.currentTimeMillis();


    /********************************************************/
    public static void periodicProcessing(String str) {
        nbBDT++;
        traceWithSystemTime("periodicProcessing of " + str + " / nbBDT: " + nbBDT);
    }

    /********************************************************/
    public static void traceWithSystemTime(String comments) {
            long t =  System.currentTimeMillis();
            long deltaT =t - t0;
           System.out.println("time - t0: " + t0 + " /  t: "+ t + " / detaT: " + deltaT + " ms --- " + comments);
    }

  /********************************************************/
    public void start(Stage primaryStage) {

        primaryStage.setTitle("Hello World sur Android! ");

        // A PERIODIC TASK
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                for (int i=0; i < 10; i++) {
                    periodicProcessing("timer plus");
                }
            }
        };
           final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
           service.scheduleAtFixedRate(runnable, 0, BDTapplication, TimeUnit.MILLISECONDS);

// A DELAYED TASK
        int TASK_DELAY = 1000; // ms
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                for (int i = 0; i < 10; i++) {
                    periodicProcessing("timer task done");
                }
            }
        };

        new Timer().schedule(task, TASK_DELAY);


        AnchorPane root = new AnchorPane();
         root.setVisible(true);
        Scene scene = new Scene(root);


        // *********************** Button
      // btn works fine
        Button btn = new Button();
        btn.setText("setOnAction 1");

        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                nbAppuiToucheSetOnAction++;
               traceWithSystemTime("SETonACTION: nbAppui = "+ nbAppuiToucheSetOnAction);
                showPopUpMenuPrincipal();
         }
        });
        HBox.setMargin(btn, new Insets(10, 30, 10, 30));

        VBox zoneBtn= new VBox();
        VBox.setMargin(zoneBtn, new Insets(30, 5, 1, 10));
        zoneBtn.getChildren().add( btn);
        zoneBtn.setAlignment(Pos.CENTER);

         root.getChildren().addAll(zoneBtn);


         primaryStage.setTitle("Title");


        // ************************************* DISPLAY
        root.requestFocus();
        primaryStage.setScene(scene);
        primaryStage.setTitle("Test4");
        primaryStage.setFullScreen(true);
        primaryStage.show();

       traceWithSystemTime("End of test");

    }

    /*************************************/
void    showPopUpMenuPrincipal(){
    traceWithSystemTime("Beginning of  showPopUpMenuPrincipal");
    Button boutonPopUpA = new Button("setOnAction 2a");
    boutonPopUpA.setOnAction(e-> {
        nbAppuiTouchePopUp++;
       traceWithSystemTime("Action sur setOnAction 2a: nbAppui: " + nbAppuiTouchePopUp);
    });
    Button boutonPopUpB = new Button("setOnAction 2b");
    boutonPopUpB.setOnAction(e-> {
        nbAppuiTouchePopUp++;
       traceWithSystemTime("Action sur setOnAction 2b: nbAppui: " + nbAppuiTouchePopUp);
    });

    HBox.setMargin(boutonPopUpA, new Insets(10, 30, 10, 30));

    VBox zonePopUp= new VBox();
    VBox.setMargin(zonePopUp, new Insets(30, 5, 1, 10));
    zonePopUp.getChildren().add( boutonPopUpA);
    zonePopUp.setAlignment(Pos.CENTER);


    Stage stagePopUpMenu = new Stage();
    stagePopUpMenu.setTitle("Title");
    stagePopUpMenu.initModality(Modality.APPLICATION_MODAL);

    HBox boutonsMenuPrincipal = new HBox();
    boutonsMenuPrincipal.setAlignment(Pos.CENTER);
    boutonsMenuPrincipal.getChildren().addAll( zonePopUp, boutonPopUpB);

    Scene sceneMenu = new Scene(boutonsMenuPrincipal, 400, 250);

    stagePopUpMenu.setOpacity(0.8);
    stagePopUpMenu.setResizable(false);


    stagePopUpMenu.setScene(sceneMenu);
    stagePopUpMenu.show();
    traceWithSystemTime("End of  showPopUpMenuPrincipal");
}

    }

And my build gradle:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.0.0-b10'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
}

mainClassName = 'com.gluonapplication.GluonApplication'

jfxmobile {
    android {
        applicationPackage = 'com.gluonapplication'
        manifest = 'src/android/AndroidManifest.xml'
        androidSdk = 'C:/Users/pascal/AppData/Local/Android/sdk'
        resDirectory = 'src/android/res'
        compileSdkVersion = '23'
        buildToolsVersion = '22.0.1'
    }
    ios {
        infoPList = file('src/ios/Default-Info.plist')
    }
}

回答1:

You need to update the jfxmobile plugin version. Many things have been fixed and updated since the 1.0.0-b10 version (from a year and a half ago).

Currently the version is 1.3.2. It is not only the plugin, but the mainly the javafxports version that the plugin includes.

If you use the Gluon plugin on your favorite IDE, selecting a Single View project you will get the minimum project template and a valid build.gradle file.

This is an updated build script:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.3.2'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
    }
}

mainClassName = 'com.gluonhq.testtouch.TestTouch'

dependencies {
    compile 'com.gluonhq:charm:4.3.0'
}

jfxmobile {
    downConfig {
        version = '3.2.0'
        plugins 'display', 'lifecycle', 'statusbar', 'storage'
    }
    android {
        manifest = 'src/android/AndroidManifest.xml'
    }
}

You can add all your code to the BasicView, deploy it on mobile and test it.

I've just done it and everything works fine: the task runs fast, and the buttons are responsive.

Using JavaFXPorts it's not recommended creating a second Stage. You can use a Dialog (either built-in JavaFX dialog or Gluon Mobile dialog) instead.

You can test Gluon Mobile library for free, you will get only a nag screen at startup.

Anyway, you can remove the Gluon Mobile library (just remove com.gluonhq:charm:4.3.0 from dependencies), and you'll have to port back MobileApplication to a regular JavaFX Application and remove the BasicView class (mostly as you have now).