Pilling two obj with OnMousePressed on top of each other in javafx - java

Been trying around and searching but couldn't find any solution, so I finally decided to give up and ask further...
Creating a javafx app, I load tiles in a TilePane.
This tiles are clickable and lead to a details page of their respective content.
On each tile, if they do belong to a certain pack, I do display the pack name, that is also clickable and lead to a page showing that specific pack content.
So that means the container, the tile, that is a Pane is clickable and on top of it I have a Label that is claickable also. What happens is when I do click the Label, it also triggers the Pane onMousePressed()... Here is a part of the tile creation code, the part focused on the onMousePressed(). I tried to make the Pane react by double click and the Label by single, it works, but I want to Pane to open with a single click.
I would be more than thankfull for any ideas how to solve that.
public DownloadTile (Downloadable upload, MainApp mainApp) {
_mainApp = mainApp;
_upload = upload;
_tile = new Pane();
_tile.setPrefHeight(100);
_tile.setPrefWidth(296);
_tile.setStyle("-fx-background-color: #ffffff;");
_tile.setCursor(Cursor.HAND);
}
public void refresh() {
_tile.getChildren().clear();
_tile.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.isPrimaryButtonDown() /*&& event.getClickCount() == 2*/) {
_mainApp.showDownloadDialog(dt, _upload);
}
}
});
if (_upload.getPack() != null) {
Label pack = new Label();
pack.setText(_upload.getPack());
pack.getStyleClass().add("pack-link");
pack.setCursor(Cursor.HAND);
pack.relocate(10, 48);
_tile.getChildren().add(pack);
pack.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.isPrimaryButtonDown()) {
_mainApp.showPackPage(_upload);
}
}
});
}
}

Your label will receive the mouseclick first (since it's on top), so after you have processed the click, you can stop it from being passed down the chain using 'consume':
pane.setOnMouseClicked(
(Event event) -> {
// process your click here
System.out.println("Panel clicked");
pane.requestFocus();
event.consume();
};

Related

Javafx- Mouse click event that undoes what the previous mouse click did

So I currently have a 3x3 gridpane of which I add a pane with a white background to each space on the grid.
What I am trying to do is have it so that if a user clicks on one of these spaces, the white pane will change to another color. Then if the user were to click on the space again, the pane would change back to white. If clicked again, then it would change to that color again, and so on.
In short, a click would cause an action, and the next click, and those after it would reverse/undo the previous action.
However, I can only get the initial click to work with this. Everything else I've thought to add to this hasn't worked.
#Override
public void handle(MouseEvent me) {
if (me.getClickCount() == 1) {
pane.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));}
Any help would be really appreciated!
If it really has to be a Pane, you could try to write a custom Pane which will make it easier for you to control its behaviour:
class MyPane extends Pane{
private Background standard, other;
public MyPane(){
standard = new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY));
other = new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY));
this.setBackground(standard);
}
public void changeColor(){
if(this.getBackground().equals(standard){
this.setBackground(other);
else{
this.setBackground(standard);
}
}
public void setBackground(Background bckgrnd){
this.other = bckgrnd;
}
If you use this class instead of a standard Pane, you are able to control the color changing simply via
#Override
public void handle(MouseEvent me){
myPane.changeColor();
}
If you would use the Rectangleclass, you could use the following code:
#Override
public void handle(MouseEvent me){
if(rectangle.getFill() == standard){
rectangle.setFill(other);
}else{
rectangle.setFill(standard);
}
provided that you defined the 2 Paint variables standard and other, e.g. :
private final Paint standard = Color.WHITE;
private Paint other = Color.RED;
see Color

Smooth Panning in ScrollPane Javafx

I have a scrollPane with pannable enabled. When panning with a large image the transformation "lags" behind the mouse making for a "blocky" transformation. Is there a way to fix this? There is not much code that is really relevant here to post if you need more specifics just ask.
I realize this is an old post, but others might need help in this area. What I did to solve this problem is to create a Transition object, and under the interpolate function, set the ScrollPane vValue or hValue equal to itself plus 0.001 depending on how fast you want to pan. vValue and hValue are the viewing locations on the ScrollPane, so basically you're just slowly incrementing what your viewing, so it looks like panning but its not. Here's an example from a project I'm working on where you can "pan" down or up with KeyEvents.
#FXML
ScrollPane scroll;
private Transition down;
private Transition up;
public void initialize(){
this.down = new Transition() {
{
setCycleDuration(Duration.INDEFINITE);
}
#Override
protected void interpolate(double v) {
scroll.setVvalue(scroll.getVvalue()+0.001);
}
};
this.up = new Transition() {
{
setCycleDuration(Duration.INDEFINITE);
}
#Override
protected void interpolate(double v) {
scroll.setVvalue(scroll.getVvalue()-0.001);
}
};
}
#FXML
private void handleKeyPress(KeyEvent event){
if(event.getCode() == KeyCode.S){
down.play();
}
if(event.getCode() == KeyCode.W){
up.play();
}
}
#FXML
private void handleKeyRelease(){
this.down.stop();
this.up.stop();
}

JavaFx multiple click events

I am creating a simple programme in javafx.
private void onClick(final Circle circle) {
circle.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
circle.setTranslateX(150.);
}
});
}
in the "public void start" i match th created circle with the method "onClick"
onClick(circle1);
this code move a circle to the right. How can I move it multiple times? I tried to create more methods analogically "onClick1" but it always respond just to the first click. I need to move it to the right with each click again.
Thank you for your time.
What about
circle.setTranslateX(circle.getTranslateX() + 150.0);

Add touch gestures to legacy swing application

I have a legacy swing application that I need to add touch gestures to,specifically pinch to zoom and touch and drag.
I tried the SwingNode of JDK 8 and I can run the swing application there, but the display performance was cut by more than 50% which won't work. SwingTextureRenderer in MT4J has the same issue and that is without even trying to redispatch touch events as mouse events.
I thought about a glass pane approach using a JavaFX layer on top and capturing the touch events and attempting to dispatch them as mouse events to the Swing app underneath.
Does anyone have an alternative approach? The target platform is windows 8.
Bounty coming as soon as Stackoverflow opens it up. I need this one pretty rapidly.
EDIT:
Here is what I tried with SwingNode (the mouse redispatch didn't work). The SwingNode stuff might be a distraction from the best solution so ignore this if you have a better idea for getting touch into swing:
#Override
public void start(Stage stage) {
final SwingNode swingNode = new SwingNode();
createAndSetSwingContent(swingNode);
StackPane pane = new StackPane();
pane.getChildren().add(swingNode);
stage.setScene(new Scene(pane, 640, 480));
stage.show();
}
private void createAndSetSwingContent(final SwingNode swingNode) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
UILib.setPlatformLookAndFeel();
// create GraphViewTouch
String datafile = null;
String label = "label";
final JPanel frame = GraphView.demoFrameless(datafile, label);
swingNode.setContent(frame);
swingNode.setOnZoom(new EventHandler<ZoomEvent>() {
#Override public void handle(ZoomEvent event) {
MouseWheelEvent me = new MouseWheelEvent(frame, 1, System.currentTimeMillis(), 0, (int)Math.round(event.getSceneX()), (int)Math.round(event.getSceneY()), (int)Math.round(event.getScreenX()), (int)Math.round(event.getScreenY()), (int)Math.round(event.getZoomFactor()), false, MouseWheelEvent.WHEEL_UNIT_SCROLL, (int)Math.round(event.getZoomFactor()), (int)Math.round(event.getZoomFactor()), event.getZoomFactor());
frame.dispatchEvent(me);
System.out.println("GraphView: Zoom event" +
", inertia: " + event.isInertia() +
", direct: " + event.isDirect());
event.consume();
}
});
}
});
}
You can use JNA to parse the messages from Windows.
Some documentation on the multi touch events from Microsoft:
https://learn.microsoft.com/en-us/windows/desktop/wintouch/wm-touchdown
Some documentation on how to do it in Java and sample code:
https://github.com/fmsbeekmans/jest/wiki/Native-Multitouch-for-AWT-component-(Windows)
hmm... this is a tough one, but there is a chance.
What I would do is make multiple MouseListener classes (relative to the number of mouse events you want to pick up), and than create some sort of system to detect certain adjustments, eg. (zoom)
1st listener:
public void mousePressed(MouseEvent e){
//Set click to true
clk = true;
//set first mouse position
firstPos = window.getMousePosition();
}
public void mouseReleased(MouseEvent e){
//set second mouse position
secondPos = window.getMousePosition();
}
Second Listener
public void mousePressed(MouseEvent e){
//set clicked to true
clk = true;
//set first mouse position (listener 2)
firstPos = window.getMousePosition();
}
public void mouseReleased(MouseEvent e){
//set second mouse position
secondPos = window.getMousePosition();
}
Main handler
if(Listener1.get1stMousePos() < Listener1.get2ndMousePos() && Listener2.get1stMousePos() < Listener2.get2ndMousePos() && Listener1.clk && Listener2.clk){
zoomMethod((Listener1.get1stMousePos - Listener1.get2ndMousePos()) + (Listener1.get1stListener2.get2ndMousePos());
}
And than just do this to add it to the window:
window.addMouseListener(Listener1);
window.addMouseListener(Listener2);
Hope you find a way.
For the pinch-to-zoom:
Try the GestureMagnificationListener by guigarage.com. It provides a method:
public void magnify(GestureMagnificationEvent me){...}

Using Smart GWT TreeGrid for Navigation

I'm working on a SmartGWT project where I'd like my main navigation to be done via a treegrid. The treegrid renders proprerly and its DataSource is functioning appropriately as well. The treegrid is correctly situated to the left of the mainView Canvas.
What I can't seem to figure out is how to switch the contents of the mainView Canvas based on what is selected in the NavigationTree. I've mimicked the functionality I'd like by adding new windows to the existing Canvas, but I can't find an example demonstrating how to clear the canvas entirely and replace it with a new Window.
Am I on the right track here? Can anyone point me at an example that shows roughly what I'm trying to accomplish?
public class NavigationTree extends TreeGrid {
public NavigationTree(Canvas mainView)
{
setDataSource(NavigationDataSource.getInstance());
setAutoFetchData(true);
setShowHeader(false);
addNodeClickHandler(new NavClickHandler(mainView));
}
// Handler for clicking an item on the Navigation Tree.
private class NavClickHandler implements NodeClickHandler
{
private Canvas mainView;
public NavClickHandler(Canvas mainView)
{
super();
this.mainView = mainView;
}
#Override
public void onNodeClick(NodeClickEvent event)
{
Window window = new Window();
window.setWidth(300);
window.setHeight(230);
window.setCanDragReposition(true);
window.setCanDragResize(true);
window.setTitle(event.getNode().getAttribute("name"));
window.addItem(new Label("huzzah!"));
window.setParentElement(mainView);
window.redraw();
}
}
}
You can keep the mainView canvas, clear its children (if any is set) and then set the newly created window as its new child. Something like the following as the body of your click handler:
Window window = new Window();
window.setWidth(300);
window.setHeight(230);
window.setCanDragReposition(true);
window.setCanDragResize(true);
window.setTitle(event.getNode().getAttribute("name"));
window.addItem(new Label("huzzah!"));
for (Canvas child: mainView.getChildren()) {
mainView.removeChild(child);
}
mainView.addChild(window);
I managed to accomplish what I needed with the following change to the event handler code:
public NavClickHandler(UI ui) //UI extends HLayout
{
this.ui = ui;
}
#Override
public void onNodeClick(NodeClickEvent event) {
Window window = new Window();
window.setWidth100();
window.setHeight100();
window.setHeaderControls(HeaderControls.HEADER_LABEL);
window.setTitle(event.getNode().getAttribute("name"));
window.addItem(new Label("Huzzah!"));
ui.setMainView(window);
}
...and the following change to my main UI layout:
public void setMainView(Canvas canvas)
{
mainView.destroy();
mainView = canvas;
addMember(mainView);
this.redraw();
}

Categories