带有自定义控件和自定义 StringProperty 的 Proguard
Posted
技术标签:
【中文标题】带有自定义控件和自定义 StringProperty 的 Proguard【英文标题】:Proguard with custom control and custom StringProperty 【发布时间】:2021-12-27 06:56:59 【问题描述】:我想将 proguard 与带有一些自定义控件的 javafx 应用程序一起使用。
我有一个包含属性的自定义控件
StringProperty textProperty = new SimpleStringProperty(this,"text");
public final StringProperty textProperty() return textProperty;
public final String getText() return textProperty().get();
public final void setText(String text) textProperty.set(text);
我在一个 fxml 文件中使用我的自定义控件。
<Menu [...] text="logo"/>
Menu 类是我的自定义控件,所有导入语句都可以。
在我的 pom 文件中,我保持 StringProperties 不变。
<option>-keepclassmembers class * extends javafx.scene.control.Control javafx.beans.property.StringProperty *;
public final javafx.beans.property.StringProperty *;
public final java.lang.String *;
public final void *;
</option>
我在启动应用程序时收到此错误。
Caused by: com.sun.javafx.fxml.PropertyNotFoundException: Property "text" does not exist or is read-only.
编辑 MRE
pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>Example</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Example</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- Java Fx libraries -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>16</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>16</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<obfuscate>true</obfuscate>
<optimize>true</optimize>
<shrink>true</shrink>
<injar>$project.build.finalName.jar</injar>
<outjar>$project.build.finalName.jar</outjar>
<includeDependency>true</includeDependency>
<options>
<option>-keep public class com.example.Main *; </option>
<option>-keep public class com.example.Launcher *; </option>
<option>-keepnames class com.example.custombuttons.*</option>
<option>-adaptresourcefilecontents **.fxml </option>
<option>-dontnote jdk.internal.jimage.*</option>
<option>-dontnote module-info</option>
<option>-dontnote jdk.internal.jrtfs.*</option>
<option>-dontnote jdk.internal.jimage.decompressor.*</option>
<option>-classobfuscationdictionary $project.basedir/keywords.txt</option>
<option>-keepclassmembers class * extends javafx.scene.control.Control javafx.beans.property.StringProperty *;
public final javafx.beans.property.StringProperty *;
public final java.lang.String *;
public final void *;
</option>
</options>
<libs>
<lib>$java.home/jmods/java.base.jmod</lib>
<lib>$java.home/jmods/java.xml.jmod</lib>
<lib>$java.home/jmods/java.datatransfer.jmod</lib>
<lib>$java.home/jmods/java.desktop.jmod</lib>
</libs>
<archive>
<manifest>
<mainClass>Main</mainClass>
<packageName>com.example</packageName>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.Launcher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
启动器类。
package com.example;
import javafx.application.Application;
public class Launcher
public static void main(String[] args)
Application.launch(Main.class);
主类
package com.example;
import com.example.custombuttons.Menu;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application
Menu menu;
@Override
public void start(Stage primaryStage) throws Exception
AnchorPane pane;
FXMLLoader mainLoader = new FXMLLoader(getClass().getClassLoader().getResource("layouts/main.fxml"));
pane = mainLoader.load();
Scene scene = new Scene(pane, 600, 445);
primaryStage.setScene(scene);
primaryStage.show();
menu = (Menu) scene.lookup("#menu");
菜单类
package com.example.custombuttons;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.Control;
import javafx.scene.control.Skin;
public class Menu extends Control
StringProperty textProperty = new SimpleStringProperty(this,"text");
public final StringProperty textProperty() return textProperty;
public final String getText() return textProperty().get();
public final void setText(String text) textProperty.set(text);
public Menu()
super();
public Menu(String text)
super();
@Override protected Skin<?> createDefaultSkin()
return new MenuSkin(this);
MemuSkin 类
package com.example.custombuttons;
import javafx.scene.control.SkinBase;
public class MenuSkin extends SkinBase<Menu>
String text;
public MenuSkin(Menu control)
super(control);
text = control.getText();
Main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import com.example.custombuttons.Menu?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" >
<children>
<Menu layoutX="238.0" layoutY="224.0" prefHeight="63.0" prefWidth="125.0" text="menu" />
</children>
</AnchorPane>
堆栈跟踪
Caused by: javafx.fxml.LoadException:
file:C:/USER/example/target/Example-1.0-SNAPSHOT.jar!/layouts/main.fxml:10
[...]
Caused by: com.sun.javafx.fxml.PropertyNotFoundException: Property "text" does not exist or is read-only.
at javafx.fxml.FXMLLoader$Element.processValue(FXMLLoader.java:357)
at javafx.fxml.FXMLLoader$Element.processPropertyAttribute(FXMLLoader.java:334)
at javafx.fxml.FXMLLoader$Element.processInstancePropertyAttributes(FXMLLoader.java:244)
at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:777)
at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2924)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2639)
【问题讨论】:
hmm .. 如果没有 proguard,它是否按预期工作?无论如何,请minimal reproducible example。 我以为有人会问这个,但我真的希望有人以前看过这个。我将创建一个 MRE @kleopatra 我用一个可以按原样运行的示例编辑了这个问题。干杯 【参考方案1】:我发现我的通配符不正确。 应该是,以一般的方式:
<option>-keepclassmembers class * extends javafx.scene.control.Control
javafx.beans.property.* *;
void set*(***);
boolean is*();
*** get*();
</option>
事实上,这将解决自定义控制文件中所有属性的问题。
【讨论】:
以上是关于带有自定义控件和自定义 StringProperty 的 Proguard的主要内容,如果未能解决你的问题,请参考以下文章