java - 通过 for 循环将按钮添加到 FlowPane (JavaFX)

标签 java for-loop javafx fxml

我曾多次尝试通过 for 循环向 FlowPane 添加按钮。但是,当循环在我的 start 方法中运行时,按钮无法呈现。我已经为 Controller 类和我使用的 fxml 布局文件提供了代码。

这是我的 Controller 代码:

package dimension.audio.player;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.ResourceBundle;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.media.Media;
import javafx.stage.Stage;

public class MediaViewer extends Application{
    ArrayList<String> list;

    File directory;

    Button lab;

    ArrayList<String> tagged = new ArrayList<String>();

    @FXML
    BorderPane layout = new BorderPane();

    @FXML
    FlowPane butLayout = new FlowPane(Orientation.HORIZONTAL);

    @FXML
    GridPane searchLayout;

    @SuppressWarnings("rawtypes")
    ObservableMap map;

    static Stage stage;
    static Scene scene;

    public void start(final Stage stage) throws Exception {
    MediaViewer.stage = stage;
    Parent root = FXMLLoader.load(new URL(this.getClass().getResource("library.fxml").toExternalForm()));

    if (MainController.getMedia() != null) {
        list = organizeDirectory(new File(MainController.getMedia().getSource()).getParentFile(), "mp3");
    } else {
        list = organizeDirectory(new File(System.getProperty("user.home") + "/Music/"), "mp3");
    }
    stage.setTitle("Library - " + directory.getAbsolutePath());
    stage.setResizable(false);
    scene = new Scene(root);
    addListItems(butLayout, stage, scene);
    }

    public ArrayList<String> organizeDirectory(File file, final String extension) {
    directory = file;
    if (!file.getName().contains("http")) {
        final ArrayList<String> filtered = new ArrayList<String>();
        File[] fileList = file.listFiles();
        if (fileList != null) {
        Path path = Paths.get(file.getAbsolutePath());
        try {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                return FileVisitResult.CONTINUE;
            }

            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                if (file.getFileName().toString().endsWith(extension)) {
                filtered.add(file.toString());
                }
                return FileVisitResult.CONTINUE;
            }

            public FileVisitResult visitFileFailed(Path file, IOException e) {
                return FileVisitResult.CONTINUE;
            }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return filtered;
        } else {
        return null;
        }
    } else {
        return null;
    }

    }

    public void addListItems(final Pane layout, final Stage stage, final Scene scene) {
    ArrayList<Node> but = new ArrayList<Node>();
    if (list != null) {
        for (final String s : list) {
        final String[] sList = s.split("\\\\");
        System.out.println(sList[sList.length - 1]);
        lab = new Button(sList[sList.length - 1]);
        lab.getStyleClass().add("lab");
        lab.setPrefHeight(10);
        lab.setPrefWidth(scene.getWidth());
        lab.setAlignment(Pos.CENTER_LEFT);
        lab.setStyle("-fx-border-color: black");
        lab.setStyle("-fx-backgound-color: lightgray");
        lab.setTooltip(new Tooltip(lab.getText()));
        lab.setOnMouseClicked(new EventHandler<MouseEvent>() {
            public void handle(MouseEvent arg0) {
            System.out.println("visible");
            }
        });

        scene.widthProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
            lab.setPrefWidth(scene.getWidth());
            }
        });
        but.add(lab);
        }
        layout.getChildren().setAll(but);
        stage.setScene(scene);
        stage.show();
    }
    }
}

这是 fxml:

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

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane id="layout" prefHeight="600.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="dimension.audio.player.MediaViewer">
  <!-- TODO Add Nodes -->
  <center>
    <ScrollPane hbarPolicy="NEVER" prefHeight="200.0" prefWidth="200.0">
      <content>
        <FlowPane id="butLayout" mouseTransparent="false" orientation="VERTICAL" pickOnBounds="false" prefHeight="549.0" prefWidth="599.0" style="" />
      </content>
    </ScrollPane>
  </center>
  <top>
    <GridPane id="searchLayout" alignment="CENTER_RIGHT" prefWidth="579.0" style="-fx-padding: 10">
      <children>
        <Label text="Search:" textAlignment="JUSTIFY" GridPane.columnIndex="0" GridPane.rowIndex="0" />
        <TextField prefWidth="525.0" GridPane.columnIndex="1" GridPane.rowIndex="0" />
      </children>
      <columnConstraints>
        <ColumnConstraints hgrow="SOMETIMES" maxWidth="320.0" minWidth="10.0" prefWidth="61.0" />
        <ColumnConstraints hgrow="SOMETIMES" maxWidth="609.0" minWidth="10.0" prefWidth="539.0" />
      </columnConstraints>
      <rowConstraints>
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      </rowConstraints>
    </GridPane>
  </top>
</BorderPane>

最佳答案

  1. 不要在 Controller 中实例化 @FXML 注入(inject)的字段。这个想法是,这些实例由 FXMLLoader 实例化,这些实例是为您注入(inject)的。
  2. 要将 FXML 文件中的字段注入(inject) Controller ,您需要属性 fx:id="fieldName",例如<FlowPane fx:id="butLayout" ...>

使用您拥有的代码,字段不会被注入(inject),并且您不会在场景图中的节点上进行操作(即,您将按钮添加到您在 Controller 中创建的 FlowPane,而不是您在FMXL 文件)。

关于java - 通过 for 循环将按钮添加到 FlowPane (JavaFX),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22927055/

相关文章:

java - 卡夫卡 : Failed to update metadata after 60000 ms

Java run 方法中的简短 if 语句

java - 为什么我的 Scanner 变量没有使用 : System. out.println(input.nextDouble()); 转换为 double 值?

javascript - Angular 不返回内部嵌套的 for 循环

java - 如何更改CSS上的字体?

java - 如何从数组列表填充 JavaFX 中的 TableView

JavaFX 访问 Controller 给出空指针异常

java - 如何解决给出 NullPointerException 的@Inject?

Python:For 循环遍历列表理解

python - 如何从字典创建数据框