2016-04-07 10 views
1

Ich entdeckte gerade JavaFX und ich mochte es wirklich. Ich hasse Java-Standard-GUI, also habe ich sofort entschieden, mein Fenster zu personalisieren. Ich hatte zahlreiche Versuche, aber ich habe eine große Einschränkung und ein großes Ziel; Einschränkung? Ich muss MVC-Muster verwenden. Zielsetzung? Machen Sie das benutzerdefinierte Fenster wiederverwendbar.JavaFX - einfache benutzerdefinierte minimale Fensterimplementierung

So ... Dies ist der Punkt, den ich jetzt habe: wstaw.org/m/2016/04/07/resoruces.png

ich einen allgemeines Paket Antrag gestellt, die App.java enthält, dass Wille Starten Sie die App. Dann mache ich ein weiteres internes Paket, das die "MinimalWindow" -Logik enthält, mit allen Resorucen, die ich brauche.

implementiert ich diesen FXML Code aus dem Fenster auszuführen:

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

<?import javafx.scene.layout.BorderPane?> 
<?import javafx.scene.layout.HBox?> 
<?import javafx.scene.layout.StackPane?> 
<?import javafx.scene.image.ImageView?> 
<?import javafx.scene.layout.Region?> 
<?import javafx.scene.control.Label?> 

<StackPane fx:id="minimalWindowShadowContainer" id="minimalWindowShadowContainer" stylesheets="@style.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" onMousePressed="#updateXY" onMouseDragged="#windowDragging" onMouseReleased="#updateStatus" > 
    <BorderPane fx:id="minimalWindowContainer" id="minimalWindowContainer"> 
     <!-- This padding will create the dropshadow effect for the window behind --> 
     <padding> 
      <Insets top="5" right="5" bottom="5" left="5"/> 
     </padding> 

     <!-- "Title Bar" --> 
     <top> 
      <HBox id="titleBar" alignment="CENTER" spacing="5" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="600.0"> 
       <padding> 
        <Insets top="5" right="5" bottom="5" left="5"/> 
       </padding> 

       <ImageView fx:id="logo" fitWidth="20" fitHeight="20"></ImageView> 
       <Label fx:id="lblTitle" id="title" text="MinimalWindow"></Label> 
       <Region HBox.hgrow="ALWAYS" prefHeight="30.0" prefWidth="200.0"></Region> 

       <HBox alignment="CENTER_RIGHT"> 
        <Button id="btnMin" onMouseClicked="#minimizeApp" minHeight="20" minWidth="20" maxHeight="20" maxWidth="20"></Button> 
        <Button fx:id="btnMax" id="btnMax" onMouseClicked="#maximizeApp" minHeight="20" minWidth="20" maxHeight="20" maxWidth="20"></Button> 
        <Button id="btnCls" onMouseClicked="#closeApp" minHeight="20" minWidth="20" maxHeight="20" maxWidth="20"></Button> 
       </HBox> 
      </HBox> 
     </top> 

     <!-- The content of the window will go here --> 
     <center> 
      <StackPane fx:id="contentArea" id="contentArea"></StackPane> 
     </center> 

     <!-- Footer --> 
     <bottom> 
      <HBox id="footer"> 
       <padding> 
        <Insets top="5" right="5" bottom="5" left="5"/> 
       </padding> 

       <Button fx:id="btnResize" id="btnResize" alignment="BOTTOM_RIGHT" onMouseClicked="#updateXY" onMouseEntered="#setMouseCursor" onMouseExited="#resetMouseCursor" onMouseDragged="#resizeWindow" minHeight="10" minWidth="10" maxHeight="10" maxWidth="10"></Button>  
      </HBox> 
     </bottom> 
    </BorderPane> 
</StackPane> 

ich dann die Controller-Klasse implementiert:

package application.minimalWindow; 


import javafx.application.Application; 
import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.geometry.Insets; 
import javafx.scene.Cursor; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.StackPane; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 
import javafx.stage.StageStyle; 

public class MinimalWindow extends Application { 

    @FXML 
    Label lblTitle; 

