A DESCRIPTION OF THE PROBLEM :
Button is not pannable in a ScrollPane. To hack/fix that in Java 8 it was enough to call ButtonSkin#consumeMouseEvents(false).
With Java 8+ this is not enough anymore. The ButtonBehavior registers a default mapping for MouseEvent.MOUSE_PRESSED. This mapping consumes the event and the ScrollPane does not receive it anymore for panning calculation. So for 8+ you also need to redirect the MOUSE_PRESSED event to the viewRect of the ScrollPane as a workaround.
I provided code where the test variable can be toggled to enable/disable the workaround.
---------- BEGIN SOURCE ----------
package com.bizerba.gtsc.sirius.menu.view;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Skin;
import javafx.scene.control.skin.ButtonSkin;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ButtonPanning extends Application
{
private Node viewPort;
private MouseEvent lastFiredEvent;
public static void main(String[] args)
{
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception
{
boolean fix = true;
primaryStage.setTitle("Hello World!");
VBox box = new VBox();
addBtns(box, 30, fix);
ScrollPane pane = new ScrollPane(box)
{
@Override
protected Skin<?> createDefaultSkin()
{
Skin<?> skin = super.createDefaultSkin();
for (Node ch : getChildren())
{
if (ch.getStyleClass().contains("viewport"))
{
viewPort = ch;
break;
}
}
return skin;
}
};
pane.addEventFilter(MouseEvent.MOUSE_PRESSED, e ->
{
if (fix && lastFiredEvent != e)
{
lastFiredEvent = e.copyFor(e.getSource(), viewPort);
viewPort.fireEvent(lastFiredEvent); //This fix is needed for JAVA >8
}
});
pane.setPannable(true);
primaryStage.setScene(new Scene(pane, 300, 250));
primaryStage.show();
}
private void addBtns(VBox box, int count, boolean fix)
{
for (int i = 0; i < count; i++)
{
box.getChildren().add(new Button("" + (i + 1))
{
@Override
protected Skin<?> createDefaultSkin()
{
return new FixedButtonSkin(this, fix);
}
});
}
}
class FixedButtonSkin extends ButtonSkin
{
public FixedButtonSkin(Button control, boolean fix)
{
super(control);
if (fix)
consumeMouseEvents(false);//this fix alone was enough for JAVA 8
}
}
}
---------- END SOURCE ----------
FREQUENCY : always
Button is not pannable in a ScrollPane. To hack/fix that in Java 8 it was enough to call ButtonSkin#consumeMouseEvents(false).
With Java 8+ this is not enough anymore. The ButtonBehavior registers a default mapping for MouseEvent.MOUSE_PRESSED. This mapping consumes the event and the ScrollPane does not receive it anymore for panning calculation. So for 8+ you also need to redirect the MOUSE_PRESSED event to the viewRect of the ScrollPane as a workaround.
I provided code where the test variable can be toggled to enable/disable the workaround.
---------- BEGIN SOURCE ----------
package com.bizerba.gtsc.sirius.menu.view;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Skin;
import javafx.scene.control.skin.ButtonSkin;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ButtonPanning extends Application
{
private Node viewPort;
private MouseEvent lastFiredEvent;
public static void main(String[] args)
{
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception
{
boolean fix = true;
primaryStage.setTitle("Hello World!");
VBox box = new VBox();
addBtns(box, 30, fix);
ScrollPane pane = new ScrollPane(box)
{
@Override
protected Skin<?> createDefaultSkin()
{
Skin<?> skin = super.createDefaultSkin();
for (Node ch : getChildren())
{
if (ch.getStyleClass().contains("viewport"))
{
viewPort = ch;
break;
}
}
return skin;
}
};
pane.addEventFilter(MouseEvent.MOUSE_PRESSED, e ->
{
if (fix && lastFiredEvent != e)
{
lastFiredEvent = e.copyFor(e.getSource(), viewPort);
viewPort.fireEvent(lastFiredEvent); //This fix is needed for JAVA >8
}
});
pane.setPannable(true);
primaryStage.setScene(new Scene(pane, 300, 250));
primaryStage.show();
}
private void addBtns(VBox box, int count, boolean fix)
{
for (int i = 0; i < count; i++)
{
box.getChildren().add(new Button("" + (i + 1))
{
@Override
protected Skin<?> createDefaultSkin()
{
return new FixedButtonSkin(this, fix);
}
});
}
}
class FixedButtonSkin extends ButtonSkin
{
public FixedButtonSkin(Button control, boolean fix)
{
super(control);
if (fix)
consumeMouseEvents(false);//this fix alone was enough for JAVA 8
}
}
}
---------- END SOURCE ----------
FREQUENCY : always