【问题标题】:Having two button in a list view in javaFX with XML file在带有 XML 文件的 javaFX 的列表视图中有两个按钮
【发布时间】:2018-12-03 21:22:03
【问题描述】:

我正在尝试使用 javaFX 制作像 Facebook 这样的应用程序,并且我希望有一个页面在列表视图中显示朋友,并选择确认和删除朋友请求。我正在考虑使用列表视图,但我不知道如何在每个单元格上添加按钮。 那么,是否可以在 JavaFX 的列表视图中添加两个好友请求按钮或删除按钮
喜欢 facebook 好友列表 enter image description here

如果有其他控制视图做同样的事情,请告诉我。

【问题讨论】:

  • 是的,有可能。

标签: java xml listview button javafx


【解决方案1】:

我认为很简单的一种可能方法是为ListView 提供您自己的CellFactory。这允许您为每个单元格构建一个完整的布局。

以下示例应用程序将演示该过程:

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class ListViewButtonsSample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Create some sample Users
        ObservableList<User> usersList = FXCollections.observableArrayList();
        usersList.addAll(
                new User("Amir"),
                new User("Jasmine"),
                new User("Leonardo")
        );

        // Create the ListView
        ListView<User> listView = new ListView<>();

        // We need to create a new CellFactory so we can display our layout for each individual user
        listView.setCellFactory((Callback<ListView<User>, ListCell<User>>) param -> {
            return new ListCell<User>() {
                @Override
                protected void updateItem(User user, boolean empty) {
                    super.updateItem(user, empty);

                    if (user == null || empty) {
                        setText(null);
                    } else {
                        // Here we can build the layout we want for each ListCell. Let's use a HBox as our root.
                        HBox root = new HBox(10);
                        root.setAlignment(Pos.CENTER_LEFT);
                        root.setPadding(new Insets(5, 10, 5, 10));

                        // Within the root, we'll show the username on the left and our two buttons to the right
                        root.getChildren().add(new Label(user.getUsername()));

                        // I'll add another Region here to expand, pushing the buttons to the right
                        Region region = new Region();
                        HBox.setHgrow(region, Priority.ALWAYS);
                        root.getChildren().add(region);

                        // Now for our buttons
                        Button btnAddFriend = new Button("Add Friend");
                        btnAddFriend.setOnAction(event -> {
                            // Code to add friend
                            System.out.println("Added " + user.getUsername() + " as a friend!");
                        });
                        Button btnRemove = new Button("Remove");
                        btnRemove.setOnAction(event -> {
                            // Code to remove friend
                            System.out.println("Broke up with " + user.getUsername() + "!");
                        });
                        root.getChildren().addAll(btnAddFriend, btnRemove);

                        // Finally, set our cell to display the root HBox
                        setText(null);
                        setGraphic(root);
                    }

                }
            };

        });

        // Set our users to display in the ListView
        listView.setItems(usersList);

        root.getChildren().add(listView);

        // Show the Stage
        primaryStage.setWidth(500);
        primaryStage.setHeight(300);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

class User {

    private final StringProperty username = new SimpleStringProperty();

    public User(String username) {
        this.username.set(username);
    }

    public String getUsername() {
        return username.get();
    }

    public StringProperty usernameProperty() {
        return username;
    }

    public void setUsername(String username) {
        this.username.set(username);
    }
}

结果:

注意:结果与 Sedrick 的解决方案类似,但不使用 FXML。如果您打算在应用程序的其他地方使用此 ListCell 实现,您可能需要为这个特定的 ListCell 创建一个单独的类,以便可以重用它。