    @FXML 
    Button btnMax, btnResize; 

    @FXML 
    StackPane minimalWindowShadowContainer, minimalWindowContainer,contentArea; 

    @FXML 
    Double SHADOW_SPACE; 

    final private static int MIN_WIDTH = 730, MIN_HEIGHT = 500; 


    private double actualX, actualY; 
    private boolean isMovable; 
    private String source, title; 

    private Stage mainStage; 

    // 
    // Public logic of the class 
    // 

    public MinimalWindow() { 
     //TODO must work... 
    } 


    //Show the window 
    public void show() { 
     mainStage.show(); 
    } 


    // 
    // MIMIZIE | MAXIMIZE | CLOSE 
    // 

    //When pressed, will minimize the window to tray 
    @FXML 
    private void minimizeApp(MouseEvent e) { 
     mainStage.setIconified(true); 
    } 

    //When pressed, check if it must maximize or restore the window 
    @FXML 
    private void maximizeApp(MouseEvent e) { 
     if (mainStage.isMaximized()) { 
      setMin(); 
      isMovable = true; 
     } 

     else { 
      setMax(); 
      isMovable = false; 
     } 
    } 

    //When pressed, will kill the window 
    @FXML 
    private void closeApp(MouseEvent e) { 
     mainStage.close(); 
     System.exit(0); 
    } 


    // 
    // WINDOW MOVING 
    // 

    //When i must update the XY of the click 
    @FXML 
    private void updateXY(MouseEvent e){ 
     actualX = e.getScreenX() - mainStage.getX(); 
     actualY = e.getScreenY() - mainStage.getY(); 
    } 

    //When pressing and dragging the mouse it will move the window 
    @FXML 
    private void windowDragging(MouseEvent e) { 
     if (isMovable) { 
      mainStage.setX(e.getScreenX() - actualX); 
      mainStage.setY(e.getScreenY() - actualY); 
     } 

     else { 
      //setMin(); 
      mainStage.setX(e.getScreenX()); 
      mainStage.setY(e.getScreenY()); 
     } 
    } 

    //Update the status of the window from not movable to movable, after "normalize" effect 
    //from the dragging it when it's maximized 
    @FXML 
    private void updateStatus(MouseEvent e) { 
     if (mainStage.isMaximized() == false) { 
      isMovable = true; 
     } 
    } 


    // 
    // WINDOW RESIZING 
    // 

    /*onMouseEntered="#setMouseCursor" onMouseExited="#resetMouseCursor" onMouseDragged="#resizeWindow"*/ 

    @FXML 
    private void setMouseCursor (MouseEvent e) { 
     minimalWindowContainer.setCursor(Cursor.CROSSHAIR); 
    } 

    @FXML 
    private void resetMouseCursor (MouseEvent e) { 
     minimalWindowContainer.setCursor(Cursor.DEFAULT); 
    } 

    @FXML 
    private void resizeWindow (MouseEvent e) { 
     actualX = e.getScreenX() - mainStage.getX() + 13; 
     actualY = e.getScreenY() - mainStage.getY() + 10; 

     if (actualX % 5 == 0 || actualY % 5 == 0) { 
      if (actualX > MIN_WIDTH) { 
       mainStage.setWidth(actualX); 
      } else { 
       mainStage.setWidth(MIN_WIDTH); 
      } 

      if (actualY > MIN_HEIGHT) { 
       mainStage.setHeight(actualY); 
      } else { 
       mainStage.setHeight(MIN_HEIGHT); 
      } 
     } 
    } 


    // 
    // Internal methods 
    // 

    //Will set the window to MAXIMIZE size 
    private void setMax() { 
     mainStage.setMaximized(true); 
     btnResize.setVisible(false); 
     btnMax.setStyle("-fx-background-image: url('/res/dSquare.png');"); 
     minimalWindowContainer.setPadding(new Insets(0, 0, 0, 0)); 
    } 

