2016-07-22 3 views
0

Für meine JavaFX-GUI muss ich einige geteilte Fensterbereiche verwenden. Aber ein Problem tritt auf: Ich muss machen, wenn der Benutzer auf eine Schaltfläche im geteilten Bereich klickt, dieses geteilte Fenster einen dieser Seitenbereiche ausblenden und einen weiteren Klick benötigen, um diesen Seitenbereich als sichtbar zurückzusetzen.Einrichten der OneTouchExpandable-Schaltfläche auf JavaFX SplitPane

Ich habe eine andere Frage wie mich hier gefunden: Can we add OneTouchExpansable button on Javafx SplitPane like swing JSplitPane, aber alt und keine andere Antwort als "Nein, du kannst nicht".

Ich hoffe, dass jemand eine Idee hat, wie man das möglich macht, oder wie man etwas Ähnliches macht.

Danke euch allen!

+1

Sie könnten einen Ansatz versuchen, ähnlich wie James_D beschreibt [hier] (http://stackoverflow.com/questions/38209981/value-into-slider-thumb-in-javafx). Sie sollten wahrscheinlich entweder horizontal-Grabber oder vertikal-Grabber (oder beide?). Siehe [CSS Referenz] (https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html#splitpane) – Itai

+0

Hum .. das Problem ist, dass ein 'Divider' (die Sache, die Bereiche in JavaFx 'SplitPane' trennen) erweitert' Pane' nicht. Aber ich denke, es gibt eine Möglichkeit, 'SplitPane.Divider' zu überschreiben und meinen eigenen Teiler zu erstellen. ** EDIT: ** Arf unmöglich ... 'SplitPane.Divider' hat alle seine Methoden final: '( – NatNgs

Antwort

1

Ich konnte nicht widerstehen, dies zu versuchen. Dies ist keine gute Lösung, da es NodeOrientation ignoriert und die Barrierefreiheit nicht unterstützt (dh unter anderem keine Tastatursteuerung). Außerdem sind die Erweiterungstasten irritierend klein, was es schwierig macht, darauf zu klicken.

Aber es ist zumindest etwas. Vielleicht kann jemand mit mehr Zeit es weiter verbessern.

import java.util.Collection; 
import java.util.Objects; 

import javafx.application.Application; 
import javafx.application.Platform; 

import javafx.beans.binding.Bindings; 
import javafx.beans.binding.DoubleBinding; 
import javafx.beans.binding.DoubleExpression; 

import javafx.geometry.Insets; 
import javafx.geometry.Orientation; 
import javafx.geometry.Pos; 

import javafx.scene.Cursor; 
import javafx.scene.Group; 
import javafx.scene.Node; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.SplitPane; 
import javafx.scene.effect.ColorAdjust; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.StackPane; 
import javafx.scene.shape.Polygon; 

import javafx.stage.Stage; 

public class OneTouchExpandable 
extends Application { 

    /** 
    * Node properties key whose value is the saved divider position 
    * just before user's one-touch-expand action is executed. 
    */ 
    private static final Object ORIGINAL_POSITION = 
     OneTouchExpandable.class.getName() + ".originalPosition"; 

    /** 
    * Percentage of divider thickness which one-touch button takes up, 
    * as a value from 0.0 to 1.0. 
    */ 
    private static final double ARROW_THICKNESS = 0.60; 

    /** 
    * Delta for comparing divider position (a double) with the min and max 
    * divider values, which in practice do not reach 0.0 or 1.0. 
    */ 
    private static final double END_TOLERANCE = 0.01; 

    /** 
    * Adds one-touch-expand buttons to a SplitPane's first divider. 
    */ 
    public static void addOneTouchExpansion(SplitPane pane) { 

     StackPane divider = (StackPane) pane.lookup(".split-pane-divider"); 
     Objects.requireNonNull(divider, "SplitPane's divider not present!" 
      + " (you probably need to call this method from within" 
      + " Platform.runLater)"); 

     DoubleBinding dividerPosition = Bindings.selectDouble(
      Bindings.valueAt(pane.getDividers(), 0), "position"); 

     Button colorSource = new Button(); 
     ColorAdjust disabledColor = new ColorAdjust(0, 0, 0.5, 0); 

     BorderPane expander = new BorderPane(); 
     if (pane.getOrientation() == Orientation.VERTICAL) { 
      DoubleExpression scale = 
       divider.heightProperty().multiply(ARROW_THICKNESS); 
      DoubleExpression indent = 
       divider.heightProperty().multiply((1 - ARROW_THICKNESS)/2); 

      Polygon upArrow = new Polygon(1, 0, 0, 1, 2, 1); 
      upArrow.setCursor(Cursor.DEFAULT); 
      upArrow.fillProperty().bind(colorSource.textFillProperty()); 
      upArrow.scaleXProperty().bind(scale); 
      upArrow.scaleYProperty().bind(scale); 
      upArrow.disableProperty().bind(
       dividerPosition.isEqualTo(0, END_TOLERANCE)); 
      upArrow.effectProperty().bind(
       Bindings.when(upArrow.disabledProperty()) 
        .then(disabledColor).otherwise((ColorAdjust) null)); 
      upArrow.setOnMouseClicked(e -> setDividerPosition(pane, 0)); 

      Polygon downArrow = new Polygon(1, 1, 0, 0, 2, 0); 
      downArrow.setCursor(Cursor.DEFAULT); 
      downArrow.fillProperty().bind(colorSource.textFillProperty()); 
      downArrow.scaleXProperty().bind(scale); 
      downArrow.scaleYProperty().bind(scale); 
      downArrow.translateXProperty().bind(scale.multiply(2).add(3)); 
      downArrow.disableProperty().bind(
       dividerPosition.isEqualTo(1, END_TOLERANCE)); 
      downArrow.effectProperty().bind(
       Bindings.when(downArrow.disabledProperty()) 
        .then(disabledColor).otherwise((ColorAdjust) null)); 
      downArrow.setOnMouseClicked(e -> setDividerPosition(pane, 1)); 

      Group expandButtonsPane = new Group(upArrow, downArrow); 
      expandButtonsPane.translateYProperty().bind(indent); 

      expander.setLeft(expandButtonsPane); 
     } else { 
      DoubleExpression scale = 
       divider.widthProperty().multiply(ARROW_THICKNESS); 
      DoubleExpression indent = 
       divider.widthProperty().multiply((1 - ARROW_THICKNESS)/2); 

      Polygon leftArrow = new Polygon(0, 1, 1, 0, 1, 2); 
      leftArrow.setCursor(Cursor.DEFAULT); 
      leftArrow.fillProperty().bind(colorSource.textFillProperty()); 
      leftArrow.scaleXProperty().bind(scale); 
      leftArrow.scaleYProperty().bind(scale); 
      leftArrow.disableProperty().bind(
       dividerPosition.isEqualTo(0, END_TOLERANCE)); 
      leftArrow.effectProperty().bind(
       Bindings.when(leftArrow.disabledProperty()) 
        .then(disabledColor).otherwise((ColorAdjust) null)); 
      leftArrow.setOnMouseClicked(e -> setDividerPosition(pane, 0)); 

      Polygon rightArrow = new Polygon(1, 1, 0, 0, 0, 2); 
      rightArrow.setCursor(Cursor.DEFAULT); 
      rightArrow.fillProperty().bind(colorSource.textFillProperty()); 
      rightArrow.scaleXProperty().bind(scale); 
      rightArrow.scaleYProperty().bind(scale); 
      rightArrow.translateYProperty().bind(scale.multiply(2).add(3)); 
      rightArrow.disableProperty().bind(
       dividerPosition.isEqualTo(1, END_TOLERANCE)); 
      rightArrow.effectProperty().bind(
       Bindings.when(rightArrow.disabledProperty()) 
        .then(disabledColor).otherwise((ColorAdjust) null)); 
      rightArrow.setOnMouseClicked(e -> setDividerPosition(pane, 1)); 

      Group expandButtonsPane = new Group(leftArrow, rightArrow); 
      expandButtonsPane.translateXProperty().bind(indent); 

      expander.setTop(expandButtonsPane); 
     } 

     divider.getChildren().add(expander); 
    } 

    /** 
    * Checks whether double values are nearly equal. 
    */ 
    private static boolean isNearly(double value, 
            double target) { 
     return (Math.abs(target - value) < END_TOLERANCE); 
    } 

    /** 
    * Executes a one-touch expansion/contraction. 
    * 
    * @param pane SplitPane to perform expansion on 
    * @param end farthest divider position in direction of expansion, 
    *   either 0 or 1 
    */ 
    private static void setDividerPosition(SplitPane pane, 
              double end) { 
     double oldPosition = pane.getDividers().get(0).getPosition(); 
     double start = 1 - end; 
     if (isNearly(oldPosition, start)) { 
      Object savedPosition = pane.getProperties().get(ORIGINAL_POSITION); 
      if (savedPosition instanceof Number) { 
       pane.setDividerPosition(0, 
        ((Number) savedPosition).doubleValue()); 
      } else { 
       pane.setDividerPosition(0, 0.5); 
      } 
     } else if (!isNearly(oldPosition, end)) { 
      pane.getProperties().put(ORIGINAL_POSITION, oldPosition); 
      pane.setDividerPosition(0, end); 
     } 
    } 

    /** 
    * Displays test window. Invoke application with 'vertical' as first 
    * command-line argument to use a vertical SplitPane. 
    */ 
    @Override 
    public void start(Stage stage) { 
     Node child1 = createChild("Child 1"); 
     Node child2 = createChild("Child 2"); 

     SplitPane pane = new SplitPane(child1, child2); 

     Collection<String> params = getParameters().getUnnamed(); 
     if (params.stream().anyMatch(s -> s.matches("[Vv].*"))) { 
      pane.setOrientation(Orientation.VERTICAL); 
     } 

     Platform.runLater(() -> addOneTouchExpansion(pane)); 

     stage.setTitle("One-Touch Expandable Demo"); 
     stage.setScene(new Scene(pane)); 
     stage.show(); 
    } 

    /** 
    * Creates a SplitPane child for test window. 
    * 
    * @param text text to show in node 
    */ 
    private static Node createChild(String text) { 
     Label label = new Label(text); 
     label.setAlignment(Pos.CENTER); 

     label.setMinWidth(0); 
     label.setMinHeight(0); 
     label.setMaxWidth(10000); 
     label.setMaxHeight(10000); 

     Label sizer = new Label(text); 
     sizer.setVisible(false); 
     sizer.setPadding(new Insets(100)); 

     sizer.setMinWidth(0); 
     sizer.setMinHeight(0); 
     sizer.setMaxWidth(10000); 
     sizer.setMaxHeight(10000); 

     StackPane pane = new StackPane(label, sizer); 

     return pane; 
    } 
} 
+0

Oh mein Gott, es ist hässlich xD Aber eine gute Idee! Für mein Projekt habe ich ein' MySplitPane 'neu gemacht 'Verwenden von 3 Bereichen, wo die Größe der Fensterscheiben mit Drag & Drop auf der zweiten Scheibe der' MySplitPane' geändert werden kann, ist aber hässlicher als Ihre Lösung! (+1! Ich setze die Antwort für jetzt nicht als gelöst, ich werde warte ein bisschen mehr Zeit und wenn keine bessere Antwort erscheint, werde ich deine Antwort als DIE Antwort akzeptieren: P) – NatNgs