2016-08-17 5 views
0

FXMLでDialogPaneを構築していますが、onActionはButtonTypeの有効なパラメータではないため、ダイアログのボタンの押下にどのように応答するかを調べようとしています。 FXMLとControllerクラスを添付しました。 DialogPaneに関するドキュメントはほとんどなく、FXMLで行うことはあまりありませんので、どのように進めるかはわかりません。FXMLの設定ButtonType onAction

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

<?import javafx.scene.control.ButtonType?> 
<?import javafx.scene.control.DialogPane?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.TextField?> 
<?import javafx.scene.layout.ColumnConstraints?> 
<?import javafx.scene.layout.GridPane?> 
<?import javafx.scene.layout.RowConstraints?> 

<DialogPane fx:id="loginPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="LoginController"> 
    <content> 
     <GridPane hgap="5.0" vgap="5.0"> 
      <columnConstraints> 
       <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> 
       <ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="300.0" /> 
      </columnConstraints> 
      <rowConstraints> 
       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
      </rowConstraints> 
      <children> 
       <Label text="Driver Name" /> 
       <TextField fx:id="driverTxt" GridPane.columnIndex="1" /> 
       <Label text="URL" GridPane.rowIndex="1" /> 
       <TextField fx:id="urlTxt" GridPane.columnIndex="1" GridPane.rowIndex="1" /> 
       <Label text="Username" GridPane.rowIndex="2" /> 
       <TextField fx:id="userTxt" GridPane.columnIndex="1" GridPane.rowIndex="2" /> 
       <Label text="Password" GridPane.rowIndex="3" /> 
       <TextField fx:id="passTxt" GridPane.columnIndex="1" GridPane.rowIndex="3" /> 
      </children> 
     </GridPane> 
    </content> 
    <buttonTypes> 
     <ButtonType fx:id="loginButton" text="Login" /> 
     <ButtonType fx:id="cancelBtn" text="Cancel" /> 
    </buttonTypes> 
</DialogPane> 

import javafx.fxml.FXML; 
import javafx.scene.Scene; 
import javafx.scene.control.ButtonType; 
import javafx.scene.control.DialogPane; 
import javafx.scene.control.TextField; 

public class LoginController { 

    @FXML 
    DialogPane loginPane; 
    @FXML 
    TextField driverTxt; 
    @FXML 
    TextField urlTxt; 
    @FXML 
    TextField userTxt; 
    @FXML 
    TextField passTxt; 
    @FXML 
    ButtonType loginButton; 

    @FXML 
    private void loginButtonAction(){ 
     // How do I do something here 
    } 

    public void initialize() { 
     driverTxt.setText("org.postgresql.Driver"); 
     urlTxt.setText("jdbc:postgresql://localhost/postgres"); 
     userTxt.setText("postgres"); 
     passTxt.setText("postgres"); 
    } 

} 

答えて

2

通常、これを行う必要はありません。 Dialog<ButtonType>showAndWait()メソッドでは、通常、DialogPaneと表示され、押されたボタンを表すOptional<ButtonType>が返されます。だから、通常の使用では

public class LoginController { 

    public static final ButtonType LOGIN = new ButtonType("Login"); 

    @FXML 
    DialogPane loginPane; 
    @FXML 
    TextField driverTxt; 
    @FXML 
    TextField urlTxt; 
    @FXML 
    TextField userTxt; 
    @FXML 
    TextField passTxt; 


    public void initialize() { 
     driverTxt.setText("org.postgresql.Driver"); 
     urlTxt.setText("jdbc:postgresql://localhost/postgres"); 
     userTxt.setText("postgres"); 
     passTxt.setText("postgres"); 
    } 

    public String getDriver() { 
     return driverTxt.getText(); 
    } 

    public String getUrl() { 
     return urlTxt.getText(); 
    } 

    public String getUser() { 
     return userTxt.getText(); 
    } 

    public String getPass() { 
     return pass.getText(); 
    } 

} 

ようなものになると、あなたのFXMLファイルを次のように変更します:

<buttonTypes> 
    <LoginController fx:constant="LOGIN" /> 
    <ButtonType fx:constant="CANCEL" /> 
</buttonTypes> 

次にあなたがこれを使用します。公開する代わりに

Dialog<ButtonType> dialog = new Dialog<>(); 
FXMLLoader dialogLoader = new FXMLLoader(getClass().getResource("Login.fxml")); 
dialog.setDialogPane(dialogLoader.load()); 
LoginController controller = dialogLoader.getController(); 
dialog.showAndWait().filter(LoginController.LOGIN::equals) 
    .ifPresent(button -> { 
     String driver = controller.getDriver(); 
     // etc etc 
     // process login... 
    }); 

テキストフィールドのテキストを使用する場合は、テキストフィールドを読み込んで、必要な処理をしたコントローラ自体にprocessLogin()メソッドを定義することができます。

public class LoginController { 

    public static final ButtonType LOGIN = new ButtonType("Login"); 

    @FXML 
    DialogPane loginPane; 
    @FXML 
    TextField driverTxt; 
    @FXML 
    TextField urlTxt; 
    @FXML 
    TextField userTxt; 
    @FXML 
    TextField passTxt; 


