简体   繁体   English

ScrollPane中的FX:ID的JavaFX Access节点

[英]JavaFX Access nodes inside ScrollPane by FX:ID

One of my projects with JavaFX has a settings window with an ScrollPane in it. 我的一个使用JavaFX的项目中有一个带有ScrollPane的设置窗口。 There I have all the checkboxes, input fields and sliders. 那里有所有复选框,输入字段和滑块。

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

    <?import com.jfoenix.controls.JFXCheckBox?>
    <?import com.jfoenix.controls.JFXComboBox?>
    <?import com.jfoenix.controls.JFXSlider?>
    <?import com.jfoenix.controls.JFXTabPane?>
    <?import com.jfoenix.controls.JFXTextField?>
    <?import javafx.geometry.Insets?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.control.ScrollPane?>
    <?import javafx.scene.control.Tab?>
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.layout.StackPane?>
    <?import javafx.scene.layout.VBox?>

    <StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
       <children>
          <JFXTabPane rotateGraphic="true" side="BOTTOM">
             <tabs>
                <Tab closable="false" styleClass="container" text="%settings.tab.main">
                  <content>
                      <VBox prefHeight="200.0" prefWidth="100.0" spacing="20.0" styleClass="container">
                         <children>
                            <VBox prefHeight="200.0" prefWidth="100.0" spacing="15.0">
                               <children>
                                  <Label maxWidth="1.7976931348623157E308" text="%settings.language" />
                                  <JFXComboBox maxWidth="1.7976931348623157E308" promptText="%settings.language" />
                               </children>
                            </VBox>
                            <VBox layoutX="10.0" layoutY="10.0" prefHeight="200.0" prefWidth="100.0" spacing="15.0">
                               <children>
                                  <Label maxWidth="1.7976931348623157E308" text="%settings.window.width" />
                                  <JFXSlider majorTickUnit="50.0" max="1049.0" maxWidth="1.7976931348623157E308" min="850.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" />
                               </children>
                            </VBox>
                            <VBox layoutX="10.0" layoutY="210.0" prefHeight="200.0" prefWidth="100.0" spacing="15.0">
                               <children>
                                  <Label maxWidth="1.7976931348623157E308" text="%settings.window.height" />
                                  <JFXSlider majorTickUnit="50.0" max="900.0" maxWidth="1.7976931348623157E308" min="500.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" />
                               </children>
                            </VBox>
                            <VBox layoutX="10.0" layoutY="143.0" prefHeight="200.0" prefWidth="100.0" spacing="15.0">
                               <children>
                                  <JFXCheckBox maxWidth="1.7976931348623157E308" text="%settings.window.maximized" />
                               </children>
                            </VBox>
                         </children>
                         <padding>
                            <Insets bottom="30.0" left="30.0" right="30.0" top="30.0" />
                         </padding>
                      </VBox>
                  </content>
                </Tab>
                <Tab closable="false" styleClass="container" text="%settings.tab.exercises">
                   <content>
                      <ScrollPane fitToHeight="true" fitToWidth="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefViewportHeight="593.0" prefViewportWidth="600.0">
                         <content>
                            <VBox prefHeight="200.0" prefWidth="100.0" spacing="20.0" styleClass="container">
                               <children>
                                  <VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0">
                                     <children>
                                        <Label maxWidth="1.7976931348623157E308" text="%settings.add.ex" />
                                        <HBox maxWidth="1.7976931348623157E308" prefHeight="100.0" prefWidth="200.0">
                                           <children>
                                              <JFXCheckBox maxHeight="30.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" text="%settings.add" HBox.hgrow="ALWAYS" />
                                              <JFXTextField maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.add.min" HBox.hgrow="ALWAYS" />
                                              <JFXTextField maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.add.max" HBox.hgrow="ALWAYS" />
                                           </children>
                                        </HBox>
                                     </children>
                                  </VBox>
                                  <VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0">
                                     <children>
                                        <Label maxWidth="1.7976931348623157E308" text="%settings.sub.ex" />
                                        <HBox maxWidth="1.7976931348623157E308" prefHeight="100.0" prefWidth="200.0">
                                           <children>
                                              <JFXCheckBox maxHeight="30.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" text="%settings.sub" HBox.hgrow="ALWAYS" />
                                              <JFXTextField maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.sub.min" HBox.hgrow="ALWAYS" />
                                              <JFXTextField maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.sub.max" HBox.hgrow="ALWAYS" />
                                           </children>
                                        </HBox>
                                     </children>
                                  </VBox>
                                  <VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0">
                                     <children>
                                        <Label maxWidth="1.7976931348623157E308" text="%settings.mul.ex" />
                                        <HBox maxWidth="1.7976931348623157E308" prefHeight="100.0" prefWidth="200.0">
                                           <children>
                                              <JFXCheckBox maxHeight="30.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" text="%settings.mul" HBox.hgrow="ALWAYS" />
                                              <JFXTextField maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.mul.min" HBox.hgrow="ALWAYS" />
                                              <JFXTextField maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.mul.max" HBox.hgrow="ALWAYS" />
                                           </children>
                                        </HBox>
                                     </children>
                                  </VBox>
                                  <VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0">
                                     <children>
                                        <Label maxWidth="1.7976931348623157E308" text="%settings.div.ex" />
                                        <HBox maxWidth="1.7976931348623157E308" prefHeight="100.0" prefWidth="200.0">
                                           <children>
                                              <JFXCheckBox maxHeight="30.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" text="%settings.div" HBox.hgrow="ALWAYS" />
                                              <JFXTextField maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.div.min" HBox.hgrow="ALWAYS" />
                                              <JFXTextField maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.div.max" HBox.hgrow="ALWAYS" />
                                           </children>
                                        </HBox>
                                     </children>
                                  </VBox>
                                  <VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0">
                                     <children>
                                        <Label disable="true" maxWidth="1.7976931348623157E308" text="%settings.power.ex" />
                                        <HBox maxWidth="1.7976931348623157E308" prefHeight="100.0" prefWidth="200.0">
                                           <children>
                                              <JFXCheckBox disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" text="%settings.power" HBox.hgrow="ALWAYS" />
                                              <JFXTextField disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.power.min.base" HBox.hgrow="ALWAYS" />
                                              <JFXTextField disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.power.max.base" HBox.hgrow="ALWAYS" />
                                           </children>
                                        </HBox>
                                     </children>
                                  </VBox>
                                  <VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0">
                                     <children>
                                        <Label disable="true" maxWidth="1.7976931348623157E308" text="%settings.roots.ex" />
                                        <HBox maxWidth="1.7976931348623157E308" prefHeight="100.0" prefWidth="200.0">
                                           <children>
                                              <JFXCheckBox disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" text="%settings.roots" HBox.hgrow="ALWAYS" />
                                              <JFXTextField disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.roots.min.rad" HBox.hgrow="ALWAYS" />
                                              <JFXTextField disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.roots.max.rad" HBox.hgrow="ALWAYS" />
                                           </children>
                                        </HBox>
                                        <HBox layoutX="10.0" layoutY="37.0" maxWidth="1.7976931348623157E308" prefHeight="100.0" prefWidth="200.0">
                                           <children>
                                              <JFXCheckBox disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" prefWidth="150.0" text="%settings.roots.dec" HBox.hgrow="ALWAYS" />
                                              <JFXTextField disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.roots.min.expo" HBox.hgrow="ALWAYS" />
                                              <JFXTextField disable="true" maxHeight="30.0" maxWidth="1.7976931348623157E308" promptText="%settings.roots.max.expo" HBox.hgrow="ALWAYS" />
                                           </children>
                                        </HBox>
                                     </children>
                                  </VBox>
                                  <VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0">
                                     <children>
                                        <Label maxWidth="1.7976931348623157E308" text="%settings.count" />
                                     </children>
                                  </VBox>
                               </children>
                               <padding>
                                  <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
                               </padding>
                            </VBox>
                         </content>
                      </ScrollPane>
                   </content>
                </Tab>
             </tabs>
          </JFXTabPane>
       </children>
       <padding>
          <Insets top="50.0" />
       </padding>
    </StackPane>

