Geçiş Parametreleri JavaFX FXML


195

Javafx'te ikincil bir pencereye parametreleri nasıl iletebilirim? İlgili kontrol cihazıyla iletişim kurmanın bir yolu var mı?

Örneğin: Kullanıcı bir müşteri seçer TableViewve müşterinin bilgilerini gösteren yeni bir pencere açılır.

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

newStageyeni pencere olurdu. Sorun, denetleyiciye nerede müşteri bilgilerini (kimliğini parametre olarak ileterek) aramak için bir yol bulamıyorum.

Herhangi bir fikir?


Bunun da işe
yarayıp yaramadığını

@Alvaro: çözümünüzü aldınız mı? parametre iletebilir misiniz? bir denetleyiciden başka bir denetleyici dosyasına?
Java Man

3
Evet. jewelsea kitap düzeyinde bir açıklama yaptı. Bu yüzden cevabını kabul ettim
Alvaro

Yanıtlar:


277

Önerilen Yaklaşım

Bu yanıt, parametreleri FXML denetleyicilerine geçirmek için farklı mekanizmaları numaralandırır.

Küçük uygulamalar için parametreleri doğrudan arayandan denetleyiciye geçirmenizi önemle tavsiye ederim - basit, anlaşılır ve ekstra çerçeve gerektirmez.

Daha büyük, daha karmaşık uygulamalar için, uygulamanızda Bağımlılık Enjeksiyonu veya Olay Veri Yolu mekanizmalarını kullanmak isteyip istemediğinizi araştırmak faydalı olacaktır .

Parametreleri Doğrudan Arayandan Denetleyiciye Aktarma

Denetleyiciyi FXML yükleyici örneğinden alıp denetleyicide gerekli veri değerleriyle başlatmak için bir yöntem çağırarak özel verileri bir FXML denetleyicisine aktarın.

Aşağıdaki kod gibi bir şey:

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

Örnek kodda gösterildiği gibi yeni bir FXMLLoader oluşturulur new FXMLLoader(location). Konum bir URL'dir ve böyle bir URL'yi şu şekilde bir FXML kaynağından oluşturabilirsiniz:

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

FXMLLoader'da statik yük fonksiyonu KULLANMAMAYA dikkat edin, aksi takdirde kumandanızı yükleyici durumunuzdan alamazsınız.

FXMLLoader örneklerinin kendileri etki alanı nesneleri hakkında hiçbir şey bilmez. Uygulamaya özgü etki alanı nesnelerini doğrudan FXMLLoader yapıcısına geçirmezsiniz, bunun yerine:

  1. Belirtilen bir konumda fxml işaretlemesine dayalı bir FXMLLoader oluşturma
  2. FXMLLoader örneğinden bir denetleyici alın.
  3. Denetleyiciye etki alanı nesnelerine başvurular sağlamak için alınan denetleyicideki yöntemleri çağırın.

Bu blog (başka bir yazar tarafından) alternatif, ancak benzer bir örnek sunmaktadır .

FXMLLoader'da Denetleyici Ayarlama

CustomerDialogController dialogController = 
    new CustomerDialogController(param1, param2);

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

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

Arayandan istediğiniz parametreleri denetleyici yapıcısına ileterek kodda yeni bir denetleyici oluşturabilirsiniz. Bir denetleyici oluşturduktan sonra , örnek yöntemini çağırmadan önce onu bir FXMLLoader örneğinde ayarlayabilirsiniz .load()

