- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我的 JAVAFX 应用程序具有缩放和缩放功能,如下所述: Scale at pivot point in an already scaled node我需要实现的是将图像放在右 Pane 中,并将图像保持在左侧,如下图所示。
问题如何将此应用程序嵌入到 SPlitPane 中,左侧是另一个面板。
SplitPane splitPane = new SplitPane();
splitPane.getItems().add(new Label("Left Panel"));
splitPane.getItems().add(group);
Scene scene = new Scene(splitPane, 1024, 768);
不幸的是代码导致了错误的坐标,
最佳答案
要在 ScrollPane
内进行缩放,您需要调整滚动位置。这比仅附加一个转换要复杂一些,如果不使用 ScrollPane
,则可以完成。
基本上,您需要在缩放节点之前检查当前滚动位置,并在缩放之后修改滚动位置,以防止轴心点由于更改的比例因子而改变其位置。
以下示例允许您在网格“中”移动一个圆圈,并在不单击圆圈(可平移 ScrollPane
)时围绕网格移动,此外还允许您在移动时调整缩放比例按住 CTRL 键的同时滚动鼠标滚轮。
import java.net.MalformedURLException;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class PivotZoom extends Application {
public static Region createContent() {
double width = 1000;
double height = 1000;
Canvas canvas = new Canvas(width, height);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.LIGHTGREY);
gc.fillRect(0, 0, width, height);
gc.setStroke(Color.BLUE);
gc.beginPath();
for (int i = 50; i < width; i += 50) {
gc.moveTo(i, 0);
gc.lineTo(i, height);
}
for (int i = 50; i < height; i += 50) {
gc.moveTo(0, i);
gc.lineTo(width, i);
}
gc.stroke();
Pane content = new Pane(
new Circle(50, 50, 20),
new Circle(120, 90, 20, Color.RED),
new Circle(200, 70, 20, Color.GREEN)
);
StackPane result = new StackPane(canvas, content);
result.setAlignment(Pos.TOP_LEFT);
class DragData {
double startX;
double startY;
double startLayoutX;
double startLayoutY;
Node dragTarget;
}
DragData dragData = new DragData();
content.setOnMousePressed(evt -> {
if (evt.getTarget() != content) {
// initiate drag gesture, if a child of content receives the
// event to prevent ScrollPane from panning.
evt.consume();
evt.setDragDetect(true);
}
});
content.setOnDragDetected(evt -> {
Node n = (Node) evt.getTarget();
if (n != content) {
// set start paremeters
while (n.getParent() != content) {
n = n.getParent();
}
dragData.startX = evt.getX();
dragData.startY = evt.getY();
dragData.startLayoutX = n.getLayoutX();
dragData.startLayoutY = n.getLayoutY();
dragData.dragTarget = n;
n.startFullDrag();
evt.consume();
}
});
// stop dragging when mouse is released
content.setOnMouseReleased(evt -> dragData.dragTarget = null);
content.setOnMouseDragged(evt -> {
if (dragData.dragTarget != null) {
// move dragged node
dragData.dragTarget.setLayoutX(evt.getX() + dragData.startLayoutX - dragData.startX);
dragData.dragTarget.setLayoutY(evt.getY() + dragData.startLayoutY - dragData.startY);
Point2D p = new Point2D(evt.getX(), evt.getY());
evt.consume();
}
});
return result;
}
@Override
public void start(Stage primaryStage) throws MalformedURLException {
Region zoomTarget = createContent();
zoomTarget.setPrefSize(1000, 1000);
zoomTarget.setOnDragDetected(evt -> {
Node target = (Node) evt.getTarget();
while (target != zoomTarget && target != null) {
target = target.getParent();
}
if (target != null) {
target.startFullDrag();
}
});
Group group = new Group(zoomTarget);
// stackpane for centering the content, in case the ScrollPane viewport
// is larget than zoomTarget
StackPane content = new StackPane(group);
group.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
// keep it at least as large as the content
content.setMinWidth(newBounds.getWidth());
content.setMinHeight(newBounds.getHeight());
});
ScrollPane scrollPane = new ScrollPane(content);
scrollPane.setPannable(true);
scrollPane.viewportBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
// use vieport size, if not too small for zoomTarget
content.setPrefSize(newBounds.getWidth(), newBounds.getHeight());
});
content.setOnScroll(evt -> {
if (evt.isControlDown()) {
evt.consume();
final double zoomFactor = evt.getDeltaY() > 0 ? 1.2 : 1 / 1.2;
Bounds groupBounds = group.getLayoutBounds();
final Bounds viewportBounds = scrollPane.getViewportBounds();
// calculate pixel offsets from [0, 1] range
double valX = scrollPane.getHvalue() * (groupBounds.getWidth() - viewportBounds.getWidth());
double valY = scrollPane.getVvalue() * (groupBounds.getHeight() - viewportBounds.getHeight());
// convert content coordinates to zoomTarget coordinates
Point2D posInZoomTarget = zoomTarget.parentToLocal(group.parentToLocal(new Point2D(evt.getX(), evt.getY())));
// calculate adjustment of scroll position (pixels)
Point2D adjustment = zoomTarget.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1));
// do the resizing
zoomTarget.setScaleX(zoomFactor * zoomTarget.getScaleX());
zoomTarget.setScaleY(zoomFactor * zoomTarget.getScaleY());
// refresh ScrollPane scroll positions & content bounds
scrollPane.layout();
// convert back to [0, 1] range
// (too large/small values are automatically corrected by ScrollPane)
groupBounds = group.getLayoutBounds();
scrollPane.setHvalue((valX + adjustment.getX()) / (groupBounds.getWidth() - viewportBounds.getWidth()));
scrollPane.setVvalue((valY + adjustment.getY()) / (groupBounds.getHeight() - viewportBounds.getHeight()));
}
});
StackPane left = new StackPane(new Label("Left Menu"));
SplitPane root = new SplitPane(left, scrollPane);
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
关于JAVAFX缩放,在ScrollPane中滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38604780/
我有带左侧和中心部分的 BorderPane,两者都是 ScrollPanes。如何使用一个滚动条(垂直)滚动它们。或者如何访问其中一个滚动条? 最佳答案 @invariant 的回答对我不起作用。但
在许多 android 应用程序中,我遇到了“列表的粘性标题”标题,我们喜欢它。 https://github.com/search?q=header+sticky+android ,现在,我正在尝试
我正在尝试从一个可平移的 ScrollPane(“子”)中“拦截”拖动事件,并将该事件重定向到另一个 ScrollPane(“父”)。 这是我这样做的尝试: import javafx.applica
我想知道 JavaFX 8 中是否有一个 ScrollPane 属性可以用来监听当前在给定时间显示的组件。 例如, ScrollPane 有一个 VBox,它有 8 个按钮。在滚动 Pane 中只能看
我有一个 scrollPane 可以通过按下按钮来滚动,使用下面的代码 @FXML public void scrollUp(ActionEvent event) { if (scrollPa
我想要实现像下图这样的结果,其中滚动条始终靠近“执行”按钮。 但是当我调整它的大小时,滚动 Pane 不遵守其约束例如 这是我的 FXML 代码:
我想知道是否有任何“简单”的方法可以将垂直滚动条设置为在按下按钮时或实际上在发生任何事件时“滚动”特定量。 例如,我有一个具有侧边栏的应用程序,侧边栏上的选项之一是“设置”。设置有子项目,我想添加单击
使用 groovy 的 SwingBuilder 设置滚动 Pane 的正确方法是什么?我正在使用 griffon,但我很难动态添加和删除组件... 这是我在 SwingPad 中尝试过的一个片段。它
我使用以下代码将 ScrollPane 中的 Applet 包含到我的 Eclipse 插件 View 中: @Override public void createPartControl(C
我在渲染 JavaFX 滚动 Pane 时遇到了问题。有时,当我滚动 Pane 时,所包含的 View 看起来“撕裂”或只是缺少某些细节。如果用户更改应用程序中的当前焦点(即通过单击新元素),则可以修
我正在为我的游戏创建一个商店,但我遇到了 libgdx ScrollPane 问题。它似乎将其中的表格向下移动了 155 像素。它所产生的效果是,表格显示在距顶部大约 155 像素的位置,并且无论我向
首先,可能有些人已经问过这个问题。不过,我确信我无法用谷歌搜索它。不管怎样,我有一个scrollPane,它有一个textArea 的viewPortView。我的问题是,当我在文本区域中插入大量组件
我想将 StackPane 作为我的根 Pane 。我想要一个scrollPane 作为场景中间的一个小盒子,并在容器下方有两个按钮。 我试图通过编写以下代码来实现它: private StackP
我有这个类(class)作为我的问题的一个例子。滚动 Pane 不滚动,我看不出一个很好的理由: import java.awt.Dimension; import javax.swing.J
我尝试使用: scrollPane.setStyle(".scroll-pane > .viewport { -fx-background-color: red; }"); 但它不起作用。我很确定我做
在我的代码中,我调用了一些项目(我的按钮名称指向不同的项目。名称和所有内容都来自数据库)我想要一个 J ScrollPane 围绕我的按钮,我该怎么办?我只想在滚动 Pane 内调用按钮。这是我的代码
我发现如果我在触摸设备上的 JavaFX 应用程序的 ScrollPane 内滑动,滚动动画会非常慢。我没有在 ScrollPane 的 ScrollBar 上滑动,而是在内容本身内滑动。 如何加快滑
我制作了一个包含 TextArea 的 ScrollPane。当TextArea通过push()方法获取额外文本时,需要将滚动条设置到底部。但是,当使用 push() 时,条形图会设置为顶部。我不知道
我有一个 VBox,我已向其中添加了 50 个标签。考虑到它包含在 ScrollPane 中,我认为它允许我向下滚动以查看其余数据,但它不允许这样做。 当我通过场景生成器构建它时,它被配置为 XML。
我可以在 JavaFX 中简单地创建一个只水平滚动的滚动 Pane ,如下所示: ScrollPane scroll = new ScrollPane(lcp); scroll.setPannable
我是一名优秀的程序员,十分优秀!