parameters - تمرير المعلمات JavaFX FXML




dependency-injection parameter-passing (7)

كيف يمكنني تمرير المعلمات إلى نافذة ثانوية في 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 هو النافذة الجديدة. المشكلة ، لا أستطيع إيجاد طريقة لإعلام وحدة التحكم أين تبحث عن معلومات العميل (عن طريق تمرير معرف كمعلمة).

أيه أفكار؟


Answers

يمكنك أن تقرر استخدام قائمة يمكن مراقبتها بشكل عام لتخزين البيانات العامة ، أو مجرد إنشاء طريقة عامة لتخزين البيانات واستردادها من وحدة التحكم المقابلة


يحتوي javafx.scene.Node فئة زوج من أساليب setUserData (كائن) و getUserData كائن ()

التي يمكنك استخدامها لإضافة معلوماتك إلى العقدة.

لذلك ، يمكنك الاتصال page.setUserData (معلومات) ؛

ويمكن التحقق من وحدة تحكم ، إذا تم تعيين المعلومات. أيضاً ، يمكنك استخدام ObjectProperty من أجل نقل البيانات إلى الأمام ، إذا لزم الأمر.

راقب مستندًا هنا: http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html قبل العبارة "في الإصدار الأول ، يتم وضع علامة على handleButtonAction () بـFXML للسماح بالعلامات التي تم تعريفها في مستند وحدة التحكم لاستدعاءها .في المثال الثاني ، يتم إضافة تعليق على حقل الزر للسماح للمحمل بتعيين قيمته ، كما يتم وضع طريقة التهيئة () بشكل مشابه. "

لذلك ، تحتاج إلى إقران وحدة تحكم مع عقدة ، وتعيين بيانات المستخدم إلى العقدة.


يجب عليك إنشاء فئة سياق واحدة.

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();

الآن يمكنك تمرير المعلمة إلى أي وحدة تحكم من التطبيق كله.


النهج الموصى به

تعداد هذه الإجابة آليات مختلفة لتمرير المعلمات إلى وحدات تحكم FXML.

بالنسبة للتطبيقات الصغيرة ، أوصي بشدة بتمرير المعلمات مباشرة من المتصل إلى وحدة التحكم - وهو بسيط ومباشر ولا يتطلب أي إطارات إضافية.

للحصول على تطبيقات أكبر وأكثر تعقيدًا ، سيكون من المفيد التحقيق إذا كنت تريد استخدام آليات Dependency Injection أو Event Bus ضمن التطبيق الخاص بك.

تمرير المعلمات مباشرة من المتصل إلى المراقب المالي

قم بتمرير البيانات المخصصة إلى وحدة تحكم 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 ويمكنك إنشاء عنوان URL من مورد FXML من خلال:

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

احذر من استخدام وظيفة تحميل ثابتة على FXMLLoader ، أو لن تتمكن من الحصول على وحدة التحكم الخاصة بك من مثيل محملك.

FXMLLoader مثيلات أنفسهم أبدا يعرفون أي شيء عن كائنات المجال. لا تقوم بتمرير كائنات مجال التطبيق بشكل مباشر إلى مُنشئ FXMLLoader ، بدلاً من ذلك:

  1. إنشاء FXMLLoader استنادًا إلى ترميز fxml في موقع محدد
  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 تعريف fx:controller في FXML ، أفضّل شخصيًا الحصول على وحدة التحكم من FXMLLoader بدلاً من تعيين وحدة التحكم في FXMLLoader.

وجود وحدة تحكم استرداد معلمات من "أسلوب ثابت خارجي"

يتجلى هذا الأسلوب من خلال الإجابة التي قدمها سيرجي على تطبيق Javafx 2.0 How-to Application.getParameters () في ملف Controller.java .

استخدام حقن التبعية

يدعم FXMLLoader أنظمة حقن التبعية مثل Guice أو Spring أو Java EE CDI من خلال السماح لك بتعيين مصنع وحدة تحكم مخصصة على FXMLLoader. هذا يوفر معاودة الاتصال التي يمكنك استخدامها لإنشاء مثيل وحدة التحكم مع القيم التابعة التي تم حقنها بواسطة نظام حقن التبعية المعنية. هناك عينة من دمج FXML مع نظام حقن التبعية في الربيع (للأسف الرابط ميت والمحتوى قد اختفى ، إذا كان أي شخص يعرف عن مثال مشابه ، يرجى تحرير هذا السؤال للرجوع إليه) ، على الرغم من أنه قد يكون مخادعا بعض الشيء من شأنه استخدام ميزات المصنع الجديد للتحكم المخصص المتوفرة في JavaFX 2.2.

إن أسلوب حقن الإعتمادية النظيف واللطيف هو مثال على ذلك إطار afterburner.fx مع تطبيق خرق الهواء الذي يستخدمه. يعتمد afterburner.fx على JEE6 javax.inject لتنفيذ حقن التبعية.

استخدم ناقل الأحداث

غريغ براون ، منشئ ومُنشئ مواصفات FXML الأصلي ، يقترح غالبًا التفكير في استخدام حافلة الحدث للاتصال بين وحدات التحكم الفورية FXML ومنطق التطبيق الآخر.

EventBus عبارة عن واجهة برمجة تطبيقات نشر / اشتراك بسيطة ولكنها قوية مع التعليقات التي تسمح لـ POJOs بالاتصال مع بعضهم البعض في أي مكان في JVM دون الحاجة للإشارة إلى بعضهم البعض.

متابعة سؤال وجواب

على الطريقة الأولى ، لماذا ترجع المرحلة؟ يمكن أن تكون الطريقة باطلة كذلك لأنك تعطي بالفعل show command ()؛ فقط قبل مرحلة العودة ؛ كيف تخطط للإستخدام عن طريق إرجاع المرحلة

إنه حل وظيفي للمشكلة. يتم إرجاع مرحلة من وظيفة showCustomerDialog بحيث يمكن تخزين مرجع لها من قبل فئة خارجية قد ترغب في القيام بشيء ما ، مثل إخفاء المرحلة استنادًا إلى ضغطة زر في النافذة الرئيسية ، في وقت لاحق. يمكن حل بديل ، الكائن - المنحى تغليف وظيفة ومرحلة مرجعية داخل كائن CustomerDialog أو لديك مرحلة تمديد CustomerDialog. مثال كامل لواجهة موجهة للكائنات إلى مربع حوار مخصص يقوم بتغليف FXML ووحدة التحكم وبيانات النموذج خارج نطاق هذه الإجابة ، ولكن قد يقوم بنشر تعليق مدووس لأي شخص يميل إلى إنشاء واحد.

معلومات إضافية تم توفيرها بواسطة مستخدم المسمى @dzim

مثال للحقن Dependency Injection الربيع

مسألة كيفية القيام بذلك "طريق التمهيد الربيع" ، كان هناك نقاش حول برنامج JavaFX 2 ، والذي قمت بالرجوع إليه في الرابط الثابت المرفق. النهج لا يزال ساري المفعول واختباره في مارس 2016 ، في Spring Boot v1.3.3.RELEASE: https://.com/a/36310391/1281217

في بعض الأحيان ، قد ترغب في تمرير النتائج مرة أخرى إلى المتصل ، وفي هذه الحالة يمكنك التحقق من الإجابة على السؤال ذي الصلة:


هذا يعمل ..

تذكر في المرة الأولى التي تقوم فيها بطباعة القيمة الممررة التي ستحصل عليها فارغة ، يمكنك استخدامها بعد تحميل Windows ، وهو نفسه لكل ما تريد أن تكتبه لأي مكون آخر.

المراقب الأول

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());

    }

في ما يلي مثال على تمرير المعلمات إلى مستند 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 متغير مساحة الاسم 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();
    }
}

* و ** استخدام خاص في قائمة وسيطة الدالة. * تشير إلى أن الحجة هي قائمة و ** تعني أن الحجة هي قاموس. هذا يسمح للوظائف بأخذ عدد تعسفي من الحجج