I am making an app that has a draggable background, everything is work correctly, I can drag, but I have noticed that, I can drag past my window and my scene will re-structure and allow me to drag as far as I want in a given direction, here is a snippet to show what I mean Normal before dragging
After dragging to far bottom right As noticed the scene has allowed the imageview to go as far as the mouse takes it, how can i limit it to stay within the window?
Here is my code
this.imgAdvertising.setOnMousePressed(e -> {
dragDelta.x = this.imgAdvertising.getLayoutX() - e.getSceneX();
dragDelta.y = this.imgAdvertising.getLayoutY() - e.getSceneY();
});
this.imgAdvertising.setOnMouseDragged(e -> {
double x = e.getSceneX() + dragDelta.x;
double y = e.getSceneY() + dragDelta.y;
this.imgAdvertising.setLayoutX(e.getSceneX() + dragDelta.x);
this.imgAdvertising.setLayoutY(e.getSceneY() + dragDelta.y);
});
Related
The title explains it.
So I have an application that fades to 1/2 opacity when it is not moused over and full when it is. This application is StageStyle.TRANSPARENT and moves around when the user drags their mouse.
I am wondering if there is a way to make it so that the mouse has to drag a certain (10) amount of pixels before the drag event is triggered?
Here is the code
moveWindowTemp dragDelta = new moveWindowTemp();
primaryScene.addEventFilter(MouseEvent.MOUSE_PRESSED, mouseEvent -> {
dragDelta.x = primaryStage.getX() - mouseEvent.getScreenX();
dragDelta.y = primaryStage.getY() - mouseEvent.getScreenY();
});
primaryScene.addEventFilter(MouseEvent.MOUSE_DRAGGED, mouseEvent -> {
primaryStage.setX(mouseEvent.getScreenX() + dragDelta.x);
primaryStage.setY(mouseEvent.getScreenY() + dragDelta.y);
isBeingMoved = true;
});
primaryScene.addEventFilter(MouseEvent.MOUSE_RELEASED, mouseEvent -> {
primaryStage.setX(mouseEvent.getScreenX() + dragDelta.x);
primaryStage.setY(mouseEvent.getScreenY() + dragDelta.y);
isBeingMoved = false;
});
...
public class moveWindowTemp {
double x, y;
}
If I understand your question correctly you could simply set the event as being consumed in your event filter. https://docs.oracle.com/javase/8/javafx/events-tutorial/filters.htm#BCFDCCEJ
I just added the animation part and now whenever I click on the duck it does nothing to the score, but when I comment out the animation code and the duck stays still, it increments just fine.
Full Code
Animation:
KeyValue start = new KeyValue(duck.translateXProperty(), 10);
KeyValue end = new KeyValue(duck.translateXProperty(), 400);
KeyFrame startF = new KeyFrame(Duration.ZERO, start);
KeyFrame endF = new KeyFrame(Duration.seconds(10), end);
Timeline tl = new Timeline(startF, endF);
tl.setCycleCount(Timeline.INDEFINITE);
tl.setAutoReverse(true);
tl.play();
Event Handler for Clicks:
scene.setOnMouseClicked(event -> {
if (duck.contains(event.getX(), event.getY())){
//increment score
incrementScore();
scoreDisplay.setText(""+score+"00");
}
});
Based on what you've said in the question and comments:
when I comment out the animation code and the duck stays still, it increments just fine
Whenever I click the ducks initial position, it increments the score
I'm guessing that your ImageView (the duck)'s bounding box is not getting updated.
From the ImageView docs:
This variable can be used to alter the location of a node without disturbing its layoutBounds, which makes it useful for animating a node's location.
This means that the image itself moves, and the duck is still considered to be at its initial position, so the contains() method wouldn't work. You'll have to find a different way of figuring out clicks
Perhaps what you could do is use the getTranslateX() property for your contains(), it seems like it'll get the current offset of the visual duck from the geometry duck:
scene.setOnMouseClicked(event -> {
double rawMouseX = event.getX();
double rawMouseY = event.getY();
double normalizedMouseX = rawMouseX - duck.getTranslateX();
double normalizedMouseY = rawMouseY - duck.getTranslateY();
if (duck.contains(normalizedMouseX, normalizedMouseY)){
//increment score
incrementScore();
scoreDisplay.setText(""+score+"00");
}
});
Disclaimer: I have no experience with JavaFX, I'm going mainly off of vanilla Java experience
You needn't calculate the normalized position or the mouse X/Y coordinates. You need to use the getBoundsInParent() method:
if (duck.getBoundsInParent().contains(event.getX(), event.getY())){
//increment score
incrementScore();
scoreDisplay.setText(""+score+"00");
}
Set your mouse handler on the duck, not the scene.
Also, use pickOnBounds to only react when you click on the duck's pixels, not it's bounding box.
duck.setPickOnBounds(false);
duck.setOnMouseClicked(event -> {
incrementScore();
scoreDisplay.setText(score + "00");
});
I'm trying to take a window screenshot to use that as background in the application.
This is my code:
try {
Robot robot = new Robot();
Rectangle captureSize = new Rectangle(new MainWindow().getX(), new MainWindow().getY(), MainWindow.getWIDTH(), MainWindow.getHEIGHT());
RenderManager.backgroundGUIs = robot.createScreenCapture(captureSize);
GUIManager.ThisGui = new GUI("inventory", null, false);
} catch(AWTException e) {
System.err.println("Error taking screenshot!");
}
And these are the MainWindow().getY() and MainWindow().getX() methods:
public int getX() {
return (int) frame.getLocationOnScreen().getX();
}
public int getY() {
return frame.getY();
}
Now... it works fine, but there is a problem. frame.getLocationOnScreen().getX() and frame.getX() return the location with the window border, that hasn't to be in the screensot. Ok, i can manually calculate border size to subtract it, but from Windows 7 to Windows 8, from Windows 8 to Mac, etc. window border changes.
So... is there a method to get frame position or window border size to calculate what i need?
Thank you for your time and your answer!
As simple as this:
x = frame.getRootPane().getX();
As well, you can make all other calculations according to the root pane, just dropping the frame's.
As expected, the root pane is the top-level container inside any Frame/Window/Dialog etc. It includes the menubar too.
Use this
frame.getContentPane().getSize();
Check out the Screen Image class. You can create an image of any component displayed on the frame.
So you could use frame.getRootPane() as the component you want the image of.
Or frame.getContentPane() if you don't want the menu bar. I think this method returns a Container object so you will need to cast is to a JComponent.
int mouseX = MouseInfo.getPointerInfo().getLocation().getX() - frame.getX() - frame.getRootPane().getX();
int mouseY = MouseInfo.getPointerInfo().getLocation().getY() - frame.getY() - frame.getRootPane().getY();
This gives the top right point within the border / tab of a frame
I'm developing a touch based windows 7 app using a tuio client-server setup and a touch library that extends multitouch 4 java.
One of the functionality I'm struggling with is to enable text highlighting when using touch.
I display a simple txt file using a JTextPane to display the text, the highlighting is done by through a drag action.
I get the clicked position where the drag event starts and then when it stops and tried to convert those coordinates to the text panel's space but I get different values from the ones that I should have, usually before the actual text.
The code I'm using to display the document is the following:
//Create the JDialog that is the container of it
window = new JDialog(parent);
window.setUndecorated(true);
//Create the JTextPane
text = new JTextPane();
text.setPage(newFile.toURI().toURL());
text.setEditable(false);
text.setHighlighter(null);
//ScrollPane that will be used to display the text
JScrollPane scroll = new JScrollPane(text);
scroll.setPreferredSize(new Dimension(500, 700));
window.getContentPane().add(scroll, BorderLayout.CENTER);
window.pack();
window.setVisible(true);
window.validate();
Where the JDialog parent is the main display component used in my app.
The drag is handled as follows:
#Override
public boolean processGestureEvent(GestureEvent ge) {
if((ge instanceof DragEvent) && this.component.isHighlight())
{
tapCount=0;
if(this.component.isHighlight())
{
//do highlighting
DragEvent drag = (DragEvent) ge;
switch (drag.getId()) {
case GestureEvent.GESTURE_STARTED:
Point start = drag.getFrom();
Point calcStart = new Point(start.x - compPosition.x, start.y - compPosition.y);
startPos = this.textDisplay.viewToModel(calcStart);
break;
case GestureEvent.GESTURE_ENDED:
Point end = drag.getTo();
Point calcEnd = new Point(end.x - compPosition.x, end.y - compPosition.y);
endPos = this.textDisplay.viewToModel(calcEnd);
System.out.println("I have this positions:" + startPos + "/" + endPos);
System.out.println("Should have " + this.textDisplay.getSelectionStart() + "/" + this.textDisplay.getSelectionEnd());
System.out.println("And the text is: " + this.textDisplay.getText().substring(startPos, endPos));
break;
case GestureEvent.GESTURE_CANCELED:
startPos = 0;
endPos = 0;
break;
}
}
return true;
}
In which the compPosition is the JDialog's position that holds the text pane. I'm simulating touch with the mouse so the correct text position for the highlighting I'm getting from the built-in highlighting functionality of the text pane with mouse.
Is the problem because of the JDialog and the JScroll pane that somehow skews the conversion?
The coordinate system for the point's I get from the touch are with the origin in the top left corner of the screen and the text pane's coordinate system origin is in the same top lef corner.
Any ideas on how can I solve the problem? Any suggestions are appreciated.
LE:
I was doing something wrong in that I was adding the gesture processor when I initialized the component and it's position was (0,0) and only afterwards I moved it where I wanted to.
I changed the position calculations as follows:
Point calcStart = new Point(start.x - this.component.getLocation().x, start.y -this.component.getLocation().y);
passing instead a reference to the actual component and getting the location when needed.
try instead of
Point calcStart = new Point(start.x - compPosition.x, start.y - compPosition.y);
to use
Point calcStart = new Point(start.x, start.y);
i wonder how it gonna end, so give us some value of what you get
Is there any way to actually see the selenium mouse when it's running the tests? Either with a windows cursor image or some kind of dot or cross hair or anything at all!
I'm trying to get a drag and drop function working with selenium and java in an HTML5 web app, and being able to see the cursor to see what it's actually doing would be really useful...
In the end I had to use the Java robot to get this working. Not only to see the mouse, but also because for an HTML5 Web App dragging and dropping is broken in selenium as two movements are needed to the drag and drop to register. Selenium only does one.
My method drags from the centre of each object and allows for an offset if you want to drag past the element you're dragging to.
public void dragAndDropElement(WebElement dragFrom, WebElement dragTo, int xOffset) throws Exception {
//Setup robot
Robot robot = new Robot();
robot.setAutoDelay(50);
//Fullscreen page so selenium coordinates are same as robot coordinates
robot.keyPress(KeyEvent.VK_F11);
Thread.sleep(2000);
//Get size of elements
Dimension fromSize = dragFrom.getSize();
Dimension toSize = dragTo.getSize();
//Get centre distance
int xCentreFrom = fromSize.width / 2;
int yCentreFrom = fromSize.height / 2;
int xCentreTo = toSize.width / 2;
int yCentreTo = toSize.height / 2;
//Get x and y of WebElement to drag to
Point toLocation = dragTo.getLocation();
Point fromLocation = dragFrom.getLocation();
//Make Mouse coordinate centre of element and account for offset
toLocation.x += xOffset + xCentreTo;
toLocation.y += yCentreTo;
fromLocation.x += xCentreFrom;
fromLocation.y += yCentreFrom;
//Move mouse to drag from location
robot.mouseMove(fromLocation.x, fromLocation.y);
//Click and drag
robot.mousePress(InputEvent.BUTTON1_MASK);
//Drag events require more than one movement to register
//Just appearing at destination doesn't work so move halfway first
robot.mouseMove(((toLocation.x - fromLocation.x) / 2) + fromLocation.x, ((toLocation.y - fromLocation.y) / 2) + fromLocation.y);
//Move to final position
robot.mouseMove(toLocation.x, toLocation.y);
//Drop
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
You can use Selenium "dragAndDrop" and "dragAndDropToObject" commands to drag and drop an element.
"mouseDown", "mouseMoveAt" and "mouseUp" commands are also very good alternatives.
Here is very good examples of both ways in selenium IDE. You can convert that code in to java to use.