    //Will set the window to NORMAL size 
    private void setMin() { 
     mainStage.setMaximized(false); 
     btnResize.setVisible(true); 
     btnMax.setStyle("-fx-background-image: url('/res/square.png');"); 
     minimalWindowContainer.setPadding(new Insets(SHADOW_SPACE, SHADOW_SPACE, SHADOW_SPACE, SHADOW_SPACE)); 
    } 

    @Override 
    public void start(Stage primaryStage) { 

     /* //NOT SURE IF DOING RIGHT YA' 
     try { 
      //Prepare the resource with the FXML file 
      FXMLLoader loader = new FXMLLoader(getClass().getResource("/application/minimalWindow/MainWindow.fxml")); 

      //Load the main stackpane 
      Parent root = loader.load(); 

      loader.setController(this); 

      //Prepare the content of the window, with a minWidth/Height 
      Scene scene = new Scene(root, MIN_WIDTH, MIN_HEIGHT); 

      //Making the scene transparent 
      scene.setFill(Color.TRANSPARENT); 

      //Undecorate the window due its persolalisation 
      primaryStage.initStyle(StageStyle.TRANSPARENT); 

      //Set the content of the window 
      primaryStage.setScene(scene); * 
     } 

     catch (Exception e) { 
      e.printStackTrace(); 
     }  */ 
    } 

und die CSS-Styling:

* { 
    /* Some general colors */ 
    primaryColor: #f9f9f9; 
    secondaryColor: derive(primaryColor, -75%); 

    textColor: white; 
    closeBtnColor: red; 

} 

#titleBar, #footer { 
    -fx-background-color: secondaryColor; 
} 

#title { 
    -fx-text-fill: textColor; 
} 

#contentArea { 
    -fx-background-color: primaryColor; 
} 

#minimalWindowShadowContainer { 
    -fx-background-color: transparent;  
    -fx-effect: dropshadow(gaussian , black , 5,0,0,0); 
    -fx-background-insets: 5; 
} 

#btnCls, #btnMax, #btnMin, #btnResize { 
    -fx-background-color: transparent; 
    -fx-background-radius: 0; 
    -fx-border-color: transparent; 
    -fx-border-width: 0; 
    -fx-background-position: center; 
    -fx-background-repeat: stretch; 
} 

#btnMax:hover, #btnMin:hover { 
    -fx-background-color: derive(secondaryColor, 20%); 
} 

#btnCls:hover { 
    -fx-background-color: derive(red, 45%); 
} 

#btnCls { 
    -fx-background-image: url('/res/x.png');  
} 

#btnMax { 
    -fx-background-image: url('/res/square.png'); 
} 

#btnMin { 
    -fx-background-image: url('/res/line.png'); 
} 

#btnResize { 
    -fx-background-image: url('/res/resize.png'); 
} 

In der App.java sollte ich so verwenden:

Ich poste dies meine Lösung hier becouse im Internet fand ich genau NICHTS über benutzerdefinierte Styling in MVC Muster (ja ... Ich muss es für das Prüfungsprojekt tun).

Was sind die Probleme? Es muss einfach zu verwenden und wiederverwendbar sein. Der Versuch, den Konstruktor wie folgt zu machen:

public MinimalWindow(String title, String source) { 
     this.title = title; 
     this.source = source;  
     start(mainStage); 
    } 

es gibt mir Fehler in XAML-Datei in der 11 Reihe Parsen (die erste Zeile, die die Stackpanel definieren), oder geben Sie mir einen Fehler „Verursacht durch: java.lang. IllegalStateException: Toolkit nicht initialisiert ". Zum ersten, ich weiß nicht, was es verursacht. Für die zweite schlägt die Lösung im Internet vor, meine Klasse von Application zu erweitern und dann die "Start" -Methode zu überschreiben, aber es hat nicht funktioniert.

Fragestunde: irgendeine Lösung? Vorschläge?

PS: Ich mache Arbeit dieses Code in einem nicht-MVC-Muster, mit einem anderen Stil, und es funktionierte großartig: wstaw.org/m/2016/04/07/ezgif.com-crop.gif

+0

@James_D scheint zu verstehen, was Sie achive wollen. Ich bin mir nicht 100% sicher. Wenn es um benutzerdefinierte Fensterdekorationen geht, können Sie sich einen Blick darauf werfen, indem Sie den Code von Undecorator überprüfen - eine Lib, die es schon seit einiger Zeit gibt. Vielleicht hilft das: [Undecorator @ Github] (https://github.com/in-sideFX/Undecorator) – dzim

+0

Undercoator ist sehr problematisch, und ich bevorzuge es für mich selbst zu tun, weil ich wissen muss, was die App tatsächlich macht. Ich habe es versucht, ich habe gesehen, was er kann, aber ich kann nichts tun, was so funktioniert, wie ich es wirklich wollte. Das Ergebnis, das ich möchte, ist ähnlich, aber einfacher zu implementieren und zu verwenden. Ich überprüfe dann besser, ob es die Quelle ist. – Martinocom

+1

Ok, ich verstehe deinen allgemeinen Wunsch. Und ja: Ich habe nur Undecorator ausprobiert, als es sehr sehr war [wiederhole das x mal] neu. Ich habe nur vorgeschlagen, einen Blick darauf zu werfen, wie Sie das erreichen können. Ich stolpere auch über einen alten Post von mir auf einer e (fx) clipse Google-Gruppe (als es noch kein offizielles Eclipse-Projekt war - im frühen JavaFX 2 mal) und fragte seinen Schöpfer nach Hilfe zu diesem Thema. Siehe [hier] (https://groups.google.com/forum/#!topic/efxclipse/bNneRaIBNN0) - Sie können weiterhin auf die Links für zwei GitHub-Seiten im Google-Cache zugreifen. Keine schwarze Magie. Was fehlt, ist die Größenänderung. – dzim

Antwort

0

Ok, ich folgte alles, was ich von dir gelernt habe und ich mache fast alles. Also, was hat das ich jetzt es ist das:

wstaw.org/m/2016/04/10/project.png

Jetzt

, ich habe FXML der MinimalWindow:

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

<?import javafx.scene.layout.BorderPane?> 
<?import javafx.geometry.Insets?> 
<?import javafx.scene.layout.HBox?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.layout.StackPane?> 
<?import javafx.scene.image.ImageView?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.Button?> 
<?import javafx.scene.layout.Region?> 
<?import javafx.scene.layout.AnchorPane?> 
<?import javafx.scene.layout.GridPane?> 

<!-- Container that will do the "shadow" effect --> 
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="BorderPane" fx:id="root" id="root" stylesheets="@MinimalWindowStyle.css" onMousePressed="#updateXY" onMouseDragged="#windowDragging" onMouseReleased="#updateStatus"> 
    <center> 
     <!-- Main content --> 
     <BorderPane fx:id="mainWindow" id="mainWindow"> 
      <!-- Padding will show the shadow effect under the window --> 
      <padding> 
       <Insets top="5" right="5" bottom="5" left="5"></Insets> 
      </padding> 

      <!-- Top bar of the window --> 
      <top> 
       <HBox id="titleBar" alignment="CENTER" spacing="5" prefHeight="30"> 
        <padding> 
         <Insets top="5" right="5" bottom="5" left="5"/> 
        </padding> 

        <ImageView fx:id="logo" fitWidth="20" fitHeight="20"></ImageView> 
        <Label fx:id="lblTitle" id="title" text="MinimalWindow"></Label> 
        <Region HBox.hgrow="ALWAYS" prefHeight="30.0" prefWidth="200.0"></Region> 

        <HBox alignment="CENTER_RIGHT"> 
         <Button id="btnMin" onMouseClicked="#minimizeApp" minHeight="20" minWidth="20" maxHeight="20" maxWidth="20"></Button> 
         <Button fx:id="btnMax" id="btnMax" onMouseClicked="#maximizeApp" minHeight="20" minWidth="20" maxHeight="20" maxWidth="20"></Button> 
         <Button id="btnCls" onMouseClicked="#closeApp" minHeight="20" minWidth="20" maxHeight="20" maxWidth="20"></Button> 
        </HBox> 
       </HBox> 
      </top> 

      <!-- Window content --> 
      <center> 
       <GridPane fx:id="contentArea" id="contentArea"></GridPane> 
      </center> 

      <!-- Footer of the window --> 
      <bottom> 
       <HBox id="footer" prefHeight="20" alignment="BOTTOM_RIGHT"> 
        <padding> 
         <Insets top="5" right="5" bottom="5" left="5"/> 
        </padding> 

        <Button fx:id="btnResize" id="btnResize" onMouseClicked="#updateXY" onMouseEntered="#setMouseCursor" onMouseExited="#resetMouseCursor" onMouseDragged="#resizeWindow" minHeight="10" minWidth="10" maxHeight="10" maxWidth="10"></Button>  
       </HBox> 
      </bottom> 

     </BorderPane> 
    </center> 
</fx:root> 

Der Stil für sie:

* { 
    /* Some general colors */ 
    primaryColor: #f9f9f9; 
    secondaryColor: derive(primaryColor, -75%); 

    textColor: white; 
    closeBtnColor: red; 
} 

#titleBar, #footer { 
    -fx-background-color: secondaryColor; 
} 

#title { 
    -fx-text-fill: textColor; 
} 

