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.PDFRenderer;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.embed.swing.SwingFXUtils;
|
||||
import javafx.geometry.Bounds;
|
||||
import javafx.geometry.Insets;
|
||||
@@ -729,24 +729,20 @@ public final class PdfPreviewPane {
|
||||
|
||||
if (wasInFitMode) {
|
||||
// Erster Zoom-Schritt nach Verlassen des Fit-Modus: setFitToWidth(false)
|
||||
// löst einen system-bedingten Reset von hvalue auf 0.0 aus. Statt
|
||||
// diesen Reset per Timing zu umgehen (was nicht zuverlässig ist),
|
||||
// wird er aktiv abgefangen: Ein einmaliger ChangeListener auf
|
||||
// hvalueProperty feuert beim Reset, entfernt sich sofort selbst
|
||||
// (Single-Shot) und postet anschließend die Zentrierung via
|
||||
// Platform.runLater. So wirkt setHvalue(0.5)/setVvalue(0.5)
|
||||
// garantiert nach dem Reset – ohne mehrfaches runLater oder
|
||||
// layout()-Hacks.
|
||||
@SuppressWarnings("unchecked")
|
||||
final ChangeListener<Number>[] holder = new ChangeListener[1];
|
||||
holder[0] = (obs, oldVal, newVal) -> {
|
||||
scrollPane.hvalueProperty().removeListener(holder[0]);
|
||||
Platform.runLater(() -> {
|
||||
// löst Layout-, CSS- und Property-Reset-Passes innerhalb desselben
|
||||
// JavaFX-Frames aus. Ein AnimationTimer feuert handle() nach allen
|
||||
// diesen Passes des aktuellen Frames; das ist der einzige Punkt,
|
||||
// an dem setHvalue(0.5)/setVvalue(0.5) garantiert nicht mehr von
|
||||
// einem nachträglichen Reset überschrieben werden. stop() im ersten
|
||||
// handle()-Aufruf macht den Timer zum Single-Shot.
|
||||
new AnimationTimer() {
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
stop();
|
||||
scrollPane.setHvalue(0.5);
|
||||
scrollPane.setVvalue(0.5);
|
||||
});
|
||||
};
|
||||
scrollPane.hvalueProperty().addListener(holder[0]);
|
||||
}
|
||||
}.start();
|
||||
} else {
|
||||
// Folge-Schritte: aktuelle Scroll-Position bewahren
|
||||
double hval = scrollPane.getHvalue();
|
||||
|
||||
Reference in New Issue
Block a user