web-dev-qa-db-ja.com

FXMLを使用してJavaFXでListViewをカスタマイズする

Javafxでリストビューをカスタマイズしたい。ここでは、1つのラベル、1つのテキストフィールド、1つのボタンと2つのボタン、1つのハイパーリンク、1つのラベルを別のHBoxのように、リストセルの複数のコンポーネントをバインドする必要があります。これらのHBoxは1つのVBoxに、このVBoxは単一のリストセルとそれが繰り返され、リストビューが作成されます。

コードは

<ListView fx:id="ListView" layoutX="0" layoutY="30" prefWidth="600" prefHeight="300">
    <HBox fx:id="listBox" alignment="CENTER_LEFT">
        <padding><Insets top="5" bottom="5" left="5"></Insets> </padding>
        <HBox alignment="CENTER_LEFT" prefWidth="170" minWidth="88">
            <Label fx:id="surveyName" text="Field A" styleClass="Name"></Label>
        </HBox>
        <VBox styleClass="Description" prefWidth="155" minWidth="86">

            <HBox>
                <HBox styleClass="surveyDesIcon" prefWidth="20" prefHeight="16"></HBox>
                <Label fx:id="surveyCode" text="PRW3456HJ"></Label>
            </HBox>
            <HBox>
                <HBox styleClass="DateIcon" prefWidth="20" prefHeight="16"></HBox>
                <Label fx:id="Date" text="PRW3456HJ"></Label>
            </HBox>
        </VBox>
        <HBox fx:id="Status" prefWidth="160" minWidth="80">
            <Label fx:id="StatusLabel" text="Checking Files.."/>
        </HBox>
        <HBox fx:id="StatusIcon1" prefWidth="50" prefHeight="50" alignment="CENTER">
            <Label styleClass="StatusIcon1" prefWidth="24" prefHeight="24" alignment="CENTER"/>
        </HBox>
        <HBox fx:id="StatusIcon2" prefWidth="50" prefHeight="50" styleClass="StatusIconBox" alignment="CENTER">
            <Hyperlink styleClass="StatusIcon2" prefWidth="24" maxHeight="24" alignment="CENTER"/>
        </HBox>
    </HBox>
</ListView>
35

あなたの質問を理解しています。 Listviewにアイテムを設定するには、主に2つの方法があります。

1。ObservableListを作成し、ListViewの項目をObservableListlistView.setItems(observableList))で設定します。

2。ListViewクラスのsetCellFactory()メソッドを使用します。

setCellFactory()メソッドを使用することをお勧めします。このアプローチはプロセスを単純化し、ビジネスロジックとUI(FXML)を分離するのに役立つためです。


ここに詳細な説明があります:


1。ListViewを含む_listview.fxml_という名前の新しいFXMLファイルを作成し、ListViewControllerクラスをコントローラーとして設定します。

ファイル:listview.fxml

_<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.ListView?>
<?import demo.ListViewController?>

<GridPane xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
     <ListView fx:id="listView"/>
</GridPane>
_

2。コントローラーを作成し、ListViewControllerという名前を付けます。
コントローラーは_listview.fxml_ファイルをロードし、listviewにアクセスできます。

ファイル:ListViewController.Java

_package demo;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.util.Callback;
import Java.io.IOException;
import Java.util.Set;

public class ListViewController
{
    @FXML
    private ListView listView;
    private Set<String> stringSet;
    ObservableList observableList = FXCollections.observableArrayList();

    public ListViewController()
    {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/listview.fxml"));
        fxmlLoader.setController(this);
        try
        {
            Parent parent = (Parent)fxmlLoader.load();
            Scene scene = new Scene(parent, 400.0 ,500.0);
        }
        catch (IOException e)
        {
            throw new RuntimeException(e);
        }
    }

    public void setListView()
    {
        stringSet.add("String 1");
        stringSet.add("String 2");
        stringSet.add("String 3");
        stringSet.add("String 4");
        observableList.setAll(stringSet);
        listView.setItems(observableList);
        listView.setCellFactory(new Callback<ListView<String>, javafx.scene.control.ListCell<String>>()
        {
            @Override
            public ListCell<String> call(ListView<String> listView)
            {
                return new ListViewCell();
            }
        });
    }
}
_

最初に、ObservableListの値を設定する必要があります。 これは非常に重要です。
次に、ObservableListを使用してリストの項目を設定し、ListViewsetCellFactory()メソッドを呼び出します。与えられた例では、Stringの値を取り、それらをStringセット(_Set<String> stringSet_)に追加するだけです。


4。ListViewsetCellFactory()メソッドが呼び出されると、ListCellが返されます。そこで、簡単にするために、ListCellを拡張するクラスを追加し、setGraphic()メソッドがListCell()に存在し、ListCellの項目を設定します。

ファイル:ListViewCell.Java

_package demo;

import javafx.scene.control.ListCell;