#contentArea { 
    -fx-background-color: primaryColor; 
} 

#root { 
    -fx-background-color: transparent;  
    -fx-effect: dropshadow(gaussian , black , 5,0,0,0); 
    -fx-background-insets: 5; 
} 

#btnCls, #btnMax, #btnMin, #btnResize { 
    -fx-background-color: transparent; 
    -fx-background-radius: 0; 
    -fx-border-color: transparent; 
    -fx-border-width: 0; 
    -fx-background-position: center; 
    -fx-background-repeat: stretch; 
} 

#btnMax:hover, #btnMin:hover { 
    -fx-background-color: derive(secondaryColor, 20%); 
} 

#btnCls:hover { 
    -fx-background-color: derive(red, 45%); 
} 

#btnCls { 
    -fx-background-image: url("/resources/x.png"); 
} 

#btnMax { 
    -fx-background-image: url('/resources/square.png'); 
} 

#btnMin { 
    -fx-background-image: url('/resources/line.png'); 
} 

#btnResize { 
    -fx-background-image: url('/resources/resize.png'); 
} 

Die Controller-Klasse für sich:

package controller.minimalWindow; 

import application.Main; 
import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.geometry.Insets; 
import javafx.scene.Cursor; 
import javafx.scene.Node; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.GridPane; 
import javafx.stage.Stage; 

public class MinimalWindowCtrl extends BorderPane { 

    //Values injected from the FXML 
    @FXML 
    private BorderPane root, mainWindow; 

    @FXML 
    private Label lblTitle; 

    @FXML 
    private Button btnMax, btnResize; 

    @FXML 
    private GridPane contentArea; 

    //Reference to the primaryStage 
    final private Stage stage; 

    //References to min/max width/height and the shadow effect 
    final private int MINWIDTH, MINHEIGHT, SHADOWSPACE = 5; 

    //Things for the resizing/moving window 
    private double actualX, actualY; 
    private boolean isMovable = true; 




    public MinimalWindowCtrl (Stage stage, int minwidth, int minheight) { 
     //First, take the reference to the stage 
     this.stage = stage; 

     //Taking the references to the window 
     MINWIDTH = minwidth; 
     MINHEIGHT = minheight; 

     //Then load the window, setting the root and controller 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("../../view/minimalWindow/MinimalWindow.fxml")); 
     loader.setRoot(this); 
     loader.setController(this); 



     //Try to load 
     try { 
      loader.load(); 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
      //TODO Show a message error 
      Main.close(); 
     } 
    } 

    public void setTitle(String s) { 
     lblTitle.setText(s); 
    } 

    public void setContent(Node node) { 
     contentArea.getChildren().add(node); 
    } 



    // 
    // MIMIZIE | MAXIMIZE | CLOSE 
    // 

    //When pressed, will minimize the window to tray 
    @FXML 
    private void minimizeApp(MouseEvent e) { 
     stage.setIconified(true); 
    } 