To set the default value of these nodes I want the Java code to access each element with its FX:ID. 要设置这些节点的默认值,我希望Java代码使用其FX:ID访问每个元素。

package handlers;

import java.io.IOException;

import com.jfoenix.controls.JFXCheckBox;
import com.jfoenix.controls.JFXComboBox;
import com.jfoenix.controls.JFXSlider;
import com.jfoenix.controls.JFXSnackbar;
import com.jfoenix.controls.JFXTextField;

import initializers.InitSettings;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import resources.lang.Locales;
import settings.Settings;
import resources.lang.Language;

public class SettingsHandler {

    private static Scene scene;

    public static void setDefault(Scene scene) {
        SettingsHandler.scene = scene;

//      Replace the checkboxes' values with the values from the settings file (true or false)
        setCheckboxValue("add", Settings.add);
        setCheckboxValue("sub", Settings.sub);
        setCheckboxValue("mul", Settings.mul);
        setCheckboxValue("div", Settings.div);
        setCheckboxValue("subNeg", Settings.subNeg);
        setCheckboxValue("divDec", Settings.divComma);
        setCheckboxValue("windowMaximized", Settings.startMaximized);
        setCheckboxValue("automaticUpdates", Settings.automaticUpdates);

    private static void setCheckboxValue(String selector, boolean value) {
        ((JFXCheckBox) scene.lookup("#" + selector)).setSelected(value);
    }
}

But Java can't find the elements. 但是Java找不到元素。

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at handlers.SettingsHandler.setCheckboxValue(SettingsHandler.java:141)
    at handlers.SettingsHandler.setDefault(SettingsHandler.java:30)
    at initializers.InitSettings.init(InitSettings.java:25)
    at initializers.InitMain$2.handle(InitMain.java:66)
    at initializers.InitMain$2.handle(InitMain.java:60)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8411)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$355(GlassViewEventHandler.java:388)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)

