पासिंग पैरामीटर JavaFX FXML


194

मैं javafx में एक माध्यमिक विंडो में पैरामीटर कैसे पारित कर सकता हूं? क्या संबंधित नियंत्रक के साथ संवाद करने का कोई तरीका है?

उदाहरण के लिए: उपयोगकर्ता एक ग्राहक को चुनता है TableViewऔर ग्राहक की जानकारी दिखाते हुए एक नई विंडो खोली जाती है।

Stage newStage = new Stage();
try 
{
    AnchorPane page = (AnchorPane) FXMLLoader.load(HectorGestion.class.getResource(fxmlResource));
    Scene scene = new Scene(page);
    newStage.setScene(scene);
    newStage.setTitle(windowTitle);
    newStage.setResizable(isResizable);
    if(showRightAway) 
    {
        newStage.show();
    }
}

newStageनई विंडो होगी। समस्या यह है, मुझे नियंत्रक को यह बताने का कोई तरीका नहीं मिल सकता है कि ग्राहक की जानकारी कहाँ से देखें (आईडी को पैरामीटर के रूप में पास करके)।

कोई विचार?


यह देखने के लिए जांचें कि क्या यह भी काम करता है: stackoverflow.com/questions/14370183/…
डायनेलाइट

@ अलवरो: क्या आपको अपना समाधान मिल गया? क्या आप पैरामीटर पास कर सकते हैं? एक नियंत्रक से दूसरे नियंत्रक फ़ाइल में?
जावा मैन

3
हाँ। जवाहरात ने एक पुस्तक-स्तरीय स्पष्टीकरण दिया। इसलिए मैंने उसका जवाब स्वीकार किया
अल्वारो

जवाबों:


276

अनुशंसित दृष्टिकोण

यह उत्तर एफएक्सएमएल नियंत्रकों के लिए मापदंडों को पारित करने के लिए विभिन्न तंत्रों की गणना करता है।

छोटे अनुप्रयोगों के लिए मैं अत्यधिक कॉल करने वाले से नियंत्रक तक सीधे मापदंडों को पारित करने की सलाह देता हूं - यह सरल, सीधा है और इसके लिए कोई अतिरिक्त रूपरेखा की आवश्यकता नहीं है।

यदि आप अपने आवेदन के भीतर निर्भरता इंजेक्शन या इवेंट बस तंत्र का उपयोग करना चाहते हैं, तो बड़े, अधिक जटिल अनुप्रयोगों के लिए, यह सार्थक जांच होगी ।

पास करने वाले पैरामीटर को सीधे कॉल करने वाले से नियंत्रक के पास भेज दिया जाता है

कस्टम डेटा को FXML लोडर उदाहरण से कंट्रोलर को पुनः प्राप्त करके और आवश्यक डेटा मानों के साथ इसे आरंभ करने के लिए कंट्रोलर पर एक विधि को कॉल करके एक FXML कंट्रोलर को पास करें।

निम्नलिखित कोड की तरह कुछ:

public Stage showCustomerDialog(Customer customer) {
  FXMLLoader loader = new FXMLLoader(
    getClass().getResource(
      "customerDialog.fxml"
    )
  );

  Stage stage = new Stage(StageStyle.DECORATED);
  stage.setScene(
    new Scene(
      (Pane) loader.load()
    )
  );

  CustomerDialogController controller = 
    loader.<CustomerDialogController>getController();
  controller.initData(customer);

  stage.show();

  return stage;
}

...

class CustomerDialogController {
  @FXML private Label customerName;
  void initialize() {}
  void initData(Customer customer) {
    customerName.setText(customer.getName());
  }
}

नमूना कोड में दिखाए गए अनुसार एक नया FXMLLoader का निर्माण किया जाता है new FXMLLoader(location)। स्थान एक URL है और आप FXML संसाधन से ऐसा URL उत्पन्न कर सकते हैं:

new FXMLLoader(getClass().getResource("sample.fxml"));

FXMLLoader पर स्थिर लोड फ़ंक्शन का उपयोग करने के लिए सावधान रहें, या आप अपने लोडर उदाहरण से अपने नियंत्रक को प्राप्त करने में सक्षम नहीं होंगे।

FXMLLoader उदाहरण खुद को डोमेन ऑब्जेक्ट्स के बारे में कभी नहीं जानते हैं। आप सीधे FXMLLoader कंस्ट्रक्टर में एप्लिकेशन विशिष्ट डोमेन ऑब्जेक्ट पास नहीं करते हैं, इसके बजाय आप:

  1. एक निर्दिष्ट स्थान पर fxml मार्कअप पर आधारित एक FXMLLoader का निर्माण करें
  2. FXMLLoader उदाहरण से एक नियंत्रक प्राप्त करें।
  3. डोमेन ऑब्जेक्ट के संदर्भ के साथ नियंत्रक प्रदान करने के लिए पुनर्प्राप्त नियंत्रक पर तरीकों को लागू करें।

यह ब्लॉग (एक अन्य लेखक द्वारा) एक वैकल्पिक, लेकिन समान, उदाहरण प्रदान करता है ।

FXMLLoader पर एक नियंत्रक सेट करना

CustomerDialogController dialogController = 
    new CustomerDialogController(param1, param2);

FXMLLoader loader = new FXMLLoader(
    getClass().getResource(
        "customerDialog.fxml"
    )
);
loader.setController(dialogController);

Pane mainPane = (Pane) loader.load();

आप कोड में एक नया नियंत्रक का निर्माण कर सकते हैं, जो आप अपने कॉलर से नियंत्रक पैरामीटर में चाहते हैं किसी भी पैरामीटर को पारित करना। एक बार जब आप एक नियंत्रक का निर्माण कर लेते हैं, तो आप आवृत्ति विधि लागू करने से पहले इसे एक FXMLLoader उदाहरण पर सेट कर सकते हैं ।load()

लोडर पर एक नियंत्रक सेट करने के लिए (JavaFX 2.x में) आप fx:controllerअपने fxml फ़ाइल में एक विशेषता को भी परिभाषित नहीं कर सकते ।

fx:controllerएफएक्सएमएल में परिभाषा पर सीमा के कारण , मैं व्यक्तिगत रूप से एफएक्सएमएलएलडियर से नियंत्रक प्राप्त करने के बजाय एफएक्सएमएलएलडियर से नियंत्रक प्राप्त करना पसंद करता हूं।

एक बाहरी स्टेटिक विधि से नियंत्रक को पुनः प्राप्त करना

इस विधि को सर्जेई द्वारा Javafx 2.0 के लिए कैसे-कैसे Application.getParameters () के लिए एक Controller.java फ़ाइल में जवाब दिया गया है

डिपेंडेंसी इंजेक्शन का प्रयोग करें

FXMLLoader आपको एक कस्टम कंट्रोलर फ़ैक्टरी को FXMLLoader पर सेट करने की अनुमति देकर गुइसे, स्प्रिंग या जावा EE CDI जैसी निर्भरता इंजेक्शन सिस्टम का समर्थन करता है। यह एक कॉलबैक प्रदान करता है जिसका उपयोग आप संबंधित निर्भरता इंजेक्शन प्रणाली द्वारा इंजेक्ट किए गए निर्भर मूल्यों के साथ नियंत्रक उदाहरण बनाने के लिए कर सकते हैं।

वसंत के साथ जावाएफ़एक्स एप्लिकेशन और नियंत्रक निर्भरता इंजेक्शन का एक उदाहरण निम्नलिखित में दिया गया है:

एक वास्तव में अच्छा, स्वच्छ निर्भरता इंजेक्शन दृष्टिकोण एक नमूना एयर-हैक्स एप्लिकेशन के साथ afterburner.fx फ्रेमवर्क द्वारा इसका उपयोग करने की छूट है। afterburner.fx निर्भरता इंजेक्शन करने के लिए JEE6 javax.inject पर निर्भर करता है ।

एक इवेंट बस का उपयोग करें

ग्रेग ब्राउन, मूल एफएक्सएमएल विनिर्देश निर्माता और कार्यान्वयनकर्ता, अक्सर एफएक्सएमएल इंस्टेंटिएटेड नियंत्रकों और अन्य एप्लिकेशन लॉजिक के बीच संचार के लिए एक इवेंट बस जैसे कि अमरूद इवेंटबस के उपयोग पर विचार करने का सुझाव देते हैं ।

ईवेंटबस एनोटेशन के साथ एक सरल लेकिन शक्तिशाली प्रकाशन / सदस्यता एपीआई है जो पीओजेओ को एक दूसरे के साथ संदर्भित किए बिना जेवीएम में कहीं भी एक दूसरे के साथ संवाद करने की अनुमति देता है।

अनुवर्ती प्रश्नोत्तर

पहली विधि पर, आप स्टेज क्यों लौटाते हैं? विधि शून्य भी हो सकती है क्योंकि आप पहले से ही कमांड शो () दे रहे हैं; वापसी के चरण से पहले ;। आप स्टेज को वापस करके उपयोग की योजना कैसे बनाते हैं

यह एक समस्या का एक कार्यात्मक समाधान है। showCustomerDialogफ़ंक्शन से एक चरण लौटाया जाता है ताकि इसका एक संदर्भ एक बाहरी वर्ग द्वारा संग्रहीत किया जा सके जो कुछ करने की इच्छा कर सकता है, जैसे कि बाद में मुख्य विंडो में एक बटन क्लिक पर आधारित चरण को छिपाएं। एक वैकल्पिक, ऑब्जेक्ट-ओरिएंटेड समाधान एक CustomerDialog ऑब्जेक्ट के अंदर कार्यक्षमता और स्टेज रेफ़रेंस को इनकैप कर सकता है या कस्टमरडायलॉग रेंज स्टेज कर सकता है। एफएक्सएमएल, नियंत्रक और मॉडल डेटा को घेरने वाले कस्टम संवाद के लिए ऑब्जेक्ट-ओरिएंटेड इंटरफ़ेस के लिए एक पूर्ण उदाहरण इस उत्तर के दायरे से परे है, लेकिन किसी को भी बनाने के लिए इच्छुक ब्लॉग पोस्ट बना सकता है।


@Dzim नाम के StackOverflow उपयोगकर्ता द्वारा आपूर्ति की गई अतिरिक्त जानकारी

स्प्रिंग बूट डिपेंडेंसी इंजेक्शन के लिए उदाहरण

इसे "द स्प्रिंग बूट वे" कैसे किया जाए, इस सवाल पर JavaFX 2 के बारे में चर्चा हुई, जिसे मैंने संलग्न पर्मलिंक में शामिल किया। स्प्रिंग बूट v1.3.3 पर मार्च 2016 में दृष्टिकोण अभी भी मान्य है और परीक्षण किया गया है। कृपया ध्यान दें: https://stackoverflow.com/a/36310391/1281217


कभी-कभी, आप कॉलर को वापस परिणाम देना चाहते हैं, जिस स्थिति में आप संबंधित प्रश्न का उत्तर देख सकते हैं:


FXMLLoader कन्स्ट्रक्टर केवल URL को पैरामीटर के रूप में लेते हैं .. FXMLLoader को इंस्टेंट करने का सही तरीका क्या है?
अल्वारो

1
इवेंट बस वेबसाइट में कहा गया है, "अपडेट 3/2013: ईवेंटबस बासी हो गया है ..."
j

1
डेटाएफएक्स कंट्रोलर फ्रेमवर्क एफएक्सएमएल नियंत्रकों के लिए कुछ इंजेक्शन का समर्थन प्रदान करता है: guigarage.com/2013/12/datafx-controller-framework-preview
हेन्ड्रिक एबर्स

2
@Anarkie
jewelsea

7
JavaFx में इस छोटे से काम को करने के लिए गॉडशेक कुछ सरल है? कंस्ट्रक्टर और javafx में डेटा पास करने के लिए इसकी एक बहुत ही सामान्य विशेषता यह है कि सभी चीजों को एक साथ केवल एक नाम या एक मूल्य भेजने के लिए इस नरक की आवश्यकता होती है?
ज़हान सफ़लवा

13

मुझे लगता है कि यह एक बहुत पुरानी पोस्ट है और पहले से ही कुछ शानदार जवाब हैं, लेकिन मैं इस तरह के एक दृष्टिकोण को प्रदर्शित करने के लिए एक सरल MCVE बनाना चाहता था और नए कोडर्स को तुरंत कार्रवाई में अवधारणा को देखने का एक तरीका देता हूं।

इस उदाहरण में, हम 5 फ़ाइलों का उपयोग करेंगे:

  1. Main.java - बस आवेदन शुरू करने और पहले नियंत्रक को कॉल करने के लिए उपयोग किया जाता है।
  2. Controller1.java 1. जावा - पहला एफएक्सएमएल लेआउट के लिए नियंत्रक।
  3. Controller2.java 2. जावा - दूसरा एफएक्सएमएल लेआउट के लिए नियंत्रक।
  4. Layout1.fxml - पहले दृश्य के लिए FXML लेआउट।
  5. Layout2.fxml - दूसरे दृश्य के लिए FXML लेआउट।

इस पद के नीचे सभी फाइलें अपनी संपूर्णता में सूचीबद्ध हैं।

लक्ष्य: करने के Controller1लिए Controller2और इसके विपरीत से गुजर मूल्यों का प्रदर्शन करने के लिए ।

कार्यक्रम का प्रवाह:

  • पहले दृश्य में ए TextField, ए Buttonऔर ए शामिल हैं Label। जबButton क्लिक किया जाता है, तो दूसरी विंडो लोड होती है और प्रदर्शित होती है, जिसमें पाठ दर्ज किया जाता है TextField
  • दूसरे दृश्य के भीतर, ए TextField, ए Buttonऔर ए भी है LabelLabelपाठ में दर्ज किया गया प्रदर्शित करेगा TextFieldपहला दृश्य पर।
  • दूसरे दृश्य में पाठ दर्ज करने TextFieldऔर उसके क्लिक करने पर Button, पहले दृश्य Labelको दर्ज किए गए पाठ को दिखाने के लिए अद्यतन किया जाता है।

यह एक बहुत ही सरल प्रदर्शन है और निश्चित रूप से कुछ सुधार के लिए खड़ा हो सकता है, लेकिन अवधारणा को बहुत स्पष्ट करना चाहिए।

कोड स्वयं भी कुछ विवरणों के साथ टिप्पणी करता है कि क्या हो रहा है और कैसे हो रहा है।

कोड

Main.java:

import javafx.application.Application;
import javafx.stage.Stage;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // Create the first controller, which loads Layout1.fxml within its own constructor
        Controller1 controller1 = new Controller1();

        // Show the new stage
        controller1.showStage();

    }
}

Controller1.java:

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

import java.io.IOException;

public class Controller1 {

    // Holds this controller's Stage
    private final Stage thisStage;

    // Define the nodes from the Layout1.fxml file. This allows them to be referenced within the controller
    @FXML
    private TextField txtToSecondController;
    @FXML
    private Button btnOpenLayout2;
    @FXML
    private Label lblFromController2;

    public Controller1() {

        // Create the new stage
        thisStage = new Stage();

        // Load the FXML file
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout1.fxml"));

            // Set this class as the controller
            loader.setController(this);

            // Load the scene
            thisStage.setScene(new Scene(loader.load()));

            // Setup the window/stage
            thisStage.setTitle("Passing Controllers Example - Layout1");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Show the stage that was loaded in the constructor
     */
    public void showStage() {
        thisStage.showAndWait();
    }

    /**
     * The initialize() method allows you set setup your scene, adding actions, configuring nodes, etc.
     */
    @FXML
    private void initialize() {

        // Add an action for the "Open Layout2" button
        btnOpenLayout2.setOnAction(event -> openLayout2());
    }

    /**
     * Performs the action of loading and showing Layout2
     */
    private void openLayout2() {

        // Create the second controller, which loads its own FXML file. We pass a reference to this controller
        // using the keyword [this]; that allows the second controller to access the methods contained in here.
        Controller2 controller2 = new Controller2(this);

        // Show the new stage/window
        controller2.showStage();

    }

    /**
     * Returns the text entered into txtToSecondController. This allows other controllers/classes to view that data.
     */
    public String getEnteredText() {
        return txtToSecondController.getText();
    }

    /**
     * Allows other controllers to set the text of this layout's Label
     */
    public void setTextFromController2(String text) {
        lblFromController2.setText(text);
    }
}

Controller2.java:

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

import java.io.IOException;

public class Controller2 {

    // Holds this controller's Stage
    private Stage thisStage;

    // Will hold a reference to the first controller, allowing us to access the methods found there.
    private final Controller1 controller1;

    // Add references to the controls in Layout2.fxml
    @FXML
    private Label lblFromController1;
    @FXML
    private TextField txtToFirstController;
    @FXML
    private Button btnSetLayout1Text;

    public Controller2(Controller1 controller1) {
        // We received the first controller, now let's make it usable throughout this controller.
        this.controller1 = controller1;

        // Create the new stage
        thisStage = new Stage();

        // Load the FXML file
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout2.fxml"));

            // Set this class as the controller
            loader.setController(this);

            // Load the scene
            thisStage.setScene(new Scene(loader.load()));

            // Setup the window/stage
            thisStage.setTitle("Passing Controllers Example - Layout2");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Show the stage that was loaded in the constructor
     */
    public void showStage() {
        thisStage.showAndWait();
    }

    @FXML
    private void initialize() {

        // Set the label to whatever the text entered on Layout1 is
        lblFromController1.setText(controller1.getEnteredText());

        // Set the action for the button
        btnSetLayout1Text.setOnAction(event -> setTextOnLayout1());
    }

    /**
     * Calls the "setTextFromController2()" method on the first controller to update its Label
     */
    private void setTextOnLayout1() {
        controller1.setTextFromController2(txtToFirstController.getText());
    }

}

Layout1.fxml:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <VBox alignment="CENTER" spacing="10.0">
        <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
        </padding>
        <Label style="-fx-font-weight: bold;" text="This is Layout1!"/>
        <HBox alignment="CENTER_LEFT" spacing="10.0">
            <Label text="Enter Text:"/>
            <TextField fx:id="txtToSecondController"/>
            <Button fx:id="btnOpenLayout2" mnemonicParsing="false" text="Open Layout2"/>
        </HBox>
        <VBox alignment="CENTER">
            <Label text="Text From Controller2:"/>
            <Label fx:id="lblFromController2" text="Nothing Yet!"/>
        </VBox>
    </VBox>
</AnchorPane>

Layout2.fxml:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <VBox alignment="CENTER" spacing="10.0">
        <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
        </padding>
        <Label style="-fx-font-weight: bold;" text="Welcome to Layout 2!"/>
        <VBox alignment="CENTER">
            <Label text="Text From Controller1:"/>
            <Label fx:id="lblFromController1" text="Nothing Yet!"/>
        </VBox>
        <HBox alignment="CENTER_LEFT" spacing="10.0">
            <Label text="Enter Text:"/>
            <TextField fx:id="txtToFirstController"/>
            <Button fx:id="btnSetLayout1Text" mnemonicParsing="false" text="Set Text on Layout1"/>
        </HBox>
    </VBox>
</AnchorPane>

1
क्या एफएक्सएमएल फ़ाइल में नियंत्रक को सेट करना संभव है? Beause लाइन को हटाने: loader.setController(this)और एफएक्सएमएल फ़ाइल में नियंत्रक को जोड़ने से एप्लिकेशन क्रैश हो जाता है
हॉफचैट

1
नहीं अगर FXML नियंत्रक के भीतर से लोड किया गया है। यदि आप एफएक्सएमएल को मुख्य वर्ग से लोड करते हैं, उदाहरण के लिए, आप एफएक्सएमएल फ़ाइल में नियंत्रक को परिभाषित कर सकते हैं और इसका उपयोग करके एक संदर्भ प्राप्त कर सकते हैंloader.getController()
Zephyr

अंत में मैं एक समाधान खोजने में कामयाब रहा, महान उदाहरण। मैंने इसे अपने प्रोजेक्ट में लागू किया और अब मैं कोशिश कर रहा हूं कि दोनों खिड़कियां एक साथ खुली हों और उनमें से पहली बार मोडल बनाया जाए। दुर्भाग्य से केवल एक ही खुलता है। किसी को भी इसके साथ मदद कर सकता है?
jabba

8

javafx.scene.Node क्लास में विधियों की एक जोड़ी है setUserData (ऑब्जेक्ट) और ऑब्जेक्ट getUserData ()

जिसका उपयोग आप अपनी जानकारी को नोड में जोड़ने के लिए कर सकते हैं।

तो, आप page.setUserData (जानकारी) को कॉल कर सकते हैं;

और नियंत्रक जाँच कर सकता है, यदि जानकारी सेट है। इसके अलावा, यदि आवश्यक हो, तो आप बैक-फॉरवर्ड डेटा ट्रांसफर के लिए ऑब्जेक्टप्रोपर्टी का उपयोग कर सकते हैं।

यहां एक दस्तावेज़ देखें: http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html वाक्यांश "पहले संस्करण में, हैंडलबूटनएशन () @FXML के साथ टैग किया गया है। कंट्रोलर के दस्तावेज़ में परिभाषित मार्कअप को अनुमति देने के लिए। दूसरे उदाहरण में, लोडर को उसका मान सेट करने की अनुमति देने के लिए बटन फ़ील्ड को एनोटेट किया गया है। इनिशियलाइज़ () विधि इसी तरह एनोटेट है। "

तो, आपको एक नोड के साथ एक नियंत्रक को जोड़ने की जरूरत है, और नोड के लिए एक उपयोगकर्ता डेटा सेट करें।


Stage.getScene () -> Scene.getRoot () -> Parent.getChildrenUnmodifiable () के साथ पुनरावर्ती खोज। यह बहुत गंदा तरीका है। अगर कोई बेहतर तरीके से smth का सुझाव दे सकता है - जो बहुत अच्छा होगा।
अलेक्जेंडर किरोव

ऐसा लगता है कि Stage.getScene ()। GetRoot () सही तरीका है! साभार
अलवरो

7

यहाँ नामस्थान के माध्यम से एक fxml दस्तावेज़ के मापदंडों को पारित करने के लिए एक उदाहरण है।

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/null" xmlns:fx="http://javafx.com/fxml/1">
    <BorderPane>
        <center>
            <Label text="$labelText"/>
        </center>
    </BorderPane>
</VBox>

External Textनाम स्थान चर के लिए मान को परिभाषित करें labelText:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class NamespaceParameterExampleApplication extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws IOException {
        final FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("namespace-parameter-example.fxml"));

