Javafx 使用按钮在另一个窗口中打开另一个 fxml?

问题描述 投票:0回答:1

在javafx中是否可以使用按钮从另一个fxml打开新阶段(窗口)?感谢您的回答。

因为我遇到了这个错误:

javafx.fxml.LoadException: 
/C:/Users/Me/Desktop/jj/target/classes/com/example/jj/path-window.fxml

这是我的代码:

package com.example.jj;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 520, 440);
        stage.setTitle("Download Files");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(new String[0]);
    }
}
package com.example.jj;

import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class HelloController {
    @FXML
    public TextField downloadUrl;
    @FXML
    public TextField pathUrl;
    @FXML
    public Button downloadButton;
    @FXML
    public Button DownloadAll;
    @FXML
    public Button btnInsert;
    @FXML
    public Button btnn1;
    @FXML
    public ProgressBar progressBar;
    @FXML
    public Label progressLabel;
    @FXML
    public TableView<Url> table;
    @FXML
    public TableColumn<Url,String> FileName;
    @FXML
    public TableColumn<Url,String> Size;
    @FXML
    public TableColumn<Url,String> Status;
    @FXML
    public TableColumn<Url,String> Progress;
    @FXML
    public TableColumn<Url,String> Urltext;
    ExecutorService executor = Executors.newFixedThreadPool(4); // Limit to 4 threads

    public void initialize() throws MalformedURLException {
        downloadButton.setOnAction(e -> downloadFile());

        FileName.setCellValueFactory(new PropertyValueFactory<>("FileName"));
        Size.setCellValueFactory(new PropertyValueFactory<>("Size"));
        Status.setCellValueFactory(new PropertyValueFactory<>("Status"));
        Progress.setCellValueFactory(new PropertyValueFactory<>("Progress"));


//        String urlText = this.downloadUrl.getText().trim(); // Trim to remove leading/trailing spaces
//
//        // Check if the provided text is a valid URL
//        URL url = new URL(urlText);
//
//        // Get the file name from the URL
//        String fileName = Paths.get(url.getFile()).getFileName().toString();
//        String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
//        System.out.println("File extension: " + extension);
//
//        FileChooser fileChooser = new FileChooser();
//        fileChooser.setTitle("Save As");
//        fileChooser.setInitialFileName(fileName + "." + extension); // Set the initial file name
//        this.pathUrl.setText("C:\\Users\\Me\\Desktop\\Down test");

    }

    @FXML
    public void btnPath (ActionEvent event){



        String pathText = this.pathUrl.getText().trim();


    }

    @FXML
    public void btnDownloadAll (ActionEvent event){
        // Assuming your TableView contains a list of strings (file URLs)
//        ObservableList<Url> urlList = table.getItems();
        ObservableList<Url> urlList = table.getItems()
                .filtered(url -> "waiting".equals(url.getStatus()));

        for (Url url : urlList) {

            String urlText = url.getUrltext();
            String status = url.getStatus();
            if (status.equals("waiting")) {
                System.out.println("Downloading: " + urlText);
                executor.submit(() -> {
                    DownloadAll.setOnAction(e -> downloadFile());
                });
            }
        }


    }
    @FXML
    public void updateStatus(int rowIndex, String newStatus) {
        if (rowIndex >= 0 && rowIndex < table.getItems().size()) {
            Url url = table.getItems().get(rowIndex);
            url.setStatus(newStatus); // Update the status
            table.refresh(); // Refresh the table to reflect changes
        }
    }
    @FXML
    public void btnn1(ActionEvent event) throws IOException {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("path-window.fxml"));
            Parent root = loader.load();

            Stage secondaryStage = new Stage();
            secondaryStage.setScene(new Scene(root));
            secondaryStage.setTitle("Secondary Window");
            secondaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

        @FXML
    public void btnInsert (ActionEvent event) throws IOException {

//        try {
//            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("path-window.fxml"));
//            Parent root1 = (Parent) fxmlLoader.load();
//            Stage stage = new Stage();
//            stage.initModality(Modality.APPLICATION_MODAL);
//            stage.initStyle(StageStyle.UNDECORATED);
//            stage.setTitle("ABC");
//            stage.setScene(new Scene(root1));
//            stage.show();
//        } catch(Exception e) {
//            e.printStackTrace();
//        }


        String urlText = this.downloadUrl.getText().trim(); // Trim to remove leading/trailing spaces
        URL url = null;
        try {
            url = new URL(urlText);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
        String fileName = Paths.get(url.getFile()).getFileName().toString();
        long fileSize = 0;
        try {
            fileSize = url.openConnection().getContentLengthLong();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        String path = null;
        Url obj = new Url(fileName,fileSize,"waiting","0.0",urlText, path);
        table.getItems().add(obj);


    }

    private void downloadFile() {
        this.progressBar.setVisible(true);
        this.progressLabel.setVisible(true);
        String urlText = this.downloadUrl.getText().trim(); // Trim to remove leading/trailing spaces


        if (urlText.isEmpty()) {
            // Alert user if URL is empty
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("URL not found!");
            alert.setHeaderText("Please provide the URL!");
            alert.show();
        } else {
            try {
                // Check if the provided text is a valid URL
                URL url = new URL(urlText);

                // Get the file name from the URL
                String fileName = Paths.get(url.getFile()).getFileName().toString();
                String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
                System.out.println("File extension: " + extension);

                FileChooser fileChooser = new FileChooser();
                fileChooser.setTitle("Save As");
                fileChooser.setInitialFileName(fileName + "." + extension); // Set the initial file name
                // Set the default directory
                File defaultDirectory = new File("C:\\Users\\Me\\Desktop\\Down test");
                fileChooser.setInitialDirectory(defaultDirectory);
                File selectedFile = fileChooser.showSaveDialog(this.downloadButton.getScene().getWindow());

                if (selectedFile == null) {
                    System.out.println("Selection canceled");
                } else {
                    String downloadPath = selectedFile.getAbsolutePath();
                    DownloadFile downloadFile = new DownloadFile(urlText, downloadPath, this.progressLabel);
                    Thread downloadThread = new Thread(downloadFile);
                    this.progressBar.progressProperty().unbind();
                    this.progressBar.progressProperty().bind(downloadFile.progressProperty());
                    downloadThread.start();

                    this.downloadUrl.clear();
                    downloadThread.join();
                    updateStatus(0,downloadFile.getStatus());
                }
            } catch (MalformedURLException e) {
                // Handle invalid URL format
                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.setTitle("Invalid URL!");
                alert.setHeaderText("Please provide a valid URL!");
                alert.show();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }


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

<?import java.lang.*?>
<?import javafx.collections.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<VBox alignment="CENTER" prefHeight="420.0" prefWidth="429.0" spacing="20.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.jj.HelloController">
  <padding>
    <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
  </padding>

  <Label text="Enter the URL">
      <font>
         <Font size="16.0" />
      </font></Label>
   <BorderPane prefHeight="65.0" prefWidth="389.0">
      <center>
         <TextField fx:id="downloadUrl" prefWidth="379.0" BorderPane.alignment="CENTER" />
      </center>
   </BorderPane>
  <Button fx:id="downloadButton" text="Download" />
   <StackPane prefHeight="57.0" prefWidth="389.0">
      <children>
         <ProgressBar fx:id="progressBar" prefWidth="200.0" progress="0.0" />
         <Label fx:id="progressLabel" text="0%" />
      </children>
   </StackPane>
   <Button mnemonicParsing="false" onAction="#btnn1" text="Button" />
   <Button mnemonicParsing="false" onAction="#btnInsert" text="Insert URL" />
   <HBox alignment="TOP_RIGHT" prefHeight="100.0" prefWidth="200.0">
      <children>
         <Button fx:id="DownloadAll" mnemonicParsing="false" onAction="#btnDownloadAll" text="Download All">
            <HBox.margin>
               <Insets right="110.0" />
            </HBox.margin></Button>
          <ChoiceBox value="1">
              <items>
                  <FXCollections fx:factory="observableArrayList">
                      <String fx:value="2" />
                      <String fx:value="3" />
                      <String fx:value="4" />
                  </FXCollections>
              </items>
          </ChoiceBox>
      </children></HBox>
   <TableView fx:id="table" prefHeight="200.0" prefWidth="200.0">
     <columns>
       <TableColumn fx:id="FileName" prefWidth="103.0" text="File Name" />
       <TableColumn fx:id="Size" text="Size" />
         <TableColumn fx:id="Status" prefWidth="76.0" text="Status" />
         <TableColumn fx:id="Progress" prefWidth="129.0" text="progress" />
         <TableColumn fx:id="Urltext" prefWidth="75.0" text="Column X" visible="false" />
     </columns>
   </TableView>
</VBox>

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

<?import java.lang.*?>
<?import javafx.collections.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<VBox fx:id="mainVBox" alignment="CENTER" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.jj.HelloController">
<!--    <Button fx:id="openButton" text="Open Secondary Window" onAction="#btnn"/>-->
</VBox>

还有更多不重要的课程。

那么为什么我会遇到这个问题呢? :

javafx.fxml.LoadException: 
/C:/Users/Me/Desktop/jj/target/classes/com/example/jj/path-window.fxml
java javafx fxml scenebuilder
1个回答
0
投票

是的,可以在其他阶段打开 FXML 文件。

辅助方法:

/**
 * Creates a fxml dialog.
 *
 * @param title                  The dialog title.
 * @param dialogIsModal          Dialog is modal or not.
 * @param dialogIsResizeable     Dialog is resizeable or not.
 * @param absoluteFxmlFileUrl    The absolut URL of the new fxml file.
 * @param sceneSize              The scene size.
 * @param initMethodOfController A method of the new controller which shall be executed if everything is ready.
 * @param callbackOnDialogClose  A callback which shall be executed when the dialog closes.
 * @return The stage of the created dialog.
 * @throws IOException On error.
 */
public static Stage createFxmlDialog(
        String title,
        boolean dialogIsModal,
        boolean dialogIsResizeable,
        URL absoluteFxmlFileUrl,
        Dimension2D sceneSize,
        @SuppressWarnings("rawtypes") Consumer initMethodOfController,
        Runnable callbackOnDialogClose)
        throws IOException {

    FXMLLoader loader = new FXMLLoader(absoluteFxmlFileUrl);
    Parent root = loader.load(); // this calls the constructor and after that initialize from jfx()
    Object viewController = loader.getController();
    Scene scene = sceneSize == null ? new Scene(root) : new Scene(root, sceneSize.getWidth(), sceneSize.getHeight());

    Stage stage = new Stage();
    stage.setTitle(title);
    stage.initModality(dialogIsModal ? Modality.APPLICATION_MODAL : Modality.NONE);
    stage.setResizable(dialogIsResizeable);
    stage.setScene(scene);
    stage.setOnHidden(event -> {
        event.consume();
        if (callbackOnDialogClose != null) {
            callbackOnDialogClose.run();
        }
        stage.close();
    });

    if (initMethodOfController != null) {
        //noinspection unchecked
        initMethodOfController.accept(viewController);
    }
    return stage;
}

如何使用简单模态:

        createFxmlDialog(
                "My Dialog",
                true,
                false,
                getClass().getResource("/absolute/path/to/scene1.fxml"),
                null,
                null,
                null).showAndWait();

附加信息:

有关更多信息,请查看相应的库:https://github.com/davidweber411/javafx-SimpleJavaFxApplicationBase

为此,您可以查看以下文档:https://wedasoft.com/projects/simple-java-fx-application-base/sjfxab-version-2-0-0/。您可以在“对话框 API > 单独的 FXML 对话框”下找到此功能。

© www.soinside.com 2019 - 2024. All rights reserved.