2016-05-30 9 views
0

私は家族の注文管理システムを作成しています。ユーザーがケーキ、クッキー、カップケーキなどの注文をするかどうかをユーザーが選択すると、アプリケーションを実行時に更新できるようにする必要があります。ScalaFXMLアプリケーション:CheckBoxのランタイム時にフォームにコンポーネントを追加クリック

私が解決しようとしてきたのは、空のペインをフォームに追加し、クリックするとフォームが別のFXMLファイルにあるコンポーネントでペインに移入します。問題はこれです:コントローラの私のフィールドがすべてnullに設定されているので、私がペインを更新しようとすると、nullポインタ例外が発生します。なぜ私のフィールドのすべてがnullであるのか分かりませんが、@sfxmlアノテーションは私が設定した方法と合わないという疑いがあります。おそらく、これをすべて行うより良い方法があります。どんな助けもありがとうございます。ここまで私がこれまで持っていたものがあります。私は実証可能な例を挙げようとします。 Iコンポーネントを追加する予定の領域は単にチェックボックスの下に、フォーム内のコメントによって表示されている:

フォーム:check_box_selected:Form.FXML

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

<?import javafx.geometry.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 
<BorderPane id="rootLayout" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" 
      prefHeight="500.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" 
      fx:controller="controller.FormController"> 
    <center> 
     <VBox prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER"> 
      <children> 
       <TilePane maxHeight="119.0" minHeight="100.0" prefHeight="119.0" prefWidth="485.0"> 
        <children> 
         <HBox maxHeight="30.0" maxWidth="485.0" minHeight="10.0" prefHeight="14.0" prefWidth="485.0" 
           TilePane.alignment="CENTER"> 
          <children> 
           <TextField fx:id="fNameField" maxHeight="30.0" minHeight="17.0" prefHeight="18.0" 
              prefWidth="156.0" promptText="first name"/> 
           <TextField fx:id="lNameField" maxHeight="30.0" minHeight="30.0" promptText="last name"/> 
           <TextField fx:id="dateField" maxHeight="30.0" minHeight="26.0" prefHeight="30.0" 
              prefWidth="151.0" promptText="due date"/> 
          </children> 
         </HBox> 
         <HBox maxHeight="30.0" maxWidth="485.0" minHeight="10.0" prefHeight="14.0" prefWidth="485.0" 
           TilePane.alignment="CENTER"> 
          <children> 
           <TextField fx:id="phoneNumber" maxHeight="30.0" minHeight="17.0" prefHeight="18.0" 
              prefWidth="156.0" promptText="phone number"/> 
           <TextField fx:id="email" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" 
              prefWidth="331.0" promptText="e-mail"/> 
          </children> 
         </HBox> 

         <TextField fx:id="streetField" maxHeight="30.0" minHeight="30.0" promptText="street"/> 
         <HBox maxHeight="44.0" minHeight="0.0" prefHeight="27.0" prefWidth="485.0"> 
          <children> 
           <TextField fx:id="cityField" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" 
              prefWidth="374.0" promptText="city"/> 
           <TextField fx:id="stateField" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" 
              prefWidth="109.0" promptText="state"/> 
           <TextField fx:id="zipField" maxHeight="30.0" minHeight="30.0" prefHeight="30.0" 
              prefWidth="136.0" promptText="zip"/> 
          </children> 
         </HBox> 
        </children> 
       </TilePane> 
       <HBox maxHeight="65.0" minHeight="30.0" prefHeight="33.0" prefWidth="485.0" spacing="95.0"> 
        <children> 
         <CheckBox fx:id="cakeCB" mnemonicParsing="false" text="CK" onAction="#checkboxSelected"> 
          <HBox.margin> 
           <Insets top="8.0"/> 
          </HBox.margin> 
         </CheckBox> 
         <CheckBox fx:id="cookiesCB" mnemonicParsing="false" text="CO"> 
          <HBox.margin> 
           <Insets top="8.0"/> 
          </HBox.margin> 
         </CheckBox> 
         <CheckBox fx:id="cupcakesCB" mnemonicParsing="false" text="CC"> 
          <HBox.margin> 
           <Insets top="8.0"/> 
          </HBox.margin> 
         </CheckBox> 
         <CheckBox fx:id="otherCB" mnemonicParsing="false" text="O"> 
          <HBox.margin> 
           <Insets top="8.0"/> 
          </HBox.margin> 
         </CheckBox> 
        </children> 
        <padding> 
         <Insets left="18.0"/> 
        </padding> 
       </HBox> 
       <HBox> 

       <!-- 


       included data here--> 
       <Pane id="selectionQuestions" /> 
       </HBox> 
       <TextArea fx:id="notes" prefHeight="200.0" prefWidth="200.0"/> 
       <HBox alignment="BOTTOM_RIGHT" maxHeight="30.0" minHeight="30.0" prefHeight="100.0" prefWidth="200.0"> 
        <children> 
         <Button id="submitOrderButton" mnemonicParsing="false" onAction="#submitOrder" text="submit"/> 
        </children> 
       </HBox> 
      </children> 
     </VBox> 
    </center> 
    <padding> 
     <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> 
    </padding> 
