JavaFX custom listView

Wollte ich Fragen, der beste Weg, um ein ListView-Steuerelement mit benutzerdefinierten Objekten in JavaFX, ich möchte eine Liste, die jedes Element sieht wie folgt aus:

JavaFX custom listView

Suchte ich und fand, dass die meisten Menschen es tun, mit dem Zell-factory-Methode. Gibt es irgendeine andere Möglichkeit? Zum Beispiel mit einer custome fxml?

Hier mein fmxl Archiv

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

<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="557.0" prefWidth="1012.0" style="-fx-background-color: #0288D1;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="desktop_tasker.FXMLTaskerController">
   <children>
      <SplitPane dividerPositions="0.5" layoutX="-8.0" layoutY="35.0" prefHeight="529.0" prefWidth="1027.0" style="-fx-background-color: #EEEEEE;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="28.0">
        <items>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
               <children>
                  <ListView fx:id="list_todo" onEditStart="#handleButtonAction" prefHeight="527.0" prefWidth="502.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
               </children></AnchorPane>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="527.0" prefWidth="640.0">
               <children>
                  <ListView fx:id="list_done" onEditStart="#handleButtonAction" prefHeight="527.0" prefWidth="502.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
               </children></AnchorPane>
        </items>
      </SplitPane>
      <MenuBar prefHeight="30.0" prefWidth="1012.0">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem mnemonicParsing="false" text="Close" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Edit">
            <items>
              <MenuItem mnemonicParsing="false" text="Delete" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Help">
            <items>
              <MenuItem mnemonicParsing="false" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
   </children>
</AnchorPane>

Und hier ist mein Objekt Aufgabe:

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by Usuario on 26/10/2017.
 */

public class Task implements Comparable<Task> {
    private String title;
    private String attendant;
    private String comment;
    private String description;
    private int priority;
    private String creationDate;
    private boolean state;
    private boolean visible;

    public Task(String title, String attendant, String comment, String description, int priority) {
        this.title = title;
        this.attendant = attendant;
        this.comment = comment;
        this.description = description;
        this.priority = priority;
        this.creationDate = setCreationDate();
        this.state = false;
        this.visible = true;
    }

    public Task(String title, String attendant, String comment, String description, int priority, String date, boolean state, boolean visible) {
        this.title = title;
        this.attendant = attendant;
        this.comment = comment;
        this.description = description;
        this.priority = priority;
        this.creationDate = date;
        this.state = state;
        this.visible = visible;
    }

    private static String setCreationDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        return sdf.format(date);
    }


    public boolean isVisible() {
        return visible;
    }

    public String getTitle() {
        return title;
    }

    public String getAttendant() {
        return attendant;
    }

    public String getComment() {
        return comment;
    }

    public String getDescription() {
        return description;
    }

    public int getPriority() {
        return priority;
    }

    public String getCreationDate() {
        return creationDate;
    }

    public boolean isState() {
        return state;
    }



    @Override
    public String toString() {
        return "Task{" +
                "title='" + title + '\'' +
                ", attendant='" + attendant + '\'' +
                ", comment='" + comment + '\'' +
                ", description='" + description + '\'' +
                ", priority=" + priority +
                ", creationDate='" + creationDate + '\'' +
                ", state=" + state +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Task task = (Task) o;

        if (priority != task.priority) return false;
        if (state != task.state) return false;
        if (title != null ? !title.equals(task.title) : task.title != null) return false;
        if (attendant != null ? !attendant.equals(task.attendant) : task.attendant != null)
            return false;
        if (comment != null ? !comment.equals(task.comment) : task.comment != null) return false;
        if (description != null ? !description.equals(task.description) : task.description != null)
            return false;
        return creationDate != null ? creationDate.equals(task.creationDate) : task.creationDate == null;
    }

    @Override
    public int hashCode() {
        int result = title != null ? title.hashCode() : 0;
        result = 31 * result + (attendant != null ? attendant.hashCode() : 0);
        result = 31 * result + (comment != null ? comment.hashCode() : 0);
        result = 31 * result + (description != null ? description.hashCode() : 0);
        result = 31 * result + priority;
        result = 31 * result + (creationDate != null ? creationDate.hashCode() : 0);
        result = 31 * result + (state ? 1 : 0);
        return result;
    }


    @Override
    public int compareTo( Task task) {
        int comparePrior = this.getPriority() - (task.getPriority());
        return comparePrior == 0 ? this.getTitle().compareTo(task.getTitle()) : comparePrior;
    }

}