    //When pressed, check if it must maximize or restore the window 
    @FXML 
    private void maximizeApp(MouseEvent e) { 
     if (stage.isMaximized()) { 
      setMin(); 
      isMovable = true; 
     } 

     else { 
      setMax(); 
      isMovable = false; 
     } 
    } 

    //When pressed, will kill the window 
    @FXML 
    private void closeApp(MouseEvent e) { 
     stage.close(); 
     System.exit(0); 
    } 


    // 
    // WINDOW MOVING 
    // 

    //When i must update the XY of the click 
    @FXML 
    private void updateXY(MouseEvent e){ 
     actualX = e.getScreenX() - stage.getX(); 
     actualY = e.getScreenY() - stage.getY(); 
    } 

    //When pressing and dragging the mouse it will move the window 
    @FXML 
    private void windowDragging(MouseEvent e) { 
     if (isMovable) { 
      stage.setX(e.getScreenX() - actualX); 
      stage.setY(e.getScreenY() - actualY); 
     } 

     else { 
      //setMin(); 
      stage.setX(e.getScreenX()); 
      stage.setY(e.getScreenY()); 
     } 
    } 

    //Update the status of the window from not movable to movable, after "normalize" effect 
    //from the dragging it when it's maximized 
    @FXML 
    private void updateStatus(MouseEvent e) { 
     if (stage.isMaximized() == false) { 
      isMovable = true; 
     } 
    } 


    // 
    // WINDOW RESIZING 
    // 

    /*onMouseEntered="#setMouseCursor" onMouseExited="#resetMouseCursor" onMouseDragged="#resizeWindow"*/ 

    @FXML 
    private void setMouseCursor (MouseEvent e) { 
     mainWindow.setCursor(Cursor.CROSSHAIR); 
    } 

    @FXML 
    private void resetMouseCursor (MouseEvent e) { 
     mainWindow.setCursor(Cursor.DEFAULT); 
    } 

    @FXML 
    private void resizeWindow (MouseEvent e) { 
     actualX = e.getScreenX() - stage.getX() + 13; 
     actualY = e.getScreenY() - stage.getY() + 10; 

     if (actualX % 5 == 0 || actualY % 5 == 0) { 
      if (actualX > MINWIDTH) { 
       stage.setWidth(actualX); 
      } else { 
       stage.setWidth(MINWIDTH); 
      } 

      if (actualY > MINHEIGHT) { 
       stage.setHeight(actualY); 
      } else { 
       stage.setHeight(MINHEIGHT); 
      } 
     } 
    } 


    // 
    // Internal methods 
    // 

    //Will set the window to MAXIMIZE size 
    private void setMax() { 
     stage.setMaximized(true); 
     btnResize.setVisible(false); 
     btnMax.setStyle("-fx-background-image: url('/res/dSquare.png');"); 
     mainWindow.setPadding(new Insets(0, 0, 0, 0)); 
    } 

    //Will set the window to NORMAL size 
    private void setMin() { 
     stage.setMaximized(false); 
     btnResize.setVisible(true); 
     btnMax.setStyle("-fx-background-image: url('/res/square.png');"); 
     mainWindow.setPadding(new Insets(SHADOWSPACE, SHADOWSPACE, SHADOWSPACE, SHADOWSPACE)); 

    } 
} 

Und im Main.java ich tun:

package application; 



import controller.MainWindowCtrl; 
import controller.minimalWindow.MinimalWindowCtrl; 
import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.stage.Stage; 
import javafx.stage.StageStyle; 
import javafx.scene.Scene; 
import javafx.scene.control.TabPane; 

public class Main extends Application { 

    final private int MINWIDTH = 750, MINHEGIHT = 500; 


