Zentriere ersten Zoom-Schritt mittels AnimationTimer-Single-Shot
ChangeListener auf hvalueProperty feuert nicht zuverlässig: wenn hvalue im Fit-Modus bereits 0.5 (oder identisch zum Reset-Wert) ist, gibt es keine Wertänderung beim setFitToWidth(false), und der Listener läuft nie an – der spätere JavaFX-eigene Reset auf 0.0 bleibt unkontrolliert. AnimationTimer.handle() läuft einmal pro JavaFX-Frame, nach allen Layout-, CSS- und Pulse-Passes des aktuellen Frames. Das ist der einzige in JavaFX zuverlässige Mechanismus, um nach allem zu feuern, was JavaFX in diesem Frame noch erledigt. stop() im ersten handle() macht den Timer zum Single-Shot. Folge-Zoom-Schritte (wasInFitMode == false) bleiben unverändert mit einfachem Platform.runLater. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+13
-17
@@ -17,8 +17,8 @@ import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
|
|||||||
import org.apache.pdfbox.rendering.ImageType;
|
import org.apache.pdfbox.rendering.ImageType;
|
||||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||||
|
|
||||||
|
import javafx.animation.AnimationTimer;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.value.ChangeListener;
|
|
||||||
import javafx.embed.swing.SwingFXUtils;
|
import javafx.embed.swing.SwingFXUtils;
|
||||||
import javafx.geometry.Bounds;
|
import javafx.geometry.Bounds;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
@@ -729,24 +729,20 @@ public final class PdfPreviewPane {
|
|||||||
|
|
||||||
if (wasInFitMode) {
|
if (wasInFitMode) {
|
||||||
// Erster Zoom-Schritt nach Verlassen des Fit-Modus: setFitToWidth(false)
|
// Erster Zoom-Schritt nach Verlassen des Fit-Modus: setFitToWidth(false)
|
||||||
// löst einen system-bedingten Reset von hvalue auf 0.0 aus. Statt
|
// löst Layout-, CSS- und Property-Reset-Passes innerhalb desselben
|
||||||
// diesen Reset per Timing zu umgehen (was nicht zuverlässig ist),
|
// JavaFX-Frames aus. Ein AnimationTimer feuert handle() nach allen
|
||||||
// wird er aktiv abgefangen: Ein einmaliger ChangeListener auf
|
// diesen Passes des aktuellen Frames; das ist der einzige Punkt,
|
||||||
// hvalueProperty feuert beim Reset, entfernt sich sofort selbst
|
// an dem setHvalue(0.5)/setVvalue(0.5) garantiert nicht mehr von
|
||||||
// (Single-Shot) und postet anschließend die Zentrierung via
|
// einem nachträglichen Reset überschrieben werden. stop() im ersten
|
||||||
// Platform.runLater. So wirkt setHvalue(0.5)/setVvalue(0.5)
|
// handle()-Aufruf macht den Timer zum Single-Shot.
|
||||||
// garantiert nach dem Reset – ohne mehrfaches runLater oder
|
new AnimationTimer() {
|
||||||
// layout()-Hacks.
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
public void handle(long now) {
|
||||||
final ChangeListener<Number>[] holder = new ChangeListener[1];
|
stop();
|
||||||
holder[0] = (obs, oldVal, newVal) -> {
|
|
||||||
scrollPane.hvalueProperty().removeListener(holder[0]);
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
scrollPane.setHvalue(0.5);
|
scrollPane.setHvalue(0.5);
|
||||||
scrollPane.setVvalue(0.5);
|
scrollPane.setVvalue(0.5);
|
||||||
});
|
}
|
||||||
};
|
}.start();
|
||||||
scrollPane.hvalueProperty().addListener(holder[0]);
|
|
||||||
} else {
|
} else {
|
||||||
// Folge-Schritte: aktuelle Scroll-Position bewahren
|
// Folge-Schritte: aktuelle Scroll-Position bewahren
|
||||||
double hval = scrollPane.getHvalue();
|
double hval = scrollPane.getHvalue();
|
||||||
|
|||||||
Reference in New Issue
Block a user