IllegalAccessException для JFXTextField с Java SDK 12 - PullRequest
4 голосов
/ 28 апреля 2019

Я добавил JFXTextField в свое приложение javafx, но получил эту ошибку, не зная, как ее решить

класс com.jfoenix.skins.JFXTextFieldSkin (в модуле com.jfoenix) не может получить доступ к члену класса javafx.scene.control.skin.TextFieldSkin (в модуле javafx.controls) с модификаторами «private»

Контроллер:

package sample;

import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTextField;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;

import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable {

@FXML
private Button clickMe;


@FXML
private JFXButton materialButton;

@FXML
private JFXTextField textField;


@Override
public void initialize(URL url, ResourceBundle resourceBundle) {

    materialButton.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent actionEvent)
        {
            String text = textField.getText().trim();
            System.out.println(text);
        }
    });

}
}

Sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXTextField?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: #fcda;" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <Button fx:id="clickMe" layoutX="198.0" layoutY="188.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="225.0" style="-fx-background-color: #fffe;" text="Click Me" textFill="#722929" />
      <JFXButton fx:id="materialButton" layoutX="231.0" layoutY="82.0" prefHeight="54.0" prefWidth="139.0" style="-fx-background-color: #ffff;" textFill="#280c0c">
         <font>
            <Font size="25.0" />
         </font></JFXButton>
      <JFXTextField fx:id="textField" layoutX="233.0" layoutY="24.0" promptText="Enter UserName" />
   </children>
</AnchorPane>

1 Ответ

7 голосов
/ 28 апреля 2019

Об этой проблеме уже сообщалось в системе отслеживания проблем JFoenix:

Для начала, JFoenix не совсем готов к Java 11+. Выпущенная версия предназначена для Java 9, но она по-прежнему работает с Java 11 и JavaFX 11, при условии добавления зависимостей JavaFX.

Однако в JDK 12 он не запускается, и проблема не связана с JavaFX: даже с JavaFX 11.0.2 все равно происходит сбой.

Эта проблема связана с использованием отражение для доступа к узлу Text из TextFieldSkin:

textNode = ReflectionHelper.getFieldContent(TextFieldSkin.class, this, "textNode");
java.lang.IllegalAccessException: class com.jfoenix.adapters.ReflectionHelper (in module com.jfoenix) cannot access a member of class javafx.scene.control.skin.TextFieldSkin (in module javafx.controls) with modifiers "private"
        at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:355)
        at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:639)
        at java.base/java.lang.reflect.Field.checkAccess(Field.java:1075)
        at java.base/java.lang.reflect.Field.get(Field.java:416)
        at com.jfoenix/com.jfoenix.adapters.ReflectionHelper.getFieldContent(ReflectionHelper.java:98)
        at com.jfoenix/com.jfoenix.skins.JFXTextFieldSkin.<init>(JFXTextFieldSkin.java:59)

Хотя это работало нормально вплоть до Java 11.0.2, с Java 12 a регрессия недавние изменения в unsafe мешают этому работать и вызывают textNode = null.

Как @AlanBateman упоминает в своих комментариях ниже:

[Сопровождающим JFoenix] следует заменить свой метод setAccessible на вызов obj.setAccessible(true), чтобы пользователь получал правильные исключения, когда библиотека пытается взломать внутренние компоненты, которые ей недоступны. Если вы сделаете это, пользователь сможет обойти эти проблемы с опциями --add-exports или --add-opens, пока сопровождающие библиотеки не исправят свои проблемы.

Пока это будет означать придерживаться JDK 11.

В качестве альтернативы, вы можете попытаться создать свою собственную версию JFoenix, клонировать репозиторий (ветка 9.0.0) и внести необходимые изменения, чтобы он работал с JavaFX 11+ (выходит за рамки этого ответа ...), и по возможности исключая использование отражения.

Например, textNode можно напрямую получить с помощью:

textNode = textPane.getChildren().get(1);

или, по-прежнему полагайтесь на рефлексию, но с соответствующими упомянутыми изменениями:

try {
    Field field = cls.getDeclaredField(fieldName);
    field.setAccessible(true); // <-- Use this.
    return (T) field.get(obj);
} catch (Throwable ex) { }

в сочетании с:

--add-exports=javafx.controls/javafx.scene.control.skin=$moduleName
...