Bir yükleyicide (JavaFX fx:controller2.x'te ) bir denetleyici ayarlamak için fxml dosyanızda bir öznitelik tanımlayamazsınız .

fx:controllerFXML'deki tanımdaki sınırlama nedeniyle , denetleyiciyi FXMLLoader'a ayarlamak yerine kişisel olarak denetleyiciyi FXMLLoader'dan almayı tercih ederim.

Denetleyicinin Parametreleri Harici Statik Yöntemden Alması

Bu yöntem Sergey'in bir Controller.java dosyasındaki Javafx 2.0 How-to Application.getParameters () öğesine verdiği yanıtla örneklendirilmiştir .

Bağımlılık Enjeksiyonu Kullan

FXMLLoader, FXMLLoader'da özel bir kontrolör fabrikası kurmanıza izin vererek Guice, Spring veya Java EE CDI gibi bağımlılık enjeksiyon sistemlerini destekler. Bu, ilgili bağımlılık enjeksiyon sistemi tarafından enjekte edilen bağımlı değerlere sahip denetleyici örneği oluşturmak için kullanabileceğiniz bir geri arama sağlar.

JavaFX uygulaması ve Spring ile kontrolör bağımlılığı enjeksiyonuna bir örnek aşağıdaki cevapta verilmiştir:

Gerçekten güzel, temiz bir bağımlılık enjeksiyon yaklaşımı, onu kullanan örnek bir hava korsanlığı uygulamasıyla afterburner.fx çerçevesi tarafından örneklendirilir . afterburner.fx bağımlılık enjeksiyonunu yapmak için JEE6 javax.inject dosyasına güveniyor .

Etkinlik Otobüsü Kullanma

Orijinal FXML belirtim yaratıcısı ve uygulayıcısı olan Greg Brown, genellikle FXML somutlaştırılmış denetleyiciler ve diğer uygulama mantığı arasındaki iletişim için Guava EventBus gibi bir olay veri yolunun kullanılmasını öneriyor .

EventBus, POJO'ların birbirlerine başvurmak zorunda kalmadan JVM'de herhangi bir yerde birbirleriyle iletişim kurmalarına olanak tanıyan ek açıklamalara sahip basit ama güçlü bir yayınlama / abone olma API'sidir.

Takip Soru-Cevap

ilk yöntemde neden Sahne Alanı'na dönüyorsunuz? Şimdiden show () komutunu verdiğiniz için yöntem de geçersiz olabilir. dönüş aşamasından hemen önce; Sahne Alanı'na geri dönerek kullanımı nasıl planlıyorsunuz?

Bir soruna işlevsel bir çözümdür. Bir aşama, showCustomerDialogişlevden daha sonra ana pencerede bir düğmeyi tıklatarak sahneyi gizlemek gibi bir şey yapmak isteyebilecek harici bir sınıf tarafından saklanabilmesi için işlevden döndürülür . Alternatif, nesne yönelimli bir çözüm, bir CustomerDialog nesnesi içindeki işlevselliği ve sahne referansını kapsayabilir veya bir CustomerDialog Sahne Alanı genişletebilir. FXML, denetleyici ve model verilerini kapsayan özel bir iletişim kutusuna nesne yönelimli arabirim için tam bir örnek bu yanıtın kapsamı dışındadır, ancak bir tane oluşturmaya eğilimli herkes için değerli bir blog gönderisi yapabilir.


@Dzim adlı StackOverflow kullanıcısı tarafından sağlanan ek bilgiler

Yay Önyükleme Bağımlılığı Enjeksiyonu Örneği

Bunun nasıl yapılacağı sorusu "The Spring Boot Way", ekli kalıcı bağlantıda cevapladığım JavaFX 2 hakkında bir tartışma vardı. Yaklaşım İlkbahar Boot v1.3.3.RELEASE üzerinde hala geçerli ve Mart 2016 yılında test edilmiştir: https://stackoverflow.com/a/36310391/1281217


Bazen, sonuçları arayana geri aktarmak isteyebilirsiniz, bu durumda ilgili sorunun cevabını kontrol edebilirsiniz:


FXMLLoader yapıcıları URL'leri yalnızca parametre olarak alır .. FXMLLoader'ı somutlaştırmanın doğru yolu nedir?
Alvaro

1
olay otobüsü web sitesi "Güncelleme 3/2013: EventBus bayat gitti ..." devletler
j

1
DataFX Denetleyici Çerçeveleri, FXML denetleyicileri için bazı enjeksiyon desteği sağlar: guigarage.com/2013/12/datafx-controller-framework-preview
Hendrik Ebbers

2
@Anarkie
jewelsea

7
godshake için JavaFx bu küçük işi yapmak için basit bir şey var mı? yapıcı ve javafx veri geçirmek için çok yaygın bir özellik sadece bir isim veya bir değer göndermek için hep birlikte bu şeylerin cehennemi gerektirir?
Zahan Safallwa

13

Bunun çok eski bir yazı olduğunu ve zaten bazı harika cevapları olduğunu fark ettim, ancak böyle bir yaklaşımı göstermek için basit bir MCVE yapmak ve yeni kodlayıcıların kavramı hızlı bir şekilde eylemde görmelerini sağlamak istedim.

Bu örnekte 5 dosya kullanacağız:

  1. Main.java - Uygulamayı başlatmak ve ilk denetleyiciyi çağırmak için kullanılır.
  2. Controller1.java - İlk FXML düzeni için denetleyici.
  3. Controller2.java - İkinci FXML düzeni için denetleyici.
  4. Layout1.fxml - İlk sahne için FXML düzeni.
  5. Layout2.fxml - İkinci sahne için FXML düzeni.

Tüm dosyalar, bu yayının altında tamamen listelenir.

Hedef: geçirilmesi değerleri göstermek için Controller1için Controller2ve tersi de geçerlidir.

Program Akışı:

  • İlk sahne a TextField, a Buttonve a içerir Label. Ne zaman Buttontıklandığında, ikinci pencere yüklenir ve girilen metin dahil, görüntülenen TextField.
  • İkinci sahnede ayrıca a TextField, a Buttonve a vardır Label. LabelGirilen metni görüntüler TextFieldilk sahnede.
  • İkinci sahneye metin girip üzerine TextFieldtıkladıktan sonra Button, ilk sahnenin Labelgirilen metni gösterecek şekilde güncellenmesi sağlanır.

Bu çok basit bir gösteri ve kesinlikle biraz iyileşme anlamına gelebilir, ancak kavramı çok açık hale getirmelidir.

Kodun kendisi de neler olup bittiğine dair bazı ayrıntılarla da yorumlanıyor.

KOD

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
Denetleyiciyi FXML dosyasında ayarlamak mümkün müdür? Satırı kaldırmadan önce: loader.setController(this)ve FXML dosyasına denetleyici eklemek uygulamayı
kilitler

1
FXML denetleyicinin kendisinden yüklenmişse değil. Örneğin, FXML'yi Ana sınıftan yüklerseniz, denetleyiciyi FXML dosyasında tanımlayabilir ve buna kullanarak bir referans alabilirsinizloader.getController()
Zephyr

Sonunda bir çözüm bulmayı başardım, harika bir örnek. Projeme uyguladım ve şimdi her iki pencereyi aynı anda açmaya ve ilk önce modal yapmaya çalışıyorum. Ne yazık ki sadece biri açılıyor. Birisi bu konuda yardımcı olabilir mi?
jabba

8

javafx.scene.Node sınıfının setUserData (Object) ve Object getUserData () yöntemlerinin bir çift yöntemi vardır

Bilgilerinizi Düğüme eklemek için kullanabilirsiniz.

Böylece, page.setUserData (info);

Ve bilgi ayarlanıp ayarlanmadığını kontrolör kontrol edebilir. Ayrıca, gerekirse, ileriye doğru veri aktarımı için ObjectProperty'yi kullanabilirsiniz.

Buradaki bir dokümanı inceleyin: http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html "İlk sürümde handleButtonAction (), @FXML ile etiketlendi İkinci örnekte, yükleyicinin değerini ayarlamasına izin vermek için düğme alanına açıklama eklenir. initialize () yöntemi de benzer şekilde not eklenmiştir. "

Bu nedenle, bir denetleyiciyi bir düğümle ilişkilendirmeniz ve düğüme bir kullanıcı verisi ayarlamanız gerekir.


Stage.getScene () -> Scene.getRoot () -> Parent.getChildrenUnmodifiable () ile özyinelemeli arama. Bu çok kirli bir yol. Birisi daha iyi bir şey önerebilirse - bu harika olacak.
Alexander Kirov

Stage.getScene () gibi görünüyor. GetRoot () doğru yol! Teşekkürler
Alvaro

7

Aşağıda, ad alanı aracılığıyla bir fxml belgesine parametre aktarmaya yönelik bir örnek verilmiştir.

<?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>

Ad External Textalanı değişkeni için değer tanımlayın 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();
    }
}

Bazı anahtarların dahili olarak kullanıldığına dikkat edilmelidir: örn FXMLLoader.CONTROLLER_KEYWORD. FXMLLoader.LOCATION_KEY, FXMLLoader.RESOURCES_KEYVe fx:idöznitelik için değer olarak kullanılan herhangi bir dize .
fabian

Bunun için teşekkürler, diğer sahnem sadece ana sahnemde gösterilen metni gösteren bir kap. Şimdi Namepace değişkenleri aracılığıyla içerik başlatarak birden fazla yerde yeniden kullanabileceğiniz bir fxml olabilir. Herhangi bir yeni yöntem oluşturmak ya da benim kurucu veya initalisers değiştirmek zorunda değildi - sadece FXML benim değişken eklemek ve ana denetleyicideki fxmloader koduna bir satır ekleyin.
SystemsInCode

4

Bu çalışıyor ..

Geçen değeri bastığınızda null alacağınızı unutmayın, pencereleriniz yüklendikten sonra kullanabilirsiniz, diğer herhangi bir bileşen için kodlamak istediğiniz her şey için aynıdır.

İlk Kontrolör

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

Başka Bir Denetleyici

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

1
Parametre ilk denetleyiciden ikinciye geçtiğinizde, ancak parametreyi ikinci denetleyiciden ilk denetleyiciye geçirdiğinizde, yani first.fxml yüklendikten sonra anlamına gelir.
Menai Ala Eddine - Aladdin

@XlintXms , ek sorunuza yanıt veren A Denetleyicisinden B'ye ve Geriye geçen JavaFX FXML Parametresi ile ilgili soruyu görür .
jewelsea

2

Bir Bağlam Sınıfı oluşturmanız gerekir.

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;
    }
}

Kullanıma alma sırasında kontrolör örneğini ayarlamanız yeterlidir.

Context.getInstance().setTabRough(this);

ve tüm uygulamanızdan sadece

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

Artık parametreyi tüm uygulamadan herhangi bir denetleyiciye geçirebilirsiniz.


Bu yaklaşımı kullanıyoruz ve harika çalışıyor. Yapıcı içindeki veya başlatma yöntemindeki verilere erişebilmeyi seviyorum ve yapılandırıldıktan sonra denetleyicideki verileri ayarlamak zorunda değilim
Bob

2

Evet yapabilirsin.
İlk denetleyiciye eklemeniz gerekir:

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

Sonra ikincisinde bir müşteri ilan edin, daha sonra kumandanızın altında:

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

0

İşte Guice tarafından enjekte edilen bir kontrolör kullanımına bir örnek.

/**
 * 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;
}

Yükleyicinin somut bir uygulaması:

public class ConcreteViewLoader extends GuiceFxmlLoader {

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

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

Bu örnek, görünümü Sahne Alanı'ndaki Sahne'nin kökü olan bir BoarderPane merkezine yükler. Bu, örnekle (özel kullanım durumumun uygulama detayı) ilgisizdir, ancak bazılarını yararlı bulabileceği için, bırakmaya karar verdim.


-1

Herkese açık verileri saklamak için herkese açık bir gözlemlenebilir liste kullanmaya karar verebilir veya sadece verileri depolamak ve ilgili denetleyiciden almak için bir genel ayarlayıcı yöntemi oluşturabilirsiniz.


-3

Neden 6 yaşındaki bir soruyu cevaplıyorsunuz?
Herhangi bir programlama diliyle çalışan en temel kavramlardan biri, bir pencereden (pencere, form veya sayfa) diğerine nasıl geçileceğidir. Ayrıca bu navigasyonu yaparken, geliştirici genellikle birinden (pencere, form veya sayfa) veri iletmek ve iletilen verileri görüntülemek veya kullanmak
ister. bir çentik ya da iki ya da üç
üç (pencere, form veya sayfa) arasında gezinmek ve (pencere, form veya sayfa) etrafında veri aktarmak için statik değişken kavramını kullanır çünkü üç söyleyen
Ayrıca ederken kod verme bazı karar içerecektir gidiyoruz

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

Başlat Kontrolörü

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

Birinci Sayfa Denetleyici

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

}

Sayfa İki Denetleyici

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) {

}    

}

Aşağıda tüm FXML dosyaları bulunmaktadır

<?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>


4
Üzgünüm, ama ne yaptığına veya neden yaptığınız gibi bir açıklama yapmadan yüz satır kod göndermek çok iyi bir cevap değil. Ayrıca, yayınladığınız kod çok kötü organize edilmiş ve takip edilmesi zor.
Zephyr

1
Soran kişiye kaba olmaya gerek yoktur. Hepimiz öğrenmek için buradayız
Zeyad
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.