Масштабирование слайдера происходит неправильно при привязке ползунка к свойству масштаба.JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Масштабирование слайдера происходит неправильно при привязке ползунка к свойству масштаба.

Сообщение Anonymous »

Введение
Следующий код демонстрирует функции масштабирования и перетаскивания ImageView в области просмотра. Масштаб можно регулировать, прокручивая колесо мыши или используя ползунок. При этом перетаскивание осуществляется нажатием правой кнопки мыши и перемещением мыши.
Чтобы объединить эти преобразования, я использую преобразование Affine. Scale, tx и ty — это двойные свойства с прослушивателями, поэтому всякий раз, когда устанавливается новое значение, происходит преобразование.
События и преобразования
Viewport.setOnMousePressed захватывает координаты (x,y) того места, где происходит щелчок в области просмотра, и сохраняет их с помощью объекта Delta.
Метод viewport.setOnMouseDragged вычисляет новые координаты (dx, dy). Затем он обновляет tx и ty, добавляя dx и dy соответственно. Это запускает преобразование, которое перемещает изображение в новую позицию.
Viewport.setOnMouseClicked используется для обнаружения двойных щелчков. При срабатывании centerFit вызывается с масштабом = 1, tx = 0 и ty = 0, снова центрируя изображение.
Viewport.addEventFilter(ScrollEvent.SCROLL, e -> определяет, происходит ли прокрутка внутрь или наружу. Затем он ограничивает масштаб между MIN_SCALE, MAX_SCALE и oldScale с помощью функции зажима. Наконец, он смещает и масштабирует изображение, гарантируя, что указатель мыши остается над масштабируемой точкой.
slider.valueProperty().addListener работает аналогично функции масштабирования с помощью колесика прокрутки, но увеличивает и уменьшает масштаб вокруг центра изображения.
Итак, вкратце, вот как это происходит. работа:

EventHandler ---> обновить свойства ---> создать аффинное преобразование

Код
Класс ZoomAndShiftImage, реализует все, что было объяснено выше

Код: Выделить всё

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Affine;
import javafx.stage.Stage;
import javafx.scene.control.Slider;
import javafx.util.StringConverter;

import java.util.Objects;

public class ZoomAndShiftImage extends Application {
private final double MIN_SCALE = 0.25;
private final double MAX_SCALE = 8.0;
private static double DEFAULT_SCALE;

@Override
public void start(Stage stage) {
Image image = new Image(Objects.requireNonNull(Objects.requireNonNull(getClass().getResourceAsStream("path/to/image"))));
ImageView imageView = new ImageView(image);
imageView.setPreserveRatio(true);
imageView.setSmooth(true);

Affine affine = new Affine();
imageView.getTransforms().add(affine);

Pane viewport = new Pane(imageView);
Rectangle clip = new Rectangle();

clip.widthProperty().bind(viewport.widthProperty());
clip.heightProperty().bind(viewport.heightProperty());

viewport.setClip(clip);
viewport.setStyle("-fx-background-color: #1d2026;");

// --- Model properties for transform- zoom(scale) and shift(translate)
DoubleProperty scale = new SimpleDoubleProperty(1.0); // zoom
DoubleProperty tx = new SimpleDoubleProperty(0); // shift at the x-axis
DoubleProperty ty = new SimpleDoubleProperty(0); // shift at the y-axis

Runnable applyTransform = () -> {
affine.setToTransform(scale.get(), 0, tx.get(), 0, scale.get(), ty.get());
};

// Apply transformation whe the property is changed
scale.addListener((_, _, _) -> applyTransform.run());
tx.addListener((_, _, _) -> applyTransform.run());
ty.addListener((_, _, _) -> applyTransform.run());

applyTransform.run();

final Delta drag = new Delta();
Slider slider = getSlider();
slider.valueProperty().bindBidirectional(scale);

viewport.setOnMousePressed(e -> {
if (e.getButton() == MouseButton.PRIMARY) {
// Save the current coordinates of the click
drag.x = e.getX();
drag.y = e.getY();
}
});

viewport.setOnMouseDragged(e -> {
double dx = e.getX() - drag.x;
double dy = e.getY() - drag.y;

drag.x = e.getX();
drag.y = e.getY();

tx.set(tx.get() + dx);
ty.set(ty.get() + dy);
});

viewport.setOnMouseClicked(e -> {
if (e.getClickCount() == 2 && e.getButton() == MouseButton.PRIMARY) {
scale.set(1.0);
tx.set(0.0);
ty.set(0.0);

centerFit(imageView, viewport, scale, tx, ty);
}
});

viewport.addEventFilter(ScrollEvent.SCROLL, e -> {
Point2D pivotOnImage = imageView.sceneToLocal(e.getSceneX(), e.getSceneY());

if (!imageView.getBoundsInLocal().contains(pivotOnImage))
return;

double direction = (e.getDeltaY() >  0) ? 1.1 : (1 / 1.1);
double oldScale = scale.get();
double newScale = clamp(oldScale, direction);

if (newScale == 0) {
scale.set(1.0);
tx.set(0.0);
ty.set(0.0);

centerFit(imageView, viewport, scale, tx, ty);
return;
}

tx.set(tx.get() + (oldScale - newScale) * pivotOnImage.getX());
ty.set(ty.get() + (oldScale - newScale) * pivotOnImage.getY());
scale.set(newScale);

e.consume();
});

slider.valueProperty().addListener((_, _, newV) -> {
double oldScale = scale.get();
double newScale = newV.doubleValue();

if (Math.abs(newScale - oldScale) < 1e-12)
return;

Point2D centerInScene = viewport.localToScene(viewport.getWidth() / 2.0, viewport.getHeight() / 2.0);
Point2D pivotOnImage = imageView.sceneToLocal(centerInScene);

tx.set(tx.get() + (oldScale - newScale) * pivotOnImage.getX());
ty.set(ty.get() + (oldScale - newScale) * pivotOnImage.getY());
scale.set(newScale);
});

// Center the image whenever the window is resized
viewport.layoutBoundsProperty().addListener((_, _, _) ->
centerFit(imageView, viewport, scale, tx, ty));

BorderPane root = new BorderPane(viewport);
root.setBottom(slider);

Scene scene = new Scene(root, 900, 600, Color.BLACK);
stage.setTitle("JavaFX ImageView: Zoom (wheel) + Pan (drag)");
stage.setScene(scene);
stage.show();

DEFAULT_SCALE = scale.get() * (1 / 1.1);
}

private Slider getSlider() {
Slider slider = new Slider(1, MAX_SCALE, 1.0);
slider.setBlockIncrement(0.1);
slider.setMajorTickUnit(1.0);
slider.setMinorTickCount(9);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);

slider.setLabelFormatter(new StringConverter() {
@Override
public String toString(Double v) {
if (Math.abs(v - 0.0) < 1e-6) return "0.25x";
if (Math.abs(v - 0.5) < 1e-6) return "0.5x";
if (Math.abs(v - 1.0) < 1e-6) return "1x";
if (Math.abs(v - 2.0) < 1e-6) return "2x";
if (Math.abs(v - 4.0) < 1e-6) return "4x";
if (Math.abs(v - 8.0) < 1e-6) return "8x";
return String.format("%.2fx", v);
}

@Override
public Double fromString(String s) {
return 1.0;
}
});
return slider;
}

private void centerFit(ImageView imageView, Pane viewport, DoubleProperty scale, DoubleProperty tx, DoubleProperty ty) {
Image image = imageView.getImage();
if (image == null || image.getWidth() 

Подробнее здесь: [url]https://stackoverflow.com/questions/79800110/zoom-by-slider-goes-awry-when-binding-the-slider-to-the-scale-property[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»