    @Override 
    public void start(Stage primaryStage) { 
     try { 
      //Preparing the model 
      //TODO the interface of model 
      Object m = new Object(); 

      //Loading main content 
      FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/MainWindow.fxml")); 
      TabPane mainPane = loader.load(); 

      //Setting the model for the controller 
      ((MainWindowCtrl) loader.getController()).setModel(m); 

      //Creating the style for the custom window 
      MinimalWindowCtrl minimalWindowCtrl = new MinimalWindowCtrl(primaryStage, MINWIDTH, MINHEGIHT); 
      minimalWindowCtrl.setContent(mainPane); 

      //Making new scene 
      Scene scene = new Scene(minimalWindowCtrl, MINWIDTH, MINHEGIHT); 

      //Setting the style to the window (undecorating it) 
      primaryStage.initStyle(StageStyle.TRANSPARENT); 

      //Setting the scene on the window 
      primaryStage.setScene(scene); 

      //Showing the window 
      primaryStage.show(); 

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

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

    public static void close() {   
     System.exit(0); 
    } 
} 

Es hat einige Features fehlen, wie „Ich weiß nicht, warum die Symbole für Schaltflächen ist nicht gezeigt,“ die Schatten noch buggy ist, aber es funktioniert im Allgemeinen.

Dies ist das Ergebnis:

enter image description here

+0

KORREKT: Zum Anzeigen von Symbolen einfach das CSS ändern: von "/resources/x.png" nach "/view/minimalWindow/resources/x.png" – Martinocom

+0

Das gesamte Projekt kann von hier heruntergeladen werden: https://drive.google. com/open? id = 0B1rvaQED_VuvOGJLcGxnMkJRWXc. – Martinocom

2

Die Klasse Application repräsentiert die gesamte Anwendung. Es stellt kein Fenster dar. Windows in JavaFX wird durch die Klasse Stage repräsentiert. Die Application.start()-Methode ist der Einstiegspunkt (Start) für eine JavaFX-Anwendung: Sie sollten sie als Ersatz für die main in einer "normalen" Java-Anwendung betrachten. Die Unterklasseninstanz Application wird für Sie als Teil des Startprozesses erstellt, wodurch auch das FX-Toolkit gestartet wird. Im Oracle-JDK kann der Startprozess durch Aufrufen der Java-Laufzeit (z. B. durch Aufruf von java über die Befehlszeile) und durch Angabe einer Application-Unterklasse als auszuführende Klasse eingeleitet werden. Für Umgebungen, die den direkten Start von JavaFX-Anwendungen nicht unterstützen, sollten Sie eine main-Methode einschließen, die Application.launch(args) aufruft, d. H.

public class MyApp extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     // create objects and set up GUI, etc 
    } 

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

Folglich

  1. die Application Unterklasse ist von Natur aus nicht wiederverwendbar, und Sie sollen die start(...) Methode so gering wie möglich halten (es ist im Grunde nichts anderes tun soll, aber, na ja, die Anwendung starten).
  2. Sie sollten immer nur haben eine Instanz Ihrer Application Unterklasse in jeder JVM
  3. Als Folge (2), you should never use the Application class as the controller class

So zu tun, was Sie zu tun versuchen, ich glaube, Sie wollen Erstellen Sie eine separate MinimalWindow Klasse, die keine Application Unterklasse ist. Verwenden Sie das Muster Custom Component, das in der FXML-Dokumentation beschrieben wird, damit es seine eigene FXML lädt und sich selbst als Controller-Klasse einrichtet. Dann können Sie eine minimale Hauptklasse erstellen, die Application erweitert, deren start Methode erstellt und MinimalWindow zeigt.

+0

Ich vergesse völlig die Möglichkeit, die "Fenster" -Logik in einem benutzerdefinierten Steuerelement zu isolieren. Angenommen, ich erstelle das "MinimalWindow". Ich werde es in FXML verwenden, um den echten Inhalt zu umbrechen, zum Beispiel ein Tab-Fenster: ... . Da einige Controls von MinimalWindow einen direkten Bezug auf die Mainstage haben, muss ich dem Controller auf irgendeine Weise sagen, welches Fenster man verändern soll. Ich sollte einen statischen Getter in App.Java (App.getStage()) oder einen Setter direkt im Controller (MinimalWindow {... public void setStage (Stage s)} ...) tun? Was ist das Muster "mehr MVC"? – Martinocom