我正在创建UI编辑器,为此我需要在鼠标事件上绘制UI组件。我一直坚持使用带有标题的绘图按钮。由于我在stackoverflow上搜索,我尝试使用StackPane创建带标题的Rectangle。 对于布局I,使用Group元素。问题是,当我将StackPane添加到Group时,它会显示在Group的左上角。但是,如果我只绘制矩形本身,它会显示在那个地方,我释放鼠标。 如何为StackPane实现相同的效果?
这是我的代码:
public class Main extends Application {
double startingPointX, startingPointY;
Group rectanglesGroup = new Group();
Rectangle newRectangle = null;
boolean newRectangleIsBeingDrawn = false;
// the following method adjusts coordinates so that the rectangle
// is shown "in a correct way" in relation to the mouse event
void adjustRectanglePRoperties(double startingPointX,
double startingPointY, double endingPointX, double endingPointY,
Rectangle givenRectangle) {
givenRectangle.setX(startingPointX);
givenRectangle.setY(startingPointY);
givenRectangle.setWidth(endingPointX - startingPointX);
givenRectangle.setHeight(endingPointY - startingPointY);
if (givenRectangle.getWidth() < 0) {
givenRectangle.setWidth(-givenRectangle.getWidth());
givenRectangle.setX(givenRectangle.getX()
- givenRectangle.getWidth());
}
if (givenRectangle.getHeight() < 0) {
givenRectangle.setHeight(-givenRectangle.getHeight());
givenRectangle.setY(givenRectangle.getY()
- givenRectangle.getHeight());
}
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Drawing rectangles");
Scene scene = new Scene(rectanglesGroup, 800, 600);
scene.setFill(Color.BEIGE);
scene.setOnMousePressed(e -> {
if (newRectangleIsBeingDrawn == false) {
startingPointX = e.getSceneX();
startingPointY = e.getSceneY();
newRectangle = new Rectangle();
// a non finished rectangle has always the same color
newRectangle.setFill(Color.SNOW); // almost white color
//Line line = new Line(20,120,270,120);
newRectangle.setStroke(Color.BLACK);
newRectangle.setStrokeWidth(1);
newRectangle.getStrokeDashArray().addAll(3.0, 7.0, 3.0, 7.0);
rectanglesGroup.getChildren().add(newRectangle);
newRectangleIsBeingDrawn = true;
}
});
scene.setOnMouseDragged(e -> {
if (newRectangleIsBeingDrawn == true) {
double currentEndingPointX = e.getSceneX();
double currentEndingPointY = e.getSceneY();
adjustRectanglePRoperties(startingPointX, startingPointY,
currentEndingPointX, currentEndingPointY, newRectangle);
}
});
scene.setOnMouseReleased(e->{
if(newRectangleIsBeingDrawn == true){
//now the drawing of the new rectangle is finished
//let's set the final color for the rectangle
/******************Drawing textbox*******************************/
//newRectangle.setFill(Color.WHITE);
//newRectangle.getStrokeDashArray().removeAll(3.0, 7.0, 3.0, 7.0);
/****************************************************************/
/*****************Drawing button*********************************/
Image image = new Image("file:button.png");
ImagePattern buttonImagePattern = new ImagePattern(image);
newRectangle.setFill(buttonImagePattern);
newRectangle.setStroke(Color.WHITE);
newRectangle.getStrokeDashArray().removeAll(3.0,7.0,3.0,7.0);
Text text = new Text("Button");
rectanglesGroup.getChildren().remove(newRectangle);
StackPane stack = new StackPane();
stack.getChildren().addAll(newRectangle, text);
rectanglesGroup.getChildren().add(stack);
/****************************************************************/
colorIndex++; //index for the next color to use
//if all colors have been used we'll start re-using colors
//from the beginning of the array
if(colorIndex>=rectangleColors.length){
colorIndex=0;
}
newRectangle=null;
newRectangleIsBeingDrawn=false;
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我使用OnMouseReleased事件来创建组件。
我查找了setX,setPosition或类似这样的方法,但无法在StackPane的方法中找到它们。 而且我不知道翻译方法是如何工作的。所以我没有尝试过它们来实现我的目标。
答案 0 :(得分:2)
您应该阅读有关JavaFX Node的文档。
您可以通过setLayoutX(和Y)或相对来自setTranslateX(和Y)绝对定位节点,这会增加当前布局位置。
StackPane只是一个容器,在您的情况下,与您要放置在场景中的任何其他节点没有什么不同。只需创建它,设置尺寸和位置并将其放在场景中。
您的代码不起作用,所以我创建了自己的代码。以下是有关如何处理此问题的示例代码:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeLineCap;
import javafx.stage.Stage;
public class RubberBandSelectionDemo extends Application {
CheckBox drawButtonCheckBox;
public static void main(String[] args) {
launch(args);
}
Pane root;
@Override
public void start(Stage primaryStage) {
root = new Pane();
root.setStyle("-fx-background-color:white");
root.setPrefSize(1024, 768);
drawButtonCheckBox = new CheckBox( "Draw Button");
root.getChildren().add( drawButtonCheckBox);
primaryStage.setScene(new Scene(root, root.getWidth(), root.getHeight()));
primaryStage.show();
new RubberBandSelection(root);
}
public class RubberBandSelection {
final DragContext dragContext = new DragContext();
Rectangle rect;
Pane group;
public RubberBandSelection( Pane group) {
this.group = group;
rect = new Rectangle( 0,0,0,0);
rect.setStroke(Color.BLUE);
rect.setStrokeWidth(1);
rect.setStrokeLineCap(StrokeLineCap.ROUND);
rect.setFill(Color.LIGHTBLUE.deriveColor(0, 1.2, 1, 0.6));
group.addEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressedEventHandler);
group.addEventHandler(MouseEvent.MOUSE_DRAGGED, onMouseDraggedEventHandler);
group.addEventHandler(MouseEvent.MOUSE_RELEASED, onMouseReleasedEventHandler);
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
dragContext.mouseAnchorX = event.getSceneX();
dragContext.mouseAnchorY = event.getSceneY();
rect.setX(dragContext.mouseAnchorX);
rect.setY(dragContext.mouseAnchorY);
rect.setWidth(0);
rect.setHeight(0);
group.getChildren().add( rect);
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// get coordinates
double x = rect.getX();
double y = rect.getY();
double w = rect.getWidth();
double h = rect.getHeight();
if( drawButtonCheckBox.isSelected()) {
// create button
Button node = new Button();
node.setDefaultButton(false);
node.setPrefSize(w, h);
node.setText("Button");
node.setLayoutX(x);
node.setLayoutY(y);
root.getChildren().add( node);
} else {
// create rectangle
Rectangle node = new Rectangle( 0, 0, w, h);
node.setStroke( Color.BLACK);
node.setFill( Color.BLACK.deriveColor(0, 0, 0, 0.3));
node.setLayoutX( x);
node.setLayoutY( y);
root.getChildren().add( node);
}
// remove rubberband
rect.setX(0);
rect.setY(0);
rect.setWidth(0);
rect.setHeight(0);
group.getChildren().remove( rect);
}
};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
double offsetX = event.getSceneX() - dragContext.mouseAnchorX;
double offsetY = event.getSceneY() - dragContext.mouseAnchorY;
if( offsetX > 0)
rect.setWidth( offsetX);
else {
rect.setX(event.getSceneX());
rect.setWidth(dragContext.mouseAnchorX - rect.getX());
}
if( offsetY > 0) {
rect.setHeight( offsetY);
} else {
rect.setY(event.getSceneY());
rect.setHeight(dragContext.mouseAnchorY - rect.getY());
}
}
};
private final class DragContext {
public double mouseAnchorX;
public double mouseAnchorY;
}
}
}
这是一张图片:
演示显示橡皮筋选择,允许您绘制选择矩形。释放鼠标按钮时,将绘制矩形或按钮,具体取决于左上角的“绘制按钮”复选框选项。如果您想绘制StackPane,只需在鼠标释放处理程序中相应地更改代码。
当然,如果您想直接绘制组件而不是橡皮筋,只需将橡皮筋选择代码中的矩形与e交换。 G。一个按钮。这里只是Button绘图代码,只需在上面的示例中替换它。
public class RubberBandSelection {
final DragContext dragContext = new DragContext();
Button button;
Pane group;
public RubberBandSelection( Pane group) {
this.group = group;
button = new Button();
button.setPrefSize(0, 0);
group.addEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressedEventHandler);
group.addEventHandler(MouseEvent.MOUSE_DRAGGED, onMouseDraggedEventHandler);
group.addEventHandler(MouseEvent.MOUSE_RELEASED, onMouseReleasedEventHandler);
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
dragContext.mouseAnchorX = event.getSceneX();
dragContext.mouseAnchorY = event.getSceneY();
button.setLayoutX(dragContext.mouseAnchorX);
button.setLayoutY(dragContext.mouseAnchorY);
button.setPrefWidth(0);
button.setPrefHeight(0);
group.getChildren().add( button);
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// get coordinates
double x = button.getLayoutX();
double y = button.getLayoutY();
double w = button.getWidth();
double h = button.getHeight();
// create button
Button node = new Button();
node.setDefaultButton(false);
node.setPrefSize(w, h);
node.setText("Button");
node.setLayoutX(x);
node.setLayoutY(y);
root.getChildren().add( node);
// remove rubberband
button.setLayoutX(0);
button.setLayoutY(0);
button.setPrefWidth(0);
button.setPrefHeight(0);
group.getChildren().remove( button);
}
};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
double offsetX = event.getSceneX() - dragContext.mouseAnchorX;
double offsetY = event.getSceneY() - dragContext.mouseAnchorY;
if( offsetX > 0)
button.setPrefWidth( offsetX);
else {
button.setLayoutX(event.getSceneX());
button.setPrefWidth(dragContext.mouseAnchorX - button.getLayoutX());
}
if( offsetY > 0) {
button.setPrefHeight( offsetY);
} else {
button.setLayoutY(event.getSceneY());
button.setPrefHeight(dragContext.mouseAnchorY - button.getLayoutY());
}
}
};
private final class DragContext {
public double mouseAnchorX;
public double mouseAnchorY;
}
}