All of my search queries on Google couldn't give me the right information. 我在Google上的所有搜索查询都无法为我提供正确的信息。 I just got more and more tutorials of how to create a ScrollPane. 我刚刚获得了有关如何创建ScrollPane的越来越多的教程。 So I'm asking you: How can I access the elements inside the ScrollPane. 所以我问你:我如何访问ScrollPane内部的元素。

The content simply has not been added to the scene graph, since the ScrollPane has not been layouted and therefore the skin that would add the ScrollPane content to the scene graph has not yet been created. 由于尚未布局ScrollPane ,因此尚未将内容添加到场景图,因此尚未创建将ScrollPane内容添加到场景图的skin

This code demonstrates this behaviour: 这段代码演示了这种行为:

@Override
public void start(Stage primaryStage) {
    Rectangle content = new Rectangle(100, 100);
    content.setId("id");
    ScrollPane sp = new ScrollPane(content);

    System.out.println("before: "+sp.lookup("#id")); // null

    Scene scene = new Scene(sp);

    // do layout (sp needs to be added to a scene for this to work)
    sp.applyCss();
    sp.layout();

    System.out.println("after: "+sp.lookup("#id")); // non-null

    primaryStage.setScene(scene);
    primaryStage.show();
}

It's a bad idea to identify the nodes using lookup in most cases anyway. 无论如何,在大多数情况下使用lookup来标识节点是一个坏主意。 Better use a controller or at least use the namespace of the FXMLLoader instance used to load the fxml to access the objects using the fx:id s. 最好使用控制器,或者至少使用FXMLLoader实例的namespace ,该实例用于加载fxml以使用fx:id访问对象。

Note: It would also probably be helpful to actually specify the fx:id attributes in the fxml file. 注意:在fxml文件中实际指定fx:id属性也可能会有所帮助。 Otherwise you won't find any matches even after layout. 否则,即使在布局后也找不到任何匹配项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM