Last active
March 16, 2020 14:39
-
-
Save tserber98/4b8e30b788dfb8564d1b6e1362dbfbb2 to your computer and use it in GitHub Desktop.
Slider Pane implementation for JavaFX.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.animation.*; | |
import javafx.beans.property.*; | |
import javafx.scene.Node; | |
import javafx.scene.layout.Pane; | |
import javafx.util.Duration; | |
public class SliderPane extends Pane{ | |
public SliderPane(){ | |
} | |
public SliderPane(Node... children){ | |
super(children); | |
} | |
private final IntegerProperty openedIndex = new SimpleIntegerProperty(0); | |
{ | |
openedIndex.addListener((obs, o, n) -> openedIndexChanged(o.intValue(), n.intValue())); | |
} | |
public final int getOpenedIndex(){ | |
return openedIndex.get(); | |
} | |
public final IntegerProperty openedIndexProperty(){ | |
return openedIndex; | |
} | |
public final void setOpenedIndex(int openedIndex){ | |
this.openedIndex.set(openedIndex); | |
} | |
private final BooleanProperty animated = new SimpleBooleanProperty(false); | |
public final boolean isAnimated(){ | |
return animated.get(); | |
} | |
public final BooleanProperty animatedProperty(){ | |
return animated; | |
} | |
public final void setAnimated(boolean animated){ | |
this.animated.set(animated); | |
} | |
private final IntegerProperty animationTime = new SimpleIntegerProperty(1000); | |
public final int getAnimationTime(){ | |
return animationTime.get(); | |
} | |
public final IntegerProperty animationTimeProperty(){ | |
return animationTime; | |
} | |
public final void setAnimationTime(int animationTime){ | |
this.animationTime.set(animationTime); | |
} | |
private final ReadOnlyBooleanWrapper animating = new ReadOnlyBooleanWrapper(false); | |
public final boolean isAnimating(){ | |
return animating.get(); | |
} | |
public final ReadOnlyBooleanProperty animatingProperty(){ | |
return animating.getReadOnlyProperty(); | |
} | |
private double offsetIndex; | |
private Timeline timeline; | |
private void openedIndexChanged(int oldIndex, int newIndex){ | |
if(isAnimated()){ | |
if(timeline != null){ | |
timeline.stop(); | |
} | |
DoubleProperty percentProperty = new SimpleDoubleProperty(0); | |
timeline = new Timeline(new KeyFrame(Duration.millis(getAnimationTime()), new KeyValue(percentProperty, 1.0))); | |
timeline.statusProperty().addListener((obs, o, n) -> { | |
animating.set(n == Animation.Status.RUNNING); | |
}); | |
percentProperty.addListener((obs, o, n) -> { | |
if(isAnimated()){ | |
offsetIndex = Interpolator.EASE_OUT.interpolate((double)oldIndex, newIndex, n.doubleValue()); | |
} | |
else{ | |
timeline.stop(); | |
offsetIndex = newIndex; | |
} | |
requestLayout(); | |
}); | |
timeline.play(); | |
} | |
else{ | |
offsetIndex = newIndex; | |
layoutChildren(); | |
} | |
} | |
@Override | |
protected void layoutChildren(){ | |
super.layoutChildren(); | |
double width = getWidth(); | |
double height = getHeight(); | |
int i = 0; | |
for(Node node : getManagedChildren()){ | |
node.resizeRelocate((width * i++) - (offsetIndex * width), 0, width, height); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.application.Application; | |
import javafx.collections.FXCollections; | |
import javafx.geometry.Insets; | |
import javafx.geometry.Pos; | |
import javafx.scene.Scene; | |
import javafx.scene.control.Button; | |
import javafx.scene.control.ListView; | |
import javafx.scene.control.TextField; | |
import javafx.scene.layout.HBox; | |
import javafx.scene.layout.Priority; | |
import javafx.scene.layout.VBox; | |
import javafx.stage.Stage; | |
public class SliderPaneUsage extends Application{ | |
private static final int PROJECT_LIST_INDEX = 0; | |
private static final int CREATE_PROJECT_INDEX = 1; | |
private SliderPane root; | |
@Override | |
public void start(Stage stage) throws Exception{ | |
final ListView<String> projectsList = new ListView<>(FXCollections.observableArrayList("Project 1", "Project 2", "Project 3")); | |
final HBox controlsWrapper; | |
{ | |
final Button createProjectButton = new Button("Create project"); | |
createProjectButton.setOnAction((e) -> root.setOpenedIndex(CREATE_PROJECT_INDEX)); | |
controlsWrapper = new HBox(createProjectButton); | |
controlsWrapper.setPadding(new Insets(4)); | |
} | |
VBox projectListWrapper = new VBox(projectsList, controlsWrapper); | |
VBox.setVgrow(projectsList, Priority.ALWAYS); | |
final VBox createProjectWrapper; | |
{ | |
final TextField projectNameField = new TextField(); | |
projectNameField.setPromptText("Project name"); | |
final Button cancelButton = new Button("Cancel"); | |
cancelButton.setOnAction((e) -> root.setOpenedIndex(PROJECT_LIST_INDEX)); | |
final Button createButton = new Button("Create"); | |
createButton.setOnAction((e) -> { | |
projectsList.getItems().add(projectNameField.getText()); | |
root.setOpenedIndex(PROJECT_LIST_INDEX); | |
}); | |
VBox fieldsWrapper = new VBox(projectNameField); | |
VBox.setVgrow(fieldsWrapper, Priority.ALWAYS); | |
final HBox buttonsWrapper = new HBox(cancelButton, createButton); | |
buttonsWrapper.setSpacing(4); | |
buttonsWrapper.setAlignment(Pos.CENTER_RIGHT); | |
createProjectWrapper = new VBox(fieldsWrapper, buttonsWrapper); | |
} | |
root = new SliderPane(projectListWrapper, createProjectWrapper); | |
root.setAnimated(true); | |
root.setAnimationTime(500); | |
root.getChildren().forEach((node) -> node.disableProperty().bind(root.animatingProperty())); | |
stage.setScene(new Scene(root, 640, 480)); | |
stage.show(); | |
} | |
public static void main(String[] args){ | |
launch(args); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment