ScrollPane 没有 "know" 何时展开
ScrollPane doesnt "know" when to expand
我不确定如何称呼这个问题,但你一定会明白我的意思...
至少我希望你会。
首先:我的 Pane 中有一个 ScrollPane。此窗格还包含两个按钮,我可以在其上在我的 ScrollPane 中创建矩形。
我可以四处拖动这些矩形,然后将它们移出视图。到目前为止,除了 ScrollPane 之外,一切正常。通常你让 ScrollPane 展开他的 Scroll 这样你就可以,如果你放开 Rectangle,滚动到那个 Rectangle 并再次抓住它但是友好的 JavaFX 不知道如何展开 Scroll 所以我无法再次到达这个 Rectangle。
或者我只是错过了一些重要的部分(这是更有可能发生的事情)
关于我的代码的一些话:我认为这不是我现有代码中的问题,而是一个需要解决方法的问题。我为 ScrollPane 所做的唯一更改是我将 ScrollBarPolicy 设置为始终并设置 ScrollPane Pannable 但当我单击 Rectangle 时会消耗它,因此我可以移动它们而不平移 ScrollPane。
您在上面看到的是一个完整大小的矩形和一个部分超出 ScrollPane 边界但 ScrollPane 没有展开 ScrollBar 的矩形。
不管我将 Rectangle 移离这些边界多远,Scrollbar 都不会改变,这是我选择 ScrollPane 的唯一原因,而且我认为这是实现此目的的唯一(最简单)窗格 "editor like" 视图。
是的,至少感谢您阅读到这里,并且总是为我的英语蹩脚感到抱歉^^。我希望你能给我一个如何解决这个问题的建议!
编辑:
这是一个最小的例子:
Controller.java
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
public class Controller implements Initializable{
@FXML ScrollPane actionWin;
Rectangle r;
Double orgTranslateX, orgTranslateY, orgSceneX, orgSceneY, newTranslateX, newTranslateY, offsetY, offsetX;
int i = 50;
List<Rectangle> recs = new ArrayList<Rectangle>();
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
actionWin.setPannable(true);
actionWin.setHbarPolicy(ScrollBarPolicy.ALWAYS);
actionWin.setVbarPolicy(ScrollBarPolicy.ALWAYS);
}
@FXML
public void createEntity(){
Pane container = new Pane();
// Button 1
r = new Rectangle();
r.addEventHandler(MouseEvent.ANY, event -> {
if(event.getButton() != MouseButton.MIDDLE) event.consume();
});
r.setOnMousePressed(onMousePressedEventHandler);
r.setOnMouseDragged(onMouseDraggedEventHandler);
r.setX(i);
r.setY(i);
r.setWidth(50);
r.setHeight(20);
i+=30;
recs.add(r);
for(Rectangle rec : recs){
container.getChildren().add(rec);
}
actionWin.setContent(container);
try {
AnchorPane root = (AnchorPane) FXMLLoader.load(getClass().getResource("Main.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent arg0) {
orgSceneX = arg0.getSceneX();
orgSceneY = arg0.getSceneY();
orgTranslateX = ((Rectangle) (arg0.getSource())).getTranslateX();
orgTranslateY = ((Rectangle) (arg0.getSource())).getTranslateY();
}};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent arg0) {
offsetX = arg0.getSceneX() - orgSceneX;
offsetY = arg0.getSceneY() - orgSceneY;
newTranslateX = orgTranslateX + offsetX;
newTranslateY = orgTranslateY + offsetY;
((Rectangle)(arg0.getSource())).setTranslateX(newTranslateX);
((Rectangle)(arg0.getSource())).setTranslateY(newTranslateY);
}};
}
Main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="root" maxHeight="720.0" maxWidth="1280.0" minHeight="720.0" minWidth="1280.0" prefHeight="720.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<Button fx:id="createEntity_B" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onAction="#createEntity" text="Create Entity" />
<ScrollPane fx:id="actionWin" layoutX="14.0" layoutY="39.0" prefHeight="672.0" prefWidth="996.0" />
</children>
</AnchorPane>
Main.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
public void start(Stage primaryStage) {
try {
AnchorPane root = (AnchorPane)
FXMLLoader.load(getClass().getResource("Main.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
将这三个 类 包装在一个名为 "application" 的包中,您就可以开始了。
您正在使用 translateX
和 translateY
来确定 Rectangle
的新位置。
当 parent 确定其大小时,不考虑像翻译属性这样的转换。 child 被视为位于 (layoutX, layoutY)
。如果您希望 Pane
正确调整大小,您需要修改这些属性。
createEntity
中的其他一些内容看起来很奇怪:
- 您重新创建
Pane
而不是在 fxml 中创建一次。
- 您加载了一个似乎从未被使用过的 fxml。
此外,除非您不进行任何算术运算或比较,否则您应该更喜欢原始类型 double
而不是引用类型 Double
。
<AnchorPane fx:id="root" maxHeight="720.0" maxWidth="1280.0" minHeight="720.0" minWidth="1280.0" prefHeight="720.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<Button fx:id="createEntity_B" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onAction="#createEntity" text="Create Entity" />
<ScrollPane fx:id="actionWin" layoutX="14.0" layoutY="39.0" prefHeight="672.0" prefWidth="996.0">
<content>
<Pane fx:id="container"/>
</content>
</ScrollPane>
</children>
</AnchorPane>
@FXML
private Pane container;
@FXML
public void createEntity() {
class DraggedHandler implements EventHandler<MouseEvent> {
double offsetX;
double offsetY;
@Override
public void handle(MouseEvent event) {
Node source = (Node) event.getSource();
Point2D pt = source.localToParent(event.getX(), event.getY());
source.setLayoutX(pt.getX() + offsetX);
source.setLayoutY(pt.getY() + offsetY);
}
}
Rectangle rect = new Rectangle(i, i, 50, 20);
i += 30;
container.getChildren().add(rect);
rect.addEventHandler(MouseEvent.ANY, event -> {
if (event.getButton() != MouseButton.MIDDLE) {
event.consume();
}
});
DraggedHandler handler = new DraggedHandler();
rect.setOnMouseDragged(handler);
rect.setOnMousePressed(evt -> {
Node source = (Node) evt.getSource();
Point2D pt = source.localToParent(evt.getX(), evt.getY());
handler.offsetX = source.getLayoutX() - pt.getX();
handler.offsetY = source.getLayoutY() - pt.getY();
});
}
我不确定如何称呼这个问题,但你一定会明白我的意思... 至少我希望你会。
首先:我的 Pane 中有一个 ScrollPane。此窗格还包含两个按钮,我可以在其上在我的 ScrollPane 中创建矩形。
我可以四处拖动这些矩形,然后将它们移出视图。到目前为止,除了 ScrollPane 之外,一切正常。通常你让 ScrollPane 展开他的 Scroll 这样你就可以,如果你放开 Rectangle,滚动到那个 Rectangle 并再次抓住它但是友好的 JavaFX 不知道如何展开 Scroll 所以我无法再次到达这个 Rectangle。
或者我只是错过了一些重要的部分(这是更有可能发生的事情)
关于我的代码的一些话:我认为这不是我现有代码中的问题,而是一个需要解决方法的问题。我为 ScrollPane 所做的唯一更改是我将 ScrollBarPolicy 设置为始终并设置 ScrollPane Pannable 但当我单击 Rectangle 时会消耗它,因此我可以移动它们而不平移 ScrollPane。
您在上面看到的是一个完整大小的矩形和一个部分超出 ScrollPane 边界但 ScrollPane 没有展开 ScrollBar 的矩形。 不管我将 Rectangle 移离这些边界多远,Scrollbar 都不会改变,这是我选择 ScrollPane 的唯一原因,而且我认为这是实现此目的的唯一(最简单)窗格 "editor like" 视图。
是的,至少感谢您阅读到这里,并且总是为我的英语蹩脚感到抱歉^^。我希望你能给我一个如何解决这个问题的建议!
编辑:
这是一个最小的例子: Controller.java
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
public class Controller implements Initializable{
@FXML ScrollPane actionWin;
Rectangle r;
Double orgTranslateX, orgTranslateY, orgSceneX, orgSceneY, newTranslateX, newTranslateY, offsetY, offsetX;
int i = 50;
List<Rectangle> recs = new ArrayList<Rectangle>();
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
actionWin.setPannable(true);
actionWin.setHbarPolicy(ScrollBarPolicy.ALWAYS);
actionWin.setVbarPolicy(ScrollBarPolicy.ALWAYS);
}
@FXML
public void createEntity(){
Pane container = new Pane();
// Button 1
r = new Rectangle();
r.addEventHandler(MouseEvent.ANY, event -> {
if(event.getButton() != MouseButton.MIDDLE) event.consume();
});
r.setOnMousePressed(onMousePressedEventHandler);
r.setOnMouseDragged(onMouseDraggedEventHandler);
r.setX(i);
r.setY(i);
r.setWidth(50);
r.setHeight(20);
i+=30;
recs.add(r);
for(Rectangle rec : recs){
container.getChildren().add(rec);
}
actionWin.setContent(container);
try {
AnchorPane root = (AnchorPane) FXMLLoader.load(getClass().getResource("Main.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent arg0) {
orgSceneX = arg0.getSceneX();
orgSceneY = arg0.getSceneY();
orgTranslateX = ((Rectangle) (arg0.getSource())).getTranslateX();
orgTranslateY = ((Rectangle) (arg0.getSource())).getTranslateY();
}};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent arg0) {
offsetX = arg0.getSceneX() - orgSceneX;
offsetY = arg0.getSceneY() - orgSceneY;
newTranslateX = orgTranslateX + offsetX;
newTranslateY = orgTranslateY + offsetY;
((Rectangle)(arg0.getSource())).setTranslateX(newTranslateX);
((Rectangle)(arg0.getSource())).setTranslateY(newTranslateY);
}};
}
Main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="root" maxHeight="720.0" maxWidth="1280.0" minHeight="720.0" minWidth="1280.0" prefHeight="720.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<Button fx:id="createEntity_B" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onAction="#createEntity" text="Create Entity" />
<ScrollPane fx:id="actionWin" layoutX="14.0" layoutY="39.0" prefHeight="672.0" prefWidth="996.0" />
</children>
</AnchorPane>
Main.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
public void start(Stage primaryStage) {
try {
AnchorPane root = (AnchorPane)
FXMLLoader.load(getClass().getResource("Main.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
将这三个 类 包装在一个名为 "application" 的包中,您就可以开始了。
您正在使用 translateX
和 translateY
来确定 Rectangle
的新位置。
当 parent 确定其大小时,不考虑像翻译属性这样的转换。 child 被视为位于 (layoutX, layoutY)
。如果您希望 Pane
正确调整大小,您需要修改这些属性。
createEntity
中的其他一些内容看起来很奇怪:
- 您重新创建
Pane
而不是在 fxml 中创建一次。 - 您加载了一个似乎从未被使用过的 fxml。
此外,除非您不进行任何算术运算或比较,否则您应该更喜欢原始类型 double
而不是引用类型 Double
。
<AnchorPane fx:id="root" maxHeight="720.0" maxWidth="1280.0" minHeight="720.0" minWidth="1280.0" prefHeight="720.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<children>
<Button fx:id="createEntity_B" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onAction="#createEntity" text="Create Entity" />
<ScrollPane fx:id="actionWin" layoutX="14.0" layoutY="39.0" prefHeight="672.0" prefWidth="996.0">
<content>
<Pane fx:id="container"/>
</content>
</ScrollPane>
</children>
</AnchorPane>
@FXML
private Pane container;
@FXML
public void createEntity() {
class DraggedHandler implements EventHandler<MouseEvent> {
double offsetX;
double offsetY;
@Override
public void handle(MouseEvent event) {
Node source = (Node) event.getSource();
Point2D pt = source.localToParent(event.getX(), event.getY());
source.setLayoutX(pt.getX() + offsetX);
source.setLayoutY(pt.getY() + offsetY);
}
}
Rectangle rect = new Rectangle(i, i, 50, 20);
i += 30;
container.getChildren().add(rect);
rect.addEventHandler(MouseEvent.ANY, event -> {
if (event.getButton() != MouseButton.MIDDLE) {
event.consume();
}
});
DraggedHandler handler = new DraggedHandler();
rect.setOnMouseDragged(handler);
rect.setOnMousePressed(evt -> {
Node source = (Node) evt.getSource();
Point2D pt = source.localToParent(evt.getX(), evt.getY());
handler.offsetX = source.getLayoutX() - pt.getX();
handler.offsetY = source.getLayoutY() - pt.getY();
});
}