</BorderPane> 

はHBoxのエリアに追加します。 FXML

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

    <?import javafx.scene.layout.HBox?> 
    <?import javafx.scene.control.Label?> 

    <HBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" minWidth="30" minHeight="30"> 
     <Label text="Here's my selected checkbox label" /> 
    </HBox> 

FormController.scala:

package controller 

import javafx.event.ActionEvent 
import javafx.scene._ 
import javafx.stage.Stage 

import javafx.scene.layout.Pane 
import javafx.scene.control.CheckBox 
import scalafxml.core.macros.sfxml 
import scalafxml.core.{FXMLView, NoDependencyResolver} 
import javafx.fxml.FXMLLoader 


@sfxml 
class FormController(private val selectionQuestions: Pane, 
        private val cakeCB: CheckBox, 
        private val cookiesCB: CheckBox, 
        private val cupcakesCB: CheckBox, 
        private val otherCB: CheckBox) { 

    def submitOrder(actionEvent: ActionEvent) { 
    val source = actionEvent.getSource.asInstanceOf[Node].getScene.getWindow.asInstanceOf[Stage] 
    source.hide; 
    } 

    def checkboxSelected(actionEvent: ActionEvent) { 
    val source = actionEvent.getSource 
    val box: CheckBox = source.asInstanceOf[CheckBox] 

    box.getId match { 
     case "cakeCB" => { 
     val resource = getClass.getResource("/scala/cake_box_selected.fxml") 
     val root = FXMLView(resource, NoDependencyResolver) 

     //This is the null pointer => 
     selectionQuestions.getChildren.clear 
     selectionQuestions.getChildren.add(root) 
     } 
    } 
    } 

} 

答えて

1

あなたはScalaFX Versに使用する必要がありますコントローラクラスのコンストラクタ内のコントロールのイオン。だから、単純に代わり

import javafx.scene.layout.Pane 
import javafx.scene.control.CheckBox 

使用

import scalafx.scene.layout.Pane 
import scalafx.scene.control.CheckBox 

のこれは修正されなければならないscalafxmlライブラリの制限があります。 (そのための問題を作成しました:https://github.com/vigoo/scalafxml/issues/19)をScalaFXタイプを使用している場合ActionEventのソースを使用しようとすると、あなたがコメントで説明したように

を編集して、それはキャスト例外で失敗します。このプロパティはタイプがObjectで、タイプがjavafx.scene.control.CheckBoxのJavaFXコントロール自体への参照を保持します。これは、マクロの制限のために使用しなければならないScalaFXラッパーに暗黙的に変換できます。 - コンパイラは、変換の世話をする

  • あなたはJavaFXのタイプを使用する必要があり、キャスト、を除いてどこでも
  • ScalaFXタイプを使用します。

    だからソリューションは、することです。

例:

import scalafx.event.ActionEvent 
import scalafx.scene.control.{CheckBox, ComboBox, TextField} 

// ... 

    def testCheckBoxAction(event: ActionEvent): Unit = { 
    val source: CheckBox = event.source.asInstanceOf[javafx.scene.control.CheckBox] 
    // ... 
    } 
+0

が、私はそれらの輸入品を使用した理由は、実際にあります。私は、コントローラ内のクリックのソースを「取得」する必要があるとき、私はこの構文を使用します。 ヴァル・ソース= actionEvent.getSource ヴァル・ボックス:チェックボックス= source.asInstanceOf [チェックボックス] 私は場合scalafxのインポートを使用して、javafx.scene.controlというClassCastExceptionを取得します。CheckBoxはscalafx.scene.control.CheckBoxにキャストできません。だから、私は今まで私のコントローラでjavafxのバージョンを使用しています。あなたが知っている私のコントローラーでscalafxバージョンを使用できるようにする別の方法がありますか? –

+0

FXMLのインポートがjavafxで、私のコントローラにscalafxを使用すると例外が発生するので、キャスト例外があることは知っています。 –

+0

'@sxml'は、イベントハンドラのパラメータを変換し、scalafxの' ActionEvent'ラッパを使用することもできます。これで問題が解決するかどうかは不明ですが、後で問題を再現しようとします。 – vigoo

関連する問題