public class ListViewCell extends ListCell<String>
{
    @Override
    public void updateItem(String string, boolean empty)
    {
        super.updateItem(string,empty);
        if(string != null)
        {
            Data data = new Data();
            data.setInfo(string);
            setGraphic(data.getBox());
        }
    }
}
_

5。 _listCellItem.fxml_をロードし、他のコンポーネントを子として含むHBoxを返すクラスを追加しました。
HBoxは、ListCellに設定されます。

ファイル:listCellItem.fxml

_ <?import demo.Data?>
 <?import javafx.scene.layout.HBox?>
 <?import javafx.scene.control.Label?>

<HBox xmlns:fx="http://javafx.com/fxml" fx:id="hBox">
<children>
    <Label  fx:id="label1"/>
    <Label  fx:id="label2"/>
</children>
</HBox>
_

ファイル:Data.Java

_package demo;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import Java.io.IOException;

public class Data
{
    @FXML
    private HBox hBox;
    @FXML
    private Label label1;
    @FXML
    private Label label2;

    public Data()
    {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/listCellItem.fxml"));
        fxmlLoader.setController(this);
        try
        {
            fxmlLoader.load();
        }
        catch (IOException e)
        {
            throw new RuntimeException(e);
        }
    }

    public void setInfo(String string)
    {
        label1.setText(string);
        label2.setText(string);
    }

    public HBox getBox()
    {
        return hBox;
    }
}
_

この方法を使用すると、setCellFactory()メソッドを使用して、ビジネスロジックとFXMLであるものを分離できます。

これが役に立てば幸いです。

77
Anvay

上記の@ Anvayの例では、いくつかの調整が必要です。これらはオントラックに設定する簡単なものです。

  1. ListViewControllerは、JavaFXアプリケーションスレッドで実行する必要があります。
  2. 挿入された@FXML要素は、JavaFX initialize()メソッドからのみ呼び出すことができます
  3. SetListView()を呼び出す必要があります
  4. 例のstringSetには、setListView()を呼び出す前に、newを割り当てる必要があります。

以下のListViewControllerは、これらの変更に対応しています。 「stringSet」をリスト「stringList」に変更しました。コントローラーは、ほとんどScene Builder 2によって提供されるサンプルコントローラーです。

 public class ListViewController 
 {

     @FXML private   ResourceBundle      resources;

     @FXML private   URL                 location;

     @FXML private   ListView            listView;

     private         List<String>        stringList     = new ArrayList<>(5);
     private         ObservableList      observableList = FXCollections.observableArrayList();

     public void setListView(){

         stringList.add("String 1");
         stringList.add("String 2");
         stringList.add("String 3");
         stringList.add("String 4");

         observableList.setAll(stringList);

         listView.setItems(observableList);

         listView.setCellFactory(
             new Callback<ListView<String>, javafx.scene.control.ListCell<String>>() {
                 @Override
                 public ListCell<String> call(ListView<String> listView) {
                     return new ListViewCell();
                 }
             });
     }

     @FXML
     void initialize() {
         assert listView != null : "fx:id=\"listView\" was not injected: check your FXML file 'CustomList.fxml'.";

         setListView();
     }

 }//ListViewController

JavaFXプラットフォームは、JavaFXアプリケーションのmain()メソッドで起動する必要があります。 Netbeansは、Maven JavaFXアプリケーションテンプレートからこの構造のほとんどを便利に提供します。

public class MainApp extends Application {

    @Override
    public void start(Stage stage) throws Exception {

        Parent root = FXMLLoader.load(getClass().getResource("/fxml/CustomList.fxml"));

        Scene scene = new Scene(root);
        scene.getStylesheets().add("/styles/Styles.css");

        stage.setTitle("CustomList");
        stage.setScene(scene);
        stage.show();
    }

    /**
     *  The main() method is ignored in correctly deployed JavaFX application.
     * 
     *  @param args the command line arguments
     **/
    public static void main(String[] args) {

        launch(args);
    }
}
4
will

何らかの理由でAnvayによる答えは私にはうまくいきませんでした、それを修正するために私がしなければならなかったことは、ほんのいくつかの非常に小さな調整でした:

  1. listCellItem.fxmlからインポートデータステートメントを削除します
  2. 投稿の下のコメントがData.Javaで述べているように、hBox = fmxlLoader.load()を置きます
  3. メインクラス(intellij自動生成)もありました。

    public class MainMain extends Application {
    
    @Override
    public void start(Stage primaryStage) throws Exception{
    
    FXMLLoader fxmlLoader = new 
    FXMLLoader(getClass().getResource("MainController.fxml"));
    try
    {
        Parent root = fxmlLoader.load();
    
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Title");
        primaryStage.show();
    }
    catch (IOException e)
    {
        throw new RuntimeException(e);
    }
    }
    
    
    
    public static void main(String[] args) {
        launch(args);
    }
    

これはおそらくここのほとんどの専門家にとって明らかなことだと思いますが、これらの問題はデバッグ中に何時間も困惑しました。

2
Velo