Ich soll die Gegenstände zu schauen, wie die einzelnen Container, aber ich fand keine Möglichkeit, es zu tun. Irgendwelche Empfehlungen, was zu verwenden? Und was ist der beste Weg, es zu tun?

  • Haben Sie nicht Ihre eigene Frage beantwortet hier? Sie benötigen eine Zelle, die Fabrik für dieses.
  • Das ist richtig mit einer benutzerdefinierten Zelle Fabrik. Nichts hält Sie von der Definition der Inhalte in FXML.
InformationsquelleAutor | 2017-11-27



One Reply
  1. 2

    Dies ist ein Beispiel für die Verwendung FXML zum erstellen von benutzerdefinierten ListCell

    Ersten, die einen controller angelegt ist, zu Erben ListCell. Im Konstruktor dieser controller laden wir die FXML statement auf seiner Ansicht.

    public class TaskCell extends ListCell<Task> {
    
        @FXML
        private Label titleLabel;
    
        @FXML
        private Label commentLabel;
    
        @FXML
        private Label descriptionLabel;
    
        public TaskCell() {
            loadFXML();
        }
    
        private void loadFXML() {
            try {
                FXMLLoader loader = new FXMLLoader(getClass().getResource("task_cell.fxml"));
                loader.setController(this);
                loader.setRoot(this);
                loader.load();
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override
        protected void updateItem(Task item, boolean empty) {
            super.updateItem(item, empty);
    
            if(empty) {
                setText(null);
                setContentDisplay(ContentDisplay.TEXT_ONLY);
            }
            else {
                titleLabel.setText(item.getTitle());
                commentLabel.setText(item.getComment());
                descriptionLabel.setText(item.getDescription());
    
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            }
        }
    }

    Dies ist die Ansicht – task_cell.fxml

    <fx:root type="javafx.scene.control.ListCell" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml">
        <graphic>
            <VBox>
                <children>
                    <Label fx:id="titleLabel" />
                    <VBox>
                        <children>
                            <Label fx:id="commentLabel" />
                            <Label fx:id="descriptionLabel"/>
                        </children>
                    </VBox>
                </children>
            </VBox>
        </graphic>
    </fx:root>

    Dann müssen Sie erstellen Sie eine Zelle, die Fabrik, die verwendet werden können zum erstellen von Zellen.

    public class TaskCellFactory implements Callback<ListView<Task>, ListCell<Task>> {
    
        @Override
        public ListCell<Task> call(ListView<Task> param) {
            return new TaskCell();
        }
    }

    Haben wir erst einmal die Fabrik, können wir es manuell Einreichen, um ListView mit der ListView#setCellFactory()

    public class Controller {
    
        @FXML
        private ListView<Task> listView;
    
        @FXML
        private void initialize() {
            listView.setCellFactory(new TaskCellFactory());
        }
    }

    oder wir beschreiben es in der FXML – Anweisung der Ansicht, dass enthält die ListView Kontrolle

    <GridPane fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
        <ListView fx:id="listView" GridPane.columnIndex="0" GridPane.rowIndex="0">
            <cellFactory>
                <TaskCellFactory />
            </cellFactory>
        </ListView>
    </GridPane>

    In der zweiten version, die intellij idea markiert die falsche Linie mit <TaskCellFactory /> aber dies ist eindeutig ein Fehler im xml-parser.

    • Es funktioniert! Das problem, das ich habe, ist, dass die Elemente der Liste können nicht gewählt werden. Irgendeine Idee warum?
    • Die Auswahl erfolgt in der updateItem() Funktion (speziell in super.updateItem(item, empty);). Wenn es nicht richtig funktioniert, können Sie es selbst tun mit isSelected() und ändern Sie den hintergrund der Zelle, ob es aktiviert ist oder nicht.
    • Nochmals vielen Dank! Eine Letzte Frage, ich will event-handler, wenn ein Element der listview angeklickt wird (und ich möchte die Informationen des Artikels werden barrierearm), wo sollte ich die Ereignisse?
    • Wenn Sie nicht interessiert sind, in ein Ereignis von einem bestimmten element in der Zelle, verwenden listView.getSelectionModel().selectedItemProperty().addListener(...) nach was Sie brauchen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.