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

Duplicate intstantiation of button skin within other skin

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 8u25
    • Fix Version/s: tbd
    • Component/s: javafx
    • Labels:
    • Environment:

      Windows7 JRE 1.8.0_u25

      Description

      We have an own control with an own skin class. Within the skin, several buttons are placed, which use an own button skin. The first of these button skins, which uses a graphics in addition to the button text, is instantiated two times:
      MyButtonSkin initialized for 1. Button with no graphics
      MyButtonSkin initialized for 2. Button with pane
      MyButtonSkin initialized for 3. Button with label
      MyButtonSkin initialized for 4. Button with pane
      MyButtonSkin initialized for 5. Button with label
      MyButtonSkin initialized for 2. Button with pane

      Run the appliction (sources below) as a minimal example for that behaviour. In our projects, the duplicate intstantiation leads to many problems. For instance, if the graphics of such button itself is a label, a NullPointerExcpetion occurrs:
      at com.sun.javafx.scene.control.skin.LabeledSkinBase.lambda$new$260(Unknown Source)
      at com.sun.javafx.scene.control.skin.LabeledSkinBase$$Lambda$134/1744049635.invalidated(Unknown Source)
      at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(Unknown Source)
      at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(Unknown Source)
      at javafx.scene.Node$LazyBoundsProperty.invalidate(Unknown Source)
      at javafx.scene.Node.impl_layoutBoundsChanged(Unknown Source)
      at javafx.scene.layout.Region.widthChanged(Unknown Source)
      at javafx.scene.layout.Region.access$1700(Unknown Source)
      at javafx.scene.layout.Region$6.invalidated(Unknown Source)
      at javafx.beans.property.DoublePropertyBase.markInvalid(Unknown Source)
      at javafx.beans.property.DoublePropertyBase.set(Unknown Source)
      at javafx.scene.layout.Region.setWidth(Unknown Source)
      at javafx.scene.layout.Region.resize(Unknown Source)
      at javafx.scene.Node.autosize(Unknown Source)
      at com.sun.javafx.scene.control.skin.LabeledSkinBase.layoutLabelInArea(Unknown Source)
      at com.sun.javafx.scene.control.skin.LabeledSkinBase.layoutLabelInArea(Unknown Source)
      at com.sun.javafx.scene.control.skin.LabeledSkinBase.layoutChildren(Unknown Source)
      at javafx.scene.control.Control.layoutChildren(Unknown Source)
      at javafx.scene.Parent.layout(Unknown Source)
      at javafx.scene.Parent.layout(Unknown Source)
      at javafx.scene.Parent.layout(Unknown Source)
      at javafx.scene.Group.prefWidth(Unknown Source)
      at javafx.scene.Scene.getPreferredWidth(Unknown Source)
      at javafx.scene.Scene.resizeRootToPreferredSize(Unknown Source)
      at javafx.scene.Scene.preferredSize(Unknown Source)
      at javafx.scene.Scene.impl_preferredSize(Unknown Source)
      at javafx.stage.Window$9.invalidated(Unknown Source)
      at javafx.beans.property.BooleanPropertyBase.markInvalid(Unknown Source)
      at javafx.beans.property.BooleanPropertyBase.set(Unknown Source)
      at javafx.stage.Window.setShowing(Unknown Source)
      at javafx.stage.Window.show(Unknown Source)
      at javafx.stage.Stage.show(Unknown Source)
      at buttonskin.TestApplication.start(TestApplication.java:21)
      ...

      ///////////////////// buttonskin/TestApplication.java:
      package buttonskin;
      import javafx.application.Application;
      import javafx.scene.Group;
      import javafx.scene.Scene;
      import javafx.stage.Stage;

      public class TestApplication extends Application {
          public static void main(final String[] args) {
              Application.launch(args);
          }

          @Override
          public void start(final Stage stage) throws Exception {
              final Group root = new Group();
              final Scene scene = new Scene(root);
              scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
              root.getChildren().add(new MyControl());
              stage.setScene(scene);
              stage.show();
          }
      }

      ///////////////////// buttonskin/MyControl.java:
      package buttonskin;
      import javafx.scene.control.Control;

      public class MyControl extends Control {
          public MyControl() {
              super();
              getStyleClass().add("my-control");
          }
      }

      ///////////////////// buttonskin/MyControlSkin.java:
      package buttonskin;
      import javafx.scene.control.Button;
      import javafx.scene.control.Label;
      import javafx.scene.control.SkinBase;
      import javafx.scene.layout.Pane;

      public class MyControlSkin extends SkinBase<MyControl> {
          public MyControlSkin(final MyControl control) {
              super(control);
              // The 1. button with no graphics has no effect:
              getChildren().add(new Button("1. Button with no graphics"));
              
              // The 2. button with a pane will be initialized 2 times:
              getChildren().add(new Button("2. Button with pane", new Pane()));

              // In case the 2. button is commented out and not added,
              // the 3. Button will be initialzed 2 times, leading to a NullPointerException
              // at com.sun.javafx.scene.control.skin.LabeledSkinBase.lambda$new$260(Unknown Source)
              getChildren().add(new Button("3. Button with label", new Label("Label")));
              getChildren().add(new Button("4. Button with pane", new Pane()));
              getChildren().add(new Button("5. Button with label", new Label("Label")));
          }
      }

      ///////////////////// buttonskin/MyButtonSkin.java:
      package buttonskin;
      import javafx.scene.control.Button;
      import com.sun.javafx.scene.control.skin.ButtonSkin;

      @SuppressWarnings("restriction")
      public class MyButtonSkin extends ButtonSkin {
          public MyButtonSkin(final Button button) {
              super(button);
              System.out.println("MyButtonSkin initialized for " + button.getText());
          }
      }

      ///////////////////// buttonskin/style.css:

      .button {
      -fx-skin: "buttonskin.MyButtonSkin";
      }

      .my-control {
      -fx-skin: "buttonskin.MyControlSkin";
      }




        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            jehrkejfx Jens Ehrke (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Dates

              Created:
              Updated:
              Imported: