2016-07-22 70 views
0

对于我的JavaFX GUI,我必须使用一些拆分窗格。但是会出现一个问题:当用户单击拆分窗格上的一个按钮时,我必须做到这一点,此拆分窗格隐藏了这些侧窗格中的一个,并且需要再次点击才能将此侧窗格重置为可见。在JavaFX上设置OneTouchExpandable按钮SplitPane

我在这里发现了另外一个像我这样的问题:Can we add OneTouchExpansable button on Javafx SplitPane like swing JSplitPane,但是除了“No you can not”之外,其他问题没有答案。

我希望有人对如何使这成为可能,或如何做出类似的任何想法。

谢谢大家!

+1

你可以尝试类似于James_D介绍[这里]的方法(http://stackoverflow.com/questions/38209981/value-into-slider-thumb-in-javafx)。你应该瞄准'水平抓取器'或'垂直抓取器'(或者两者都可以)。请参阅[CSS参考](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html#splitpane) – Itai

+0

嗡..问题是,一个'Divider' (在JavaFx'SplitPane'中分离窗格的东西)不会扩展'Pane'。但我认为有可能重写'SplitPane.Divider'和maky我自己的分频器。 **编辑:** Arf不可能......'SplitPane.Divider'有他所有的方法最后:'( – NatNgs

回答

1

我无法抗拒给这个尝试。这不是一个好的解决方案,因为它忽略了NodeOrientation,并且不支持可访问性(意味着除其他外,没有键盘控制)。另外,扩展按钮非常小,因此很难点击。

但至少是这样。也许有更多时间的人可以进一步改进。

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

哦,我的天啊,它很丑xD但是一个好主意!对于我的项目,我重新制作了一个MySplitPane '使用3个窗格,其中窗格的大小可以通过在MySplitPane的第二个窗格上拖放来改变;但是比你的解决方案更丑陋!(+1!我没有设置答案现在解决了,我会再等一会儿;如果没有更好的答案出现,我会接受你的答案作为答案:P) – NatNgs

相关问题