        fxmlLoader.getNamespace()
                  .put("labelText", "External Text");

        final Parent root = fxmlLoader.load();

        primaryStage.setTitle("Namespace Parameter Example");
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }
}

ऐसा लगता है कि कुछ सुझाव दिए आंतरिक रूप से उपयोग किया जाता है: उदाहरण के लिए FXMLLoader.CONTROLLER_KEYWORD, FXMLLoader.LOCATION_KEY, FXMLLoader.RESOURCES_KEYऔर किसी भी स्ट्रिंग के लिए मूल्य के रूप में इस्तेमाल fx:idविशेषता।
फ़ेबियन

इसके लिए धन्यवाद, मेरा अन्य दृश्य सिर्फ एक कंटेनर है जो पहले मेरे मुख्य दृश्य पर दिखाए गए पाठ को दिखाता है। अब मेरे पास एक एफएक्सएमएल हो सकता है जिसे मैं नेमस्पेस वैरिएबल के माध्यम से सामग्री को इनिशियलाइज़ करके कई स्थानों पर पुन: उपयोग कर सकता हूं। मुझे कोई नया तरीका नहीं बनाना है या अपने निर्माता या initalisers को बदलना है - मेरे FXML में सिर्फ एडवर्ड चर और मुख्य नियंत्रक में मेरे fxmloader कोड में एक पंक्ति जोड़ें।
SystemsInCode

4

यह काम ..

याद रखें पहली बार जब आप गुजरने वाले मूल्य को प्रिंट करते हैं तो आपको अशक्त हो जाएगा, आप इसे अपनी खिड़कियों के लोड होने के बाद उपयोग कर सकते हैं, वही सब कुछ जो आप किसी अन्य घटक के लिए कोड करना चाहते हैं।

पहला नियंत्रक

try {
    Stage st = new Stage();
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/inty360/free/form/MainOnline.fxml"));

    Parent sceneMain = loader.load();

    MainOnlineController controller = loader.<MainOnlineController>getController();
    controller.initVariable(99L);

    Scene scene = new Scene(sceneMain);
    st.setScene(scene);
    st.setMaximized(true);
    st.setTitle("My App");
    st.show();
} catch (IOException ex) {
    Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex);
}

एक और नियंत्रक

public void initVariable(Long id_usuario){
    this.id_usuario = id_usuario;
    label_usuario_nombre.setText(id_usuario.toString());
}

1
यह कार्य जब आप पहले नियंत्रक से दूसरे में पैरामीटर पास करते हैं, लेकिन दूसरे से पहले नियंत्रक से पैरामीटर कैसे पारित करते हैं, तो मेरा मतलब है कि पहले के बाद। Fxml लोड किया गया था।
मेनई अला एडडिन - अलादीन

@XlintXms संबंधित प्रश्न को जावा एक्सएक्सएक्सएक्सएल पैरामीटर नियंत्रक ए से बी और पीछे से गुजरते हुए देखते हैं , जो आपके अतिरिक्त प्रश्न को संबोधित करता है।
गहने

2

आपको एक Context Class बनाना होगा।

public class Context {
    private final static Context instance = new Context();
    public static Context getInstance() {
        return instance;
    }

    private Connection con;
    public void setConnection(Connection con)
    {
        this.con=con;
    }
    public Connection getConnection() {
        return con;
    }

    private TabRoughController tabRough;
    public void setTabRough(TabRoughController tabRough) {
        this.tabRough=tabRough;
    }

    public TabRoughController getTabRough() {
        return tabRough;
    }
}

आपको उपयोग करते हुए आरंभीकरण में नियंत्रक का उदाहरण सेट करना होगा

Context.getInstance().setTabRough(this);

और आप इसे सिर्फ उपयोग करके अपने पूरे एप्लिकेशन से उपयोग कर सकते हैं

TabRoughController cont=Context.getInstance().getTabRough();

अब आप पूरे एप्लिकेशन से किसी भी नियंत्रक को पैरामीटर पास कर सकते हैं।


हम इस दृष्टिकोण का उपयोग करते हैं और यह बहुत अच्छा काम करता है। मुझे पसंद है कि मेरे पास कंस्ट्रक्टर के अंदर या इनिशियलाइज़ मेथड में डेटा है और मुझे इसके निर्माण के बाद कंट्रोलर में डेटा सेट नहीं करना है
Bob

1

हाँ तुम कर सकते हो।
आपको पहले नियंत्रक में जोड़ना होगा:

YourController controller = loader.getController();     
controller.setclient(client);

फिर दूसरे में एक ग्राहक घोषित करें, फिर अपने नियंत्रक के नीचे:

public void setclien(Client c) {
    this.client = c;
}

0

यहां एक नियंत्रक का उपयोग करने के लिए एक उदाहरण है जो गुइसे द्वारा इंजेक्ट किया गया है।

/**
 * Loads a FXML file and injects its controller from the given Guice {@code Provider}
 */
public abstract class GuiceFxmlLoader {

   public GuiceFxmlLoader(Stage stage, Provider<?> provider) {
      mStage = Objects.requireNonNull(stage);
      mProvider = Objects.requireNonNull(provider);
   }

   /**
    * @return the FXML file name
    */
   public abstract String getFileName();

   /**
    * Load FXML, set its controller with given {@code Provider}, and add it to {@code Stage}.
    */
   public void loadView() {
      try {
         FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource(getFileName()));
         loader.setControllerFactory(p -> mProvider.get());
         Node view = loader.load();
         setViewInStage(view);
      }
      catch (IOException ex) {
         LOGGER.error("Failed to load FXML: " + getFileName(), ex);
      }
   }

   private void setViewInStage(Node view) {
      BorderPane pane = (BorderPane)mStage.getScene().getRoot();
      pane.setCenter(view);
   }

   private static final Logger LOGGER = Logger.getLogger(GuiceFxmlLoader.class);

   private final Stage mStage;
   private final Provider<?> mProvider;
}

यहाँ लोडर का एक ठोस कार्यान्वयन है:

public class ConcreteViewLoader extends GuiceFxmlLoader {

   @Inject
   public ConcreteViewLoader(Stage stage, Provider<MyController> provider) {
      super(stage, provider);
   }

   @Override
   public String getFileName() {
      return "my_view.fxml";
   }
}

ध्यान दें कि यह उदाहरण एक बोर्डरपैन के केंद्र में दृश्य को लोड करता है जो स्टेज में दृश्य की जड़ है। यह उदाहरण के लिए अप्रासंगिक है (मेरे विशिष्ट उपयोग के मामले का कार्यान्वयन विवरण) लेकिन इसे छोड़ने का फैसला किया क्योंकि कुछ को यह उपयोगी लग सकता है।


-1

आप सार्वजनिक डेटा को संग्रहीत करने के लिए एक सार्वजनिक अवलोकन सूची का उपयोग करने का निर्णय ले सकते हैं, या डेटा को संग्रहीत करने और संबंधित नियंत्रक से पुनर्प्राप्त करने के लिए एक सार्वजनिक सेटर विधि बना सकते हैं


-3

6 साल पुराने प्रश्न का उत्तर क्यों दें?
किसी भी प्रोग्रामिंग भाषा के साथ काम करने वाली सबसे मौलिक अवधारणाएं हैं कि कैसे एक (विंडो, फॉर्म या पेज) से दूसरे में नेविगेट किया जाए। इस नेविगेशन को करते समय डेवलपर अक्सर एक (विंडो, फॉर्म या पेज) से डेटा पास करना चाहता है और पास किए गए डेटा को प्रदर्शित करता है या उपयोग करता है
जबकि यहां दिए गए अधिकांश उत्तर उत्कृष्ट उदाहरणों को अच्छे से प्रदान करते हैं कि कैसे हमने सोचा कि हम इसे पूरा करेंगे। एक पायदान या दो या तीन
हमने तीन इसलिए कहा क्योंकि हम तीन (विंडो, फॉर्म या पेज) के बीच नेविगेट करेंगे और (विंडो, फॉर्म या पेज) के आसपास डेटा पास करने के लिए स्टेटिक वैरिएबल के कॉन्सेप्ट का उपयोग
करेंगे। हम कुछ निर्णय लेने वाले कोड को भी शामिल करेंगे, जबकि हम नेविगेट करते हैं

public class Start extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        // This is MAIN Class which runs first
        Parent root = FXMLLoader.load(getClass().getResource("start.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.setResizable(false);// This sets the value for all stages
        stage.setTitle("Start Page"); 
        stage.show();
        stage.sizeToScene();
    }

    public static void main(String[] args) {
        launch(args);
    } 
}

नियंत्रक प्रारंभ करें

public class startController implements Initializable {

@FXML Pane startPane,pageonePane;
@FXML Button btnPageOne;
@FXML TextField txtStartValue;
public Stage stage;
public static int intSETonStartController;
String strSETonStartController;

@FXML
private void toPageOne() throws IOException{

    strSETonStartController = txtStartValue.getText().trim();


        // yourString != null && yourString.trim().length() > 0
        // int L = testText.length();
        // if(L == 0){
        // System.out.println("LENGTH IS "+L);
        // return;
        // }
        /* if (testText.matches("[1-2]") && !testText.matches("^\\s*$")) 
           Second Match is regex for White Space NOT TESTED !
        */

        String testText = txtStartValue.getText().trim();
        // NOTICE IF YOU REMOVE THE * CHARACTER FROM "[1-2]*"
        // NO NEED TO CHECK LENGTH it also permited 12 or 11 as valid entry 
        // =================================================================
        if (testText.matches("[1-2]")) {
            intSETonStartController = Integer.parseInt(strSETonStartController);
        }else{
            txtStartValue.setText("Enter 1 OR 2");
            return;
        }

        System.out.println("You Entered = "+intSETonStartController);
        stage = (Stage)startPane.getScene().getWindow();// pane you are ON
        pageonePane = FXMLLoader.load(getClass().getResource("pageone.fxml"));// pane you are GOING TO
        Scene scene = new Scene(pageonePane);// pane you are GOING TO
        stage.setScene(scene);
        stage.setTitle("Page One"); 
        stage.show();
        stage.sizeToScene();
        stage.centerOnScreen();  
}

private void doGET(){
    // Why this testing ?
    // strSENTbackFROMPageoneController is null because it is set on Pageone
    // =====================================================================
    txtStartValue.setText(strSENTbackFROMPageoneController);
    if(intSETonStartController == 1){
      txtStartValue.setText(str);  
    }
    System.out.println("== doGET WAS RUN ==");
    if(txtStartValue.getText() == null){
       txtStartValue.setText("");   
    }
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    // This Method runs every time startController is LOADED
     doGET();
}    
}

पेज एक नियंत्रक

public class PageoneController implements Initializable {

@FXML Pane startPane,pageonePane,pagetwoPane;
@FXML Button btnOne,btnTwo;
@FXML TextField txtPageOneValue;
public static String strSENTbackFROMPageoneController;
public Stage stage;

    @FXML
private void onBTNONE() throws IOException{

        stage = (Stage)pageonePane.getScene().getWindow();// pane you are ON
        pagetwoPane = FXMLLoader.load(getClass().getResource("pagetwo.fxml"));// pane you are GOING TO
        Scene scene = new Scene(pagetwoPane);// pane you are GOING TO
        stage.setScene(scene);
        stage.setTitle("Page Two"); 
        stage.show();
        stage.sizeToScene();
        stage.centerOnScreen();
}

@FXML
private void onBTNTWO() throws IOException{
    if(intSETonStartController == 2){
        Alert alert = new Alert(AlertType.CONFIRMATION);
        alert.setTitle("Alert");
        alert.setHeaderText("YES to change Text Sent Back");
        alert.setResizable(false);
        alert.setContentText("Select YES to send 'Alert YES Pressed' Text Back\n"
                + "\nSelect CANCEL send no Text Back\r");// NOTE this is a Carriage return\r
        ButtonType buttonTypeYes = new ButtonType("YES");
        ButtonType buttonTypeCancel = new ButtonType("CANCEL", ButtonData.CANCEL_CLOSE);

        alert.getButtonTypes().setAll(buttonTypeYes, buttonTypeCancel);

        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == buttonTypeYes){
            txtPageOneValue.setText("Alert YES Pressed");
        } else {
            System.out.println("canceled");
            txtPageOneValue.setText("");
            onBack();// Optional
        }
    }
}

@FXML
private void onBack() throws IOException{

    strSENTbackFROMPageoneController = txtPageOneValue.getText();
    System.out.println("Text Returned = "+strSENTbackFROMPageoneController);
    stage = (Stage)pageonePane.getScene().getWindow();
    startPane = FXMLLoader.load(getClass().getResource("start.fxml")); 
    Scene scene = new Scene(startPane);
    stage.setScene(scene);
    stage.setTitle("Start Page"); 
    stage.show();
    stage.sizeToScene();
    stage.centerOnScreen(); 
}

private void doTEST(){
    String fromSTART = String.valueOf(intSETonStartController);
    txtPageOneValue.setText("SENT  "+fromSTART);
    if(intSETonStartController == 1){
       btnOne.setVisible(true);
       btnTwo.setVisible(false);
       System.out.println("INTEGER Value Entered = "+intSETonStartController);  
    }else{
       btnOne.setVisible(false);
       btnTwo.setVisible(true);
       System.out.println("INTEGER Value Entered = "+intSETonStartController); 
    }  
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    doTEST();
}    

}

पेज दो नियंत्रक

public class PagetwoController implements Initializable {

@FXML Pane startPane,pagetwoPane;
public Stage stage;
public static String str;

@FXML
private void toStart() throws IOException{

    str = "You ON Page Two";
    stage = (Stage)pagetwoPane.getScene().getWindow();// pane you are ON
    startPane = FXMLLoader.load(getClass().getResource("start.fxml"));// pane you are GOING TO
    Scene scene = new Scene(startPane);// pane you are GOING TO
    stage.setScene(scene);
    stage.setTitle("Start Page"); 
    stage.show();
    stage.sizeToScene();
    stage.centerOnScreen();  
}

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

}    

}

नीचे सभी एफएक्सएमएल फाइलें हैं

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane id="AnchorPane" fx:id="pagetwoPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="atwopage.PagetwoController">
   <children>
      <Button layoutX="227.0" layoutY="62.0" mnemonicParsing="false" onAction="#toStart" text="To Start Page">
         <font>
            <Font name="System Bold" size="18.0" />
         </font>
      </Button>
   </children>
</AnchorPane>

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane id="AnchorPane" fx:id="startPane" prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="atwopage.startController">
   <children>
      <Label focusTraversable="false" layoutX="115.0" layoutY="47.0" text="This is the Start Pane">
         <font>
            <Font size="18.0" />
         </font>
      </Label>
      <Button fx:id="btnPageOne" focusTraversable="false" layoutX="137.0" layoutY="100.0" mnemonicParsing="false" onAction="#toPageOne" text="To Page One">
         <font>
            <Font size="18.0" />
         </font>
      </Button>
      <Label focusTraversable="false" layoutX="26.0" layoutY="150.0" text="Enter 1 OR 2">
         <font>
            <Font size="18.0" />
         </font>
      </Label>
      <TextField fx:id="txtStartValue" layoutX="137.0" layoutY="148.0" prefHeight="28.0" prefWidth="150.0" />
   </children>
</AnchorPane>

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane id="AnchorPane" fx:id="pageonePane" prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="atwopage.PageoneController">
   <children>
      <Label focusTraversable="false" layoutX="111.0" layoutY="35.0" text="This is Page One Pane">
         <font>
            <Font size="18.0" />
         </font>
      </Label>
      <Button focusTraversable="false" layoutX="167.0" layoutY="97.0" mnemonicParsing="false" onAction="#onBack" text="BACK">
         <font>
            <Font size="18.0" />
         </font></Button>
      <Button fx:id="btnOne" focusTraversable="false" layoutX="19.0" layoutY="97.0" mnemonicParsing="false" onAction="#onBTNONE" text="Button One" visible="false">
         <font>
            <Font size="18.0" />
         </font>
      </Button>
      <Button fx:id="btnTwo" focusTraversable="false" layoutX="267.0" layoutY="97.0" mnemonicParsing="false" onAction="#onBTNTWO" text="Button Two">
         <font>
            <Font size="18.0" />
         </font>
      </Button>
      <Label focusTraversable="false" layoutX="19.0" layoutY="152.0" text="Send Anything BACK">
         <font>
            <Font size="18.0" />
         </font>
      </Label>
      <TextField fx:id="txtPageOneValue" layoutX="195.0" layoutY="150.0" prefHeight="28.0" prefWidth="150.0" />
   </children>
</AnchorPane>


3
मुझे खेद है, लेकिन यह क्या करता है या क्यों आप इसे जिस तरह से करते हैं, उसके स्पष्टीकरण के बिना कोड की सौ पंक्तियों को पोस्ट करना बहुत अच्छा जवाब नहीं है। साथ ही, आपके द्वारा पोस्ट किया गया कोड बहुत खराब तरीके से व्यवस्थित है और उसका पालन करना मुश्किल है।
Zephyr

पूछने वाले से रूबरू होने की जरूरत नहीं है। हम सब यहाँ सीखने के लिए हैं
Zeyad
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.