我的问题是,我将创建一个使用closeFile()方法关闭currentFile的按钮。所以我写了currentFile.set(null);
我在fxml文件中获得(X)按钮的按钮,关闭该文件,但是如果我加载另一个文件,则分页不起作用,请附上源代码和视频。
Controller.java
package pdfviewer;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.StringWriter;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFPage;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.IntegerBinding;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Pagination;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TitledPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
import javafx.util.Callback;
public class Controller {
@FXML private Pagination pagination ;
@FXML private Label currentZoomLabel ;
private FileChooser fileChooser ;
private ObjectProperty<PDFFile> currentFile ;
private ObjectProperty<ImageView> currentImage ;
@FXML private ScrollPane scroller ;
private DoubleProperty zoom ;
private PageDimensions currentPageDimensions ;
private ExecutorService imageLoadService ;
private static final double ZOOM_DELTA = 1.05 ;
@FXML private Button previousButton,nextButton;
// ************ Initialization *************
public void initialize() {
createAndConfigureImageLoadService();
createAndConfigureFileChooser();
currentFile = new SimpleObjectProperty<>();
updateWindowTitleWhenFileChanges();
currentImage = new SimpleObjectProperty<>();
scroller.contentProperty().bind(currentImage);
zoom = new SimpleDoubleProperty(1);
// To implement zooming, we just get a new image from the PDFFile each time.
// This seems to perform well in some basic tests but may need to be improved
// E.g. load a larger image and scale in the ImageView, loading a new image only
// when required.
zoom.addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
updateImage(pagination.getCurrentPageIndex());
}
});
currentZoomLabel.textProperty().bind(Bindings.format("%.0f %%", zoom.multiply(100)));
bindPaginationToCurrentFile();
createPaginationPageFactory();
}
private void createAndConfigureImageLoadService() {
imageLoadService = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
});
}
private void createAndConfigureFileChooser() {
fileChooser = new FileChooser();
fileChooser.setInitialDirectory(Paths.get(System.getProperty("user.home")).toFile());
fileChooser.getExtensionFilters().add(new ExtensionFilter("PDF Files", "*.pdf", "*.PDF"));
}
private void updateWindowTitleWhenFileChanges() {
currentFile.addListener(new ChangeListener<PDFFile>() {
@Override
public void changed(ObservableValue<? extends PDFFile> observable, PDFFile oldFile, PDFFile newFile) {
try {
String title = newFile == null ? "PDF Viewer" : newFile.getStringMetadata("Title") ;
Window window = pagination.getScene().getWindow();
if (window instanceof Stage) {
((Stage)window).setTitle(title);
}
} catch (IOException e) {
showErrorMessage("Could not read title from pdf file", e);
}
}
});
}
private void bindPaginationToCurrentFile() {
currentFile.addListener(new ChangeListener<PDFFile>() {
@Override
public void changed(ObservableValue<? extends PDFFile> observable, PDFFile oldFile, PDFFile newFile) {
if (newFile != null) {
pagination.setCurrentPageIndex(0);
}
}
});
pagination.pageCountProperty().bind(new IntegerBinding() {
{
super.bind(currentFile);
}
@Override
protected int computeValue() {
return currentFile.get()==null ? 0 : currentFile.get().getNumPages() ;
}
});
pagination.disableProperty().bind(Bindings.isNull(currentFile));
}
private void createPaginationPageFactory() {
pagination.setPageFactory(new Callback<Integer, Node>() {
@Override
public Node call(Integer pageNumber) {
if (currentFile.get() == null) {
return null ;
} else {
if (pageNumber >= currentFile.get().getNumPages() || pageNumber < 0) {
return null ;
} else {
if(pageNumber==0) {previousButton.setDisable(true);}
else {previousButton.setDisable(false);}
if(pageNumber==currentFile.get().getNumPages()-1) {nextButton.setDisable(true);}
else {nextButton.setDisable(false);}
updateImage(pageNumber);
return scroller ;
}
}
}
});
}
// ************** Event Handlers ****************
@FXML private void loadFile() {
final File file = fileChooser.showOpenDialog(pagination.getScene().getWindow());
if (file != null) {
final Task<PDFFile> loadFileTask = new Task<PDFFile>() {
@Override
protected PDFFile call() throws Exception {
try (
RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel()
) {
ByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
return new PDFFile(buffer);
}
}
};
loadFileTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
pagination.getScene().getRoot().setDisable(false);
final PDFFile pdfFile = loadFileTask.getValue();
currentFile.set(pdfFile);
}
});
loadFileTask.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
pagination.getScene().getRoot().setDisable(false);
showErrorMessage("Could not load file "+file.getName(), loadFileTask.getException());
}
});
pagination.getScene().getRoot().setDisable(true);
imageLoadService.submit(loadFileTask);
}
}
@FXML private void openPdfOne() {
//final File file = new File ("C:\\Users\\piratack007\\Desktop\\interaction-fer-et-microbiote.pdf");
pagination.setCurrentPageIndex(4);
}
@FXML private void closeFile() {
currentFile.set(null);
}
@FXML private void nextPage() {
int pageActuelle=pagination.getCurrentPageIndex();
pagination.setCurrentPageIndex(pageActuelle+1);
}
@FXML private void previousPage() {
int pageActuelle=pagination.getCurrentPageIndex();
pagination.setCurrentPageIndex(pageActuelle-1);
}
@FXML private void zoomIn() {
zoom.set(zoom.get()*ZOOM_DELTA);
}
@FXML private void zoomOut() {
zoom.set(zoom.get()/ZOOM_DELTA);
}
@FXML private void zoomFit() {
// TODO: the -20 is a kludge to account for the width of the scrollbars, if showing.
double horizZoom = (scroller.getWidth()-20) / currentPageDimensions.width ;
double verticalZoom = (scroller.getHeight()-20) / currentPageDimensions.height ;
zoom.set(Math.min(horizZoom, verticalZoom));
}
@FXML private void zoomWidth() {
zoom.set((scroller.getWidth()-20) / currentPageDimensions.width) ;
}
// *************** Background image loading ****************
private void updateImage(final int pageNumber) {
final Task<ImageView> updateImageTask = new Task<ImageView>() {
@Override
protected ImageView call() throws Exception {
PDFPage page = currentFile.get().getPage(pageNumber+1);
Rectangle2D bbox = page.getBBox();
final double actualPageWidth = bbox.getWidth();
final double actualPageHeight = bbox.getHeight();
// record page dimensions for zoomToFit and zoomToWidth:
currentPageDimensions = new PageDimensions(actualPageWidth, actualPageHeight);
// width and height of image:
final int width = (int) (actualPageWidth * zoom.get());
final int height = (int) (actualPageHeight * zoom.get());
// retrieve image for page:
// width, height, clip, imageObserver, paintBackground, waitUntilLoaded:
java.awt.Image awtImage = page.getImage(width, height, bbox, null, true, true);
// draw image to buffered image:
BufferedImage buffImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
buffImage.createGraphics().drawImage(awtImage, 0, 0, null);
// convert to JavaFX image:
Image image = SwingFXUtils.toFXImage(buffImage, null);
// wrap in image view and return:
ImageView imageView = new ImageView(image);
imageView.setPreserveRatio(true);
return imageView ;
}
};
updateImageTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
pagination.getScene().getRoot().setDisable(false);
currentImage.set(updateImageTask.getValue());
}
});
updateImageTask.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
pagination.getScene().getRoot().setDisable(false);
updateImageTask.getException().printStackTrace();
}
});
pagination.getScene().getRoot().setDisable(true);
imageLoadService.submit(updateImageTask);
}
private void showErrorMessage(String message, Throwable exception) {
// TODO: move to fxml (or better, use ControlsFX)
final Stage dialog = new Stage();
dialog.initOwner(pagination.getScene().getWindow());
dialog.initStyle(StageStyle.UNDECORATED);
final VBox root = new VBox(10);
root.setPadding(new Insets(10));
StringWriter errorMessage = new StringWriter();
exception.printStackTrace(new PrintWriter(errorMessage));
final Label detailsLabel = new Label(errorMessage.toString());
TitledPane details = new TitledPane();
details.setText("Details:");
Label briefMessageLabel = new Label(message);
final HBox detailsLabelHolder =new HBox();
Button closeButton = new Button("OK");
closeButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
dialog.hide();
}
});
HBox closeButtonHolder = new HBox();
closeButtonHolder.getChildren().add(closeButton);
closeButtonHolder.setAlignment(Pos.CENTER);
closeButtonHolder.setPadding(new Insets(5));
root.getChildren().addAll(briefMessageLabel, details, detailsLabelHolder, closeButtonHolder);
details.setExpanded(false);
details.setAnimated(false);
details.expandedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable,
Boolean oldValue, Boolean newValue) {
if (newValue) {
detailsLabelHolder.getChildren().add(detailsLabel);
} else {
detailsLabelHolder.getChildren().remove(detailsLabel);
}
dialog.sizeToScene();
}
});
final Scene scene = new Scene(root);
dialog.setScene(scene);
dialog.show();
}
/*
* Struct-like class intended to represent the physical dimensions of a page in pixels
* (as opposed to the dimensions of the (possibly zoomed) view.
* Used to compute zoom factors for zoomToFit and zoomToWidth.
*
*/
private class PageDimensions {
private double width ;
private double height ;
PageDimensions(double width, double height) {
this.width = width ;
this.height = height ;
}
@Override
public String toString() {
return String.format("[%.1f, %.1f]", width, height);
}
}
}
Pdfviewer.java
package pdfviewer;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class PdfViewer extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
final Parent parent = FXMLLoader.load(getClass().getResource("PdfViewerTwo.fxml"));
primaryStage.setScene(new Scene(parent,600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
PdfViewerTwo.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Pagination?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.control.ScrollPane?>
<AnchorPane prefHeight="600.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pdfviewer.Controller">
<children>
<BorderPane prefHeight="600.0" prefWidth="600.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0">
<top>
<AnchorPane prefHeight="40.0" BorderPane.alignment="CENTER">
<children>
<Button mnemonicParsing="false" onAction="#loadFile" text="Ouvrir" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="10.0" />
<Button layoutX="129.0" layoutY="10.0" mnemonicParsing="false" onAction="#zoomFit" text="Minimiser" AnchorPane.leftAnchor="129.0" AnchorPane.topAnchor="10.0" />
<Button layoutX="204.0" layoutY="10.0" mnemonicParsing="false" onAction="#zoomWidth" text="agrandir" />
<Button layoutX="328.0" layoutY="10.0" mnemonicParsing="false" onAction="#closeFile" text="X" />
<Button layoutX="298.0" layoutY="10.0" mnemonicParsing="false" onAction="#zoomOut" text="-" />
<Button layoutX="273.0" layoutY="10.0" mnemonicParsing="false" onAction="#zoomIn" text="+" />
<Label fx:id="currentZoomLabel" layoutX="442.0" layoutY="13.0" prefHeight="18.0" prefWidth="51.0" />
<Label layoutX="85.0" layoutY="12.0" text="Zoom:">
<font>
<Font size="14.0" />
</font>
</Label>
<Button fx:id="nextButton" layoutX="402.0" layoutY="10.0" mnemonicParsing="false" onAction="#nextPage" text="=>" />
<Button fx:id="previousButton" layoutX="360.0" layoutY="10.0" mnemonicParsing="false" onAction="#previousPage" text="<=" />
</children>
</AnchorPane>
</top>
<fx:define>
<ScrollPane fx:id="scroller" pannable="true" />
</fx:define>
<center>
<Pagination fx:id="pagination" BorderPane.alignment="CENTER" />
</center>
<left>
<AnchorPane prefHeight="556.0" prefWidth="28.0" BorderPane.alignment="CENTER">
<children>
<Button layoutY="76.0" mnemonicParsing="false" onAction="#openPdfOne" text="Pdf1" />
</children>
</AnchorPane>
</left>
</BorderPane>
</children>
</AnchorPane>
我如何干净地关闭文件?
我会非常感激
附加了屏幕截图和代码*
https://www.youtube.com/watch?v=9RhSmKbEUKg
最诚挚的问候
我真的很困惑,我在javaFx中有一个pdf查看器应用程序,我的问题是我想创建一个按钮,用closeFile()方法关闭currentFile。所以我写了currentFile.set(null)...