Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8284878

Panning Buttons in a ScrollPane does not work

XMLWordPrintable

    • generic
    • generic

      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


        1. ButtonPanning.java
          2 kB
          Praveen Narayanaswamy

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: