Jak utworzyć wiele kontrolerów javafx z różnymi plikami fxml?

Przeglądałem kilka blogów i innych pytań stackoverflow i nie widzę bezpośredniej odpowiedzi na moje pytanie. Tworzę klienta javafx gui i chcę, aby mój pasek menu był jednym kontrolerem w jednym fxml, a następnie chcę, aby obszar zawartości był dodatkowymi plikami fxml. Ekran logowania będzie jednym fxml, po ekranie logowania będzie główna Zawartość aplikacji i to będzie w jednym fxml. Jak mam to zrobić?

Po prostu nie chcę mieć cały mój kod do logowania, paska menu i głównej zawartości w tym samym pliku. To jest obraz tego, nad czym pracuję:

Tutaj wpisz opis obrazka

Author: j will, 2013-10-13

4 answers

Użyj FXML jako komponentów, używając niestandardowej klasy java jako FX: root i jako FX: controller Twojego pliku FXML: http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm

Aby to zrobić, musisz wywołać konstruktor swojej niestandardowej klasy java FXMLLoader, która załaduje Twój FXML. Zaletą jest zmiana sposobu ładowania komponentów FXML.

Klasyczny sposób instancjowania komponentów przez FXMLLoader z zagnieżdżonymi kontrolerami to: FXML first, then controller for each część.

W tej technice jest to: controller first, then FXML for each component. I nie będziesz ładować FXML bezpośrednio w FXML, zaimportujesz swoje niestandardowe klasy java w FXML.

Jest to lepsza abstrakcja (nie trzeba wiedzieć, jak komponent jest zaimplementowany, gdy importujesz je do FXML) i pomaga ponownie używać kodu, jak to jest jak implementacja niestandardowego widżetu z obsługą FXML. Aby komponent mógł być wielokrotnego użytku, upewnij się, że implementacja nie jest ściśle powiązana z innymi części, lub użyć IOC do tego (na przykład, z integracją Spring z JavaFX). W ten sposób będziesz mógł bez obaw zaimportować komponent do dowolnej części aplikacji (tak jak widżet DateInput) i nie zduplikujesz kodu.

W Twoim przypadku będziesz miał:

public class MenuBox extends VBox {

@FXML
private LoginBox loginBox;

@FXML
private ProfilesBox profilesBox;

public MenuBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class LoginBox extends VBox {
public LoginBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("login.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class ProfilesBox extends VBox {
public ProfilesBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("profiles.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

I zaimportujesz LoginBox i ProfilesBox w menu.fxml, który zarządza globalnym układem strony:

<?import com.foo.bar.LoginBox ?>
<?import com.foo.bar.ProfilesBox ?>
<fx:root type="javafx.scene.layout.VBox"
    xmlns:fx="http://javafx.com/fxml">

<!-- Stuff here to declare the menu bar-->

    <HBox>
       <ProfilesBox fx:id="profilesBox"/>
       <LoginBox fx:id="loginBox"/>
    </HBox>

</fx:root>

Login.fxml i profile.fxml zawiera tylko podstawowe składniki.

 34
Author: zenbeni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-14 12:31:47
  1. Możesz dołączyć dokumenty FXML jeden w drugim - powinno to pomóc w oddzieleniu logiki projektu

  2. Oznacza to, że możesz mieć zagnieżdżone Kontrolery - po jednym dla każdego dokumentu.

Z dokumentacji, możesz teraz skonfigurować kod tak, aby logika mogła być oddzielona od kontrolera głównego (jeśli zajdzie taka potrzeba).

Mam nadzieję, że to pomoże.
 5
Author: Harsha R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-13 05:53:57

Potrzebowałem wyskakującego okna o podobnych wymaganiach(większa kontrola nad węzłami i układem).

Po zapoznaniu się z zaleceniami znalazłem rozwiązanie, które może być przydatne.

Najpierw utworzyłem drugi dokument fxml i drugi kontroler (w NetBeans, New - > Empty FXML ... - >Użyj Kontrolera Java - > Utwórz Nowy...).

Małym wyzwaniem było wymyślenie, jak zbudować scenę w głównym kontrolerze i podłączyć ją do kontrolera popup.

Link przekazujący parametry JavaFX FXML daje naprawdę dobre spostrzeżenia i techniki.

Końcowy kod wygląda tak (mam nadzieję, że komuś pomoże):

// Anchor Pane from the popup
@FXML
AnchorPane anchorPanePopup;

@FXML
private void soneButtonAction(ActionEvent event) throws IOException {     
    Stage newStage = new Stage();
    AnchorPane anchorPanePopup = (AnchorPane) FXMLLoader.load(getClass().getResource("Popup_FXML.fxml"));
    Scene scene = new Scene(anchorPanePopup);
    newStage.setScene(scene);
    newStage.initModality(Modality.APPLICATION_MODAL);
    newStage.setTitle("Dialog Window");
    newStage.showAndWait();        
}
 1
Author: rainer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:16
package javafxapplication11;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.stage.Stage;

public class FXMLDocumentController implements Initializable {
@FXML
private CheckBox c1;

@FXML
private CheckBox c2;

public void clicked1(ActionEvent e) throws IOException {
Parent home_page_parent 
=FXMLLoader.load(getClass().getResource("AddDcuFXML.fxml"));
 Scene home_page_scene = new Scene(home_page_parent);
 Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
  app_stage.hide(); //optional
  app_stage.setScene(home_page_scene);
  app_stage.show();
   }
   public void clicked2(ActionEvent e) throws IOException {
   Parent home_page_parent 
    =FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
   Scene home_page_scene = new Scene(home_page_parent);
   Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
    app_stage.hide(); //optional
      app_stage.setScene(home_page_scene);
         app_stage.show();
     }
      public void clicked3(ActionEvent e) throws IOException {
     Parent home_page_parent 
   =FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
    Scene home_page_scene = new Scene(home_page_parent);
    Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
     app_stage.hide(); //optional
     app_stage.setScene(home_page_scene);
     app_stage.show();
      }
     @Override
       public void initialize(URL arg0, ResourceBundle arg1) {
        // TODO Auto-generated method stub
           } 
               }
 0
Author: Laxmi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-12 00:25:33