    public void initialize() { 
     driverTxt.setText("org.postgresql.Driver"); 
     urlTxt.setText("jdbc:postgresql://localhost/postgres"); 
     userTxt.setText("postgres"); 
     passTxt.setText("postgres"); 
    } 

    public void processLogin() { 
     String driver = driverTxt.getText(); 
     // etc... 
     // process login... 
    } 
} 

は、ちょうどあなたが本当にログインボタンとonActionハンドラを登録する必要がある場合は、

// ... 
dialog.showAndWait().filter(LoginController.LOGIN::equals) 
    .ifPresent(button -> controller.processLogin()); 

を行うコントローラでinitialize()方法でそれを行う:

public void initialize() { 
    driverTxt.setText("org.postgresql.Driver"); 
    urlTxt.setText("jdbc:postgresql://localhost/postgres"); 
    userTxt.setText("postgres"); 
    passTxt.setText("postgres"); 

    Button login = (Button) loginPane.lookupButton(loginButton); 
    login.setOnAction(e -> { /* ... */ }); 
} 

が、これはあります実際にはダイアログペインAPIの意図された使用に反しています。


一つ最終の代替案はDialogPanecreateButtonメソッドをオーバーライドすることであろう。これを行うには、DialogPaneというサブクラスが必要です。これは、FXML custom component patternの使用を意味します。

だから、これは次のようになります:

public class LoginPane extends DialogPane { 

    public static final ButtonType LOGIN = new ButtonType("Login"); 

    @FXML 
    TextField driverTxt; 
    @FXML 
    TextField urlTxt; 
    @FXML 
    TextField userTxt; 
    @FXML 
    TextField passTxt; 

    public LoginPane() { 
     try { 
      FXMLLoader loader = new FXMLLoader(getClass().getResource("LoginPane.fxml")); 
      loader.setRoot(this); 
      loader.setController(this); 
      loader.load(); 
     } catch (IOException exc) { 
      // bad if you get here... 
      throw new UncheckedIOException(exc); 
     } 
    } 

    @Override 
    public Node createButton(ButtonType buttonType) { 
     Node button = super.createButton(buttonType); 
     if (buttonType == LOGIN) { 
      ((Button) button).setOnAction(e -> processLogin()); 
     } 
     return button ; 
    } 


    public void initialize() { 
     driverTxt.setText("org.postgresql.Driver"); 
     urlTxt.setText("jdbc:postgresql://localhost/postgres"); 
     userTxt.setText("postgres"); 
     passTxt.setText("postgres"); 
    } 

    public void processLogin() { 
     String driver = driverTxt.getText(); 
     // etc... 
     // process login... 
    } 
} 

、あなたが探している場合FXMLは、その後

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

<?import javafx.scene.control.ButtonType?> 
<?import javafx.scene.control.DialogPane?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.TextField?> 
<?import javafx.scene.layout.ColumnConstraints?> 
<?import javafx.scene.layout.GridPane?> 
<?import javafx.scene.layout.RowConstraints?> 

<fx:root type="DialogPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1"> 
    <content> 
     <GridPane hgap="5.0" vgap="5.0"> 
      <columnConstraints> 
       <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> 
       <ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="300.0" /> 
      </columnConstraints> 
      <rowConstraints> 
       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
       <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> 
      </rowConstraints> 
      <children> 
       <Label text="Driver Name" /> 
       <TextField fx:id="driverTxt" GridPane.columnIndex="1" /> 
       <Label text="URL" GridPane.rowIndex="1" /> 
       <TextField fx:id="urlTxt" GridPane.columnIndex="1" GridPane.rowIndex="1" /> 
       <Label text="Username" GridPane.rowIndex="2" /> 
       <TextField fx:id="userTxt" GridPane.columnIndex="1" GridPane.rowIndex="2" /> 
       <Label text="Password" GridPane.rowIndex="3" /> 
       <TextField fx:id="passTxt" GridPane.columnIndex="1" GridPane.rowIndex="3" /> 
      </children> 
     </GridPane> 
    </content> 
    <buttonTypes> 
     <LoginPane fx:constant="LOGIN" /> 
     <ButtonType fx:constant="CANCEL" /> 
    </buttonTypes> 
</fx:root> 

のようになります。あなたはとても

Dialog dialog = new Dialog(); 
dialog.setDialogPane(new LoginPane()); 
dialog.showAndWait(); 

と、このバージョンを使用します可能な限りログインペインとfxmlにカプセル化するには、これはおそらく最もクリーンなオプションです。 の使用は、DialogDialogPaneのAPIドキュメントに完全に記載されています。

+0

最後に、DialogPaneをDialogPaneで囲むようにFXMLを更新しました.FXMLLoaderを使用してFMXLからDialogのインスタンスを作成し、例を使用してshowAndWaitを作成することができました。最も難しい部分は、私が見つけたすべての例がFXMLをベースとして使用していなかったことでした。私はできるだけ多くのことをやろうとしています。 – Shawn

関連する問題