2017-12-30 38 views
2

をIDを与えることなく、これは私のFXML階層は次のようになります。アクセスの繰り返しコントロールの各コントロールに

  • AnchorPane
    • のVBox
      • HBox
        • コンボボックス:文字列:[チャンネル名]
        • のTextField:[開始前の遅延]
        • ボタン:[記録開始トリガ]
      • のHBox
        • コンボボックス:文字列:[チャンネル名]
        • TextField:[開始までの遅延]
        • ボタン:[記録開始トリガ]
      • のHBox
        • コンボボックス:文字列:[チャンネル名]
        • のTextField:[開始前の遅延]
        • ボタン:[トリガー記録開始]

各ボックス内のコントロールにアクセスするには、-in my controller-のIDを内部の各コントロールに渡す必要がありません。

何私はcurrentyこのようなことの ホールドを取得するために、各要素のインデックスを使用しているやっている:

@FXML 
public void startRecording(MouseEvent event) { 
    ObservableList<Node> curChildNodes = ((Node) event.getTarget()).getParent().getChildrenUnmodifiable(); 
    String    channelName = ((ComboBox<String>) (curChildNodes.get(0))).getSelectionModel().getSelectedItem(); 
    long     delay   = Long.parseLong(((TextField) curChildNodes.get(1)).getText()); 

    Stream stream = new Stream(channelName, delay); 
    Recorder recorder = new Recorder(stream); 
    recorder.startAfterDelay(); 
} 

私は退屈場合を得ることができます使用しています方法を私はそのHBoxでより多くのコントロールを持っている、または私が階層内での位置を変更することを決めた場合。

もっと良い方法がありますか?

答えて

2

ComboBoxHBoxを表す(それ自身のコントローラクラスを有する)別FXMLファイルを作成TextField、及びButton。次に、<fx:include>を使用してメインのFXMLファイルに組み込みます。

必要に応じて、"Nested Controllers"テクニックを使用して、「メイン」コントローラで、含まれているFXMLファイルの各インスタンスに対して作成されたコントローラインスタンスを参照できます。あなたが

を行うことができ、コントローラあなたの "メイン" FXMLで次に

public class ChannelController { 

    @FXML 
    private ComboBox<String> channel ; 
    @FXML 
    private TextField delay ; 
    @FXML 
    private Button start ; 

    @FXML 
    private void startRecording(ActionEvent event) { 
     String channelName = channel.getValue(); 
     long delayTime = Long.parseLong(delay.getText()); 
     // ... 
    } 
} 

<HBox xmlns:fx="..." fx:controller="myapp.ChannelController"> 
    <ComboBox fx:id="channel"/> 
    <TextField fx:id="delay"/> 
    <Button text="Start" fx:id="start" onAction="startRecording"/> 
</HBox> 

ですから、このようなものを作成することができます(私はこのChannelControls.fxml呼びます)を

<AnchorPane xmlns:fx="..." fx:controller="myapp.MainController" > 
    <VBox> 
     <fx:include src="ChannelControls.fxml"/> 
     <fx:include src="ChannelControls.fxml"/> 
     <fx:include src="ChannelControls.fxml"/> 
    </VBox> 
</AnchorPane> 

メインコントローラのChannelControllerのインスタンスにアクセスする必要がある場合は、広告D <fx:include>fx:id秒:

<fx:include src="ChannelControls.fxml" fx:id="channel1" /> 
<fx:include src="ChannelControls.fxml" fx:id="channel2" /> 
<!-- etc --> 

、その後、あなたがfx:id値に"Controller"を追加することによって、コントローラにアクセスすることができます。

public class MainController { 

    @FXML 
    private ChannelController channel1Controller ; 
    @FXML 
    private ChannelController channel2Controller ; 

    public void initialize() { 
     // do anything you need with channel1Controller, etc. 
    } 
} 

この上のわずかな変形はHBoxを実装することですその部分は"Custom Component"となります。これは、実際にはFXMLファイルとコントローラクラスの作成役割を逆転させるだけです(コントローラを自動的に作成するFXMLファイルを読み込むのではなく、コントローラを作成してFXMLを自動的に読み込みます)。ですから、

public class ChannelControls extends HBox { 

    @FXML 
    private ComboBox<String> channel ; 
    @FXML 
    private TextField delay ; 
    @FXML 
    private Button start ; 

    public ChannelControls() { 
     try { 
      FXMLLoader loader = new FXMLLoader("ChannelControls.fxml"); 
      loader.setRoot(this); 
      loader.setController(this); 
      loader.load(); 
     } catch (IOException exc) { 
      // this is pretty much fatal: 
      throw new UncheckedIOException(exc); 
     } 
    } 

    @FXML 
    private void startRecording(ActionEvent event) { 
     String channelName = channel.getValue(); 
     long delayTime = Long.parseLong(delay.getText()); 
     // ... 
    } 

    // other methods as needed 
} 

を作成することができますChannelControls.fxmlへの唯一の変更は、ルート要素にある:あなたがfx:controller属性を削除する必要があることに注意してください。

<fx:root type="HBox" xmlns:fx="..."> 
    <ComboBox fx:id="channel"/> 
    <TextField fx:id="delay"/> 
    <Button text="Start" fx:id="start" onAction="startRecording"/> 
</fx:root> 

は今、あなたのメインのFXMLファイルがちょうど

<AnchorPane xmlns:fx="..." fx:controller="myapp.MainController" > 
    <VBox> 
     <ChannelControls/> 
     <ChannelControls/> 
     <ChannelControls/> 
    </VBox> 
</AnchorPane> 
を必要とします

<ChannelControls>要素にfx:idを追加し、必要に応じてメインコントローラに直接注入することができます。このアプローチにより、ChannelControlsクラスのプロパティとメソッドを公開し、メインコントローラimhoにアクセスするのがやや簡単になります。

+0

ただ一つのjavafxの質問は、** James_D **からの回答なしでは通過しません!私は今それを試してみます、ありがとう! –

+1

@JawnyThompsonいくつかのコード例で更新されました。 –

+0

トム・ジェームズありがとう!完璧に働いた! –

関連する問題