Настройка ListView в JavaFX с FXML
Я хочу настроить представление списка в javafx. Здесь мне нужно связать несколько компонентов в ячейке списка следующим образом: один ярлык, одно текстовое поле, одна кнопка под одним HBox и две кнопки, одна гиперссылка, одна метка в другом HBox и эти HBox приходят под один 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>
3 ответов
я понимаю ваш вопрос. Есть в основном два способа установить элементы в Listview:
1. создать ObservableList и установить элементы ListView С ObservableList (listView.setItems(observableList)).
2. использовать setCellFactory() метод ListView класса.
вы предпочли бы использовать setCellFactory() метод, потому что этот подход упрощает процесс, а также помогает отделить бизнес-логику и пользовательский интерфейс (FXML-файл).
вот более подробное объяснение:
1. создайте новый файл FXML с именем listview.fxml содержат ListView и выберите ListViewController класс в качестве контроллера:
<?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.
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();
            }
        });
    }
}
3. сначала вам нужно установить значение ObservableList. это очень важно.
Затем установите элементы списка с помощью ObservableList, а вызов setCellFactory() метод ListView. В данном примере я просто беру String значения добавить их в String set (the Set<String> stringSet).
4. когда setCellFactory() метод вызывается на ListView, он вернет ListCell. Поэтому для простоты я добавил класс, который расширяет ListCell и setGraphic() способ для ListCell() и выберите пункты ListCell.
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, который будет содержать другие компоненты, как дети.
The HBox затем к ListCell.
 <?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>
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.
надеюсь, это поможет.
пример выше,@Anvay нужна пара настроек для работы. Это простые вещи, чтобы установить на трассе.
- ListViewController должен быть запущен в потоке приложения JavaFX.
- вы можете вызвать только введенные элементы @FXML из JavaFX инициализации() метод
- необходимо вызвать setListView ()
- набор строк в примере должен быть выделен с новым перед вызовом setListView ().
listviewcontroller ниже работает с этими изменениями. Я изменился"методы stringset" в "stringList". Контроллер в значительной степени является образцом контроллера, предоставляемого Сцена 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 должна быть запущена в методе main () из приложения JavaFX. Netbeans conviently предоставляет большую часть этой структуры из приложения 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);
    }
}
ответ Anvay по какой-то причине не работал для меня, что я должен был сделать, чтобы исправить это были просто очень маленькие настройки:
- удалить оператор импорта данных из listCellItem.FXML-файл
- как говорится в комментарии ниже поста в данных.java put hBox = fmxlLoader.load ()
- 
У меня также был основной класс (intellij auto generated). 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); }
Я знаю, что это было, вероятно, очевидно для большинства экспертов, но эти проблемы озадачивали меня в течение нескольких часов, пока я отлаживал.