【讨论】:

    【解决方案2】:

    这是一个使用FXML 的(粗略)演示应用程序。关键是创建一个自定义节点作为ListViewCell 的视图。

    ListViewCell 的自定义节点。

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.geometry.Insets?>
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.AnchorPane?>
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.layout.VBox?>
    
    
    <fx:root fx:id="hboxRoot" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="100.0" type="HBox" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
       <children>
          <AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS">
             <children>
                <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                   <children>
                      <Label fx:id="lblName" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="Label" VBox.vgrow="ALWAYS" />
                      <Label fx:id="lblAge" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="Label" VBox.vgrow="ALWAYS" />
                      <Label fx:id="lblSex" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="Label" VBox.vgrow="ALWAYS" />
                   </children>
                   <padding>
                      <Insets left="20.0" />
                   </padding>
                </VBox>
             </children>
          </AnchorPane>
          <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="10.0">
             <children>
                <Button fx:id="btnAdd" mnemonicParsing="false" text="Button" />
                <Button fx:id="btnRemove" mnemonicParsing="false" text="Button" />
             </children>
          </HBox>
       </children>
    </fx:root>
    

    自定义节点Controller在处理自定义节点时,我不确定这是否称为Controller。它的工作原理类似于`Controller。

    import java.io.IOException;
    import javafx.event.EventHandler;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.layout.HBox;
    
    /**
     * FXML Controller class
     *
     * @author blj0011
     */
    public class CustomCellView extends HBox
    {
        @FXML
        HBox hboxRoot;
        @FXML
        Label lblName, lblAge, lblSex;
        @FXML
        Button btnAdd, btnRemove;
    
        public CustomCellView()
        {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("CellView.fxml"));
            fxmlLoader.setRoot(this);
            fxmlLoader.setController(this);
            try {
                fxmlLoader.load();
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        HBox getHBoxRoot()
        {
            return hboxRoot;
        }
    
        void setlblNameText(String text)
        {
            lblName.setText(text);
        }
    
        void setlblAgeText(String text)
        {
            lblAge.setText(text);
        }
    
        void setlblSexText(String text)
        {
            lblSex.setText(text);
        }
    
        void setBtnAddAction(EventHandler actionEvent)
        {
            btnAdd.setOnAction(actionEvent);
        }
    
        void setBtnRemoveAction(EventHandler actionEvent)
        {
            btnRemove.setOnAction(actionEvent);
        }
    }
    

    ListViewCell

    import javafx.event.Event;
    import javafx.event.EventHandler;
    import javafx.scene.control.ListCell;
    
    public class ListViewCell extends ListCell<Person>
    {
        @Override
        public void updateItem(Person person, boolean empty)
        {
            super.updateItem(person, empty);
            if (person != null) {
                CustomCellView customCellView = new CustomCellView();
                customCellView.setlblNameText(person.getName());
                customCellView.setlblAgeText(person.getAge());
                customCellView.setlblSexText(person.getSex());
    
                EventHandler addHandler = (EventHandler) (Event event) -> {
                    System.out.println("Add " + person.getName());
                };
                customCellView.setBtnAddAction(addHandler);
    
                EventHandler removeHandler = (EventHandler) (Event event) -> {
                    System.out.println("Remove " + person.getName());
                };
                customCellView.setBtnRemoveAction(removeHandler);
    
                setGraphic(customCellView.getHBoxRoot());
            }
        }
    }
    

    主要

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    /**
     *
     * @author blj0011
     */
    public class JavaFXApplication311 extends Application
    {
    
        @Override
        public void start(Stage stage) throws Exception
        {
            Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
    
            Scene scene = new Scene(root);
    
            stage.setScene(scene);
            stage.show();
        }
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args)
        {
            launch(args);
        }
    
    }
    

    主要 FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.ListView?>
    <?import javafx.scene.layout.AnchorPane?>
    
    <AnchorPane id="AnchorPane" prefHeight="573.0" prefWidth="726.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.141" fx:controller="javafxapplication311.FXMLDocumentController">
       <children>
          <ListView fx:id="lvMain" layoutX="102.0" layoutY="14.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
       </children>
    </AnchorPane>
    

    主 FXMLController

    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.ListCell;
    import javafx.scene.control.ListView;
    import javafx.util.Callback;
    
    /**
     *
     * @author blj0011
     */
    public class FXMLDocumentController implements Initializable
    {
    
        @FXML
        private ListView lvMain;
    
        @Override
        public void initialize(URL url, ResourceBundle rb)
        {
            lvMain.getItems().add(new Person("John Doe", "22", "Male"));
            lvMain.getItems().add(new Person("Jane Doe", "21", "Female"));
    
            lvMain.setCellFactory(new Callback<ListView<String>, ListCell<String>>()
            {
                @Override
                public ListCell call(ListView param)
                {
                    return new ListViewCell();
                }
    
            });
        }
    
    }
    

    /**
     *
     * @author blj0011
     */
    public class Person
    {
        private String name;
        private String age;
        private String sex;
    
        public Person(String name, String age, String sex)
        {
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
        public String getSex()
        {
            return sex;
        }
    
        public void setSex(String sex)
        {
            this.sex = sex;
        }
    
        public String getName()
        {
            return name;
        }
    
        public void setName(String name)
        {
            this.name = name;
        }
    
        public String getAge()
        {
            return age;
        }
    
        public void setAge(String age)
        {
            this.age = age;
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 2012-07-08
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 2011-08-01
      相关资源
      最近更新 更多