- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个基于 JavaFX 的界面,我正在尝试使用 JavaFXPorts 在多个平台上构建该界面。大多数代码是与平台无关的,但我有一些调用特定于平台的代码的实用程序,例如Android 与桌面上的文件系统位置。例如,在下面的 MCVE 中:使用 gradledesktop
或 gradle android
进行构建,我得到:
src/main/java/com/example/project/MyApp.java:30: error: cannot find symbol
platformGreeting = new Label("hello, " + Util.getPlatform());
^
symbol: variable Util
location: class MyScene
但是,如果我将两个源文件(MyApp.java
和 Util.java
)放在任何源目录(main
)中, desktop
, android
) 并运行相应的任务,它将构建。
在我看到的示例中,他们总是在 src/main
下实现与平台无关的接口(interface),然后在每个特定于平台的目录中实现它,但我不明白为什么这应该是必要的。
├── build.gradle
├── settings.gradle
└── src
├── android
│ └── java
│ └── com
│ └── example
│ └── project
│ └── Util.java
├── desktop
│ └── java
│ └── com
│ └── example
│ └── project
│ └── Util.java
└── main
└── java
└── com
└── example
└── project
└── MyApp.java
构建.gradle:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.10'
}
}
apply plugin: 'org.javafxports.jfxmobile'
mainClassName = 'com.example.project.MyApp'
repositories {
jcenter()
}
dependencies {
}
jfxmobile {
ios {
forceLinkClasses = [ 'com.example.project.**.*' ]
}
android {
applicationPackage = 'com.example.project'
}
}
设置.gradle:
rootProject.name = 'project'
src/main/java/com/example/project/MyApp.java:
package com.example.project;
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.scene.layout.Region;
public class MyApp extends Application {
private Scene scene;
@Override public void start(Stage stage) {
stage.setTitle("MyApp");
scene = new Scene(new MyScene(), 750, 500);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
class MyScene extends Region {
final Label platformGreeting = new Label("hello, " + Util.getPlatform());
public MyScene() {
getChildren().add(platformGreeting);
}
@Override protected void layoutChildren() {
double w = getWidth();
double h = getHeight();
layoutInArea(platformGreeting, 0, 0, w, h, 0, HPos.CENTER, VPos.CENTER);
}
@Override protected double computePrefWidth(double height) {
return 750;
}
@Override protected double computePrefHeight(double width) {
return 500;
}
}
src/desktop/java/com/example/project/Util.java:
package com.example.project;
public final class Util {
private Util() {
throw new UnsupportedOperationException();
}
public static final String getPlatform() {
return "desktop";
}
}
src/android/java/com/example/project/Util.java:
package com.example.project;
public final class Util {
private Util() {
throw new UnsupportedOperationException();
}
public static final String getPlatform() {
return "android";
}
}
最佳答案
顺便说一句,源集是在 JavaFXPorts 中定义的,main
由所有平台共享,然后每个特定的包由给定平台使用,即 desktop
仅在桌面上。
由于main
代码由所有平台共享,因此它不能包含特定平台代码,并且它不真正了解添加到的平台代码任何平台。
这就是为什么在尝试将 Util
添加到 main
时出现编译异常的原因。
解决方案1
第一种方法可以使用Class.forName(className)
来完成。在运行时,它将尝试在类路径中查找给定的类。
所以这最初应该有效:
try {
Class<?> util = Class.forName("com.example.project.Util");
} catch (ClassNotFoundException ex) {
Logger.getLogger(BasicView.class.getName()).log(Level.SEVERE, null, ex);
}
但是你遇到了一个问题:你无法真正转换到主包中的 Util
。
一种可能的解决方案是使用反射:
try {
Class<?> util = Class.forName("com.example.project.Util");
Object newInstance = util.newInstance();
Method method = util.getDeclaredMethod("getPlatform");
String platform = (String) method.invoke(newInstance);
System.out.println("Platform: " + platform));
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(BasicView.class.getName()).log(Level.SEVERE, null, ex);
}
为了方便起见,我修改了 Util
:
public class Util {
public Util() {
}
public final String getPlatform() {
return "desktop";
}
}
虽然这工作得很好,但使用起来并不容易。
解决方案2
因此,让我们向 main
包中添加一些中立的 API,我们可以更轻松地调用这些 API:具有我们感兴趣的方法的接口(interface):
public interface Platform {
String getPlatform();
}
现在让我们在平台类中实现它:
public class Util implements Platform {
public Util() {
}
@Override
public final String getPlatform() {
return "desktop";
}
}
现在事情变得更容易了,因为现在您可以获得一个 Platform
实例,并调用 getPlatform()
:
try {
Class<?> util = Class.forName("com.gluonhq.forname.Util");
Platform platform = (Platform) util.newInstance();
System.out.println("Platform: " + platform.getPlatform());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
Logger.getLogger(BasicView.class.getName()).log(Level.SEVERE, null, ex);
}
解决方案 3:降低魅力
Charm Down 是 open source library它提供不同的 native 服务,具有可从 main
包中使用的中性 API,位于所需的平台特定代码(用于桌面的 Java、Android 或用于 iOS 的 Objective-C)之上。
在您的 IDE 中使用 Gluon 插件,并创建一个使用 jfxmobile
插件的项目,将包含 Charm Down 中包含的一些服务,如 build.gradle
文件:
jfxmobile {
downConfig {
version = '3.7.0'
plugins 'display', 'lifecycle', 'statusbar', 'storage'
}
...
}
如果你看看这些服务是如何实现的,有一个核心插件有几个 classes :
平台
服务
服务工厂
...现在在您的项目中,如果包含 Charm Down 依赖项,则可以使用 Platform.getCurrent().name()
。
System.out.println("Platform: " + Platform.getCurrent().name());
不仅如此,您还可以通过以下方式获得任何服务:
Services.get(DisplayService.class)
.ifPresent(display -> System.out.println("Resolution: " + display.getScreenResolution()));
我建议您看看这些类是如何实现的。并检查不同的服务available所以你不要再次实现它们。许多可用样本 here使用其中一项或多项服务。
关于JavaFXPorts jfxmobile-plugin 未找到特定于平台的目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49034395/
我目前正在努力解决可能非常简单的问题:如何将一个 JavaFXPorts 特定项目用作另一个同类项目中的依赖项? 对于纯粹分离的项目,我不知道如何将它们组合起来(不得不承认,我对 Gradle 的了解
我的项目具有语言相关文本的属性文件,这些文本在 ISO-8859-1 中编码(默认从内容类型派生)。它们是使用ResourceBundle读取的。当我在 Android 上运行该应用程序时,我看到不可
请查看图像以获取代码引用: 如果运行上面的代码,TextArea 显示File Exists: false。 请注意:此代码有效:ImageView image = new ImageView(new
您好,我正在尝试开始使用 javafxports 为 Android 构建应用程序,我有 android sdk 和 gradle(尝试使用 2.3 和 2.2)从获取站点的起始页构建简单的应用程序,
我目前正在使用 GluonHQ 和 JavaFXPorts 使用 JavaFX 开发移动应用程序。我的其中一个屏幕包含一个 ListView ,您可以从下面的屏幕截图中看到,该屏幕截图是从我的 iPh
示例代码如下: package com.javafxportslistviewdemo; import com.gluonhq.charm.down.Platform; import com.gluo
我有一个基于 JavaFX 的界面,我正在尝试使用 JavaFXPorts 在多个平台上构建该界面。大多数代码是与平台无关的,但我有一些调用特定于平台的代码的实用程序,例如Android 与桌面上的文
我已经开始尝试获取有关此问题的一些信息(请参阅 here ),但这一次,我创建了一个示例应用程序来展示我的问题(希望以比上次更好的方式)。 在我开始之前,这里是应用程序存储库的链接: https://
我想用 JavaFXPorts 构建一个 JavaFX Android 应用程序和 Kotlin 代码。是否可以在 JavaFXPorts 项目中使用 Kotlin?这是我的示例 Gradle(版
我正在尝试使用 javafxports 从 javaFX 项目构建 Android 应用程序。目前,我在移动设备上安装并启动它时遇到问题,它抛出 ConfigurationException。 这是使
我在将 Javafx 应用程序构建到 Android 时遇到以下异常。 error: Error: No resource found that matches the given name (at
我将使用 sqlite 编写示例代码,它必须适用于 Android 和 IOS(和桌面) 这是我的build.gradle buildscript { repositories {
有没有办法访问 UIViewController,舞台正在运行?据我所知,在 RoboVM 和 Android 上有类似的东西,我们有 FXActivity 来完成这样的任务...... 感谢和问候,
我在使用 JavaFxPorts 在 Android 上保存文件时遇到问题。 我找到了那个链接 here ,但这对我不起作用。 它没有找到接口(interface),我无法使用它。 我的目标是使用 J
我使用 javafxports 和 gradle 在 netbeans 中编写了一个 javafx andoid 应用程序。我将依赖项添加到 gradel,但现在我不知道如何将 jars 添加到我的项
我在开发要移植到 Android 的 Javafx 应用程序时使用了 Netbeans 的 Gluon 插件,我想在 Android 的 Assets 文件夹中添加一些文件,但我找不到它?在哪里放置
我正在尝试使用 JavaFXPorts 和 RoboVM-cocoatouch 但我无法使用 RoboVM 中的原生内容,例如 UIButton。 我的 build.gradle 文件中有以下依赖项:
我想创建一个使用 MySqlDB 连接的应用程序/桌面应用程序。我在 Netbeans 中使用了 Gluon 插件。当我想编译桌面应用程序时,一切正常。但是当我想编译 Android 应用程序时 ->
在 Android 手机上启动我的应用程序时出现以下错误 FATAL EXCEPTION: main Process: ie.murphysoftware.games.magnatron, PID:
我正在尝试使用 javafxports 编写一个简单的 sqlite 代码。 build.gradle: buildscript { repositories { jc
我是一名优秀的程序员,十分优秀!