# JavaFX Slider soll Value erst ab einer bestimmten Bedinung aendern



## patrick-89 (31. Mai 2016)

Hallo zusammen,

kurz zur Info. Ich bin gerade dabei mir eine GUI fuer meinen Equalizer zu erstellen. Das ganze laeuft auf einem Touchdisplay.

Ich verwende die normalen Sliders von FX.
Zu meinem Problem:

Ich moechte eine Art Selektierung fuer die Sliders erstellen. Das ganze soll so funktionieren, das man auf einen Slider klickt damit dieser dann Selektiert ist. Wenn dieser dann selektiert ist, dann ich ihn ueber 2 Buttons incrementieren oder decrementieren. Leider habe ich das Problem, das wenn ich auf den Slider klicke, das sich dann auch schon die Value aendert bzw. sich der Thumb schon verschiebt. Natuerlich sollte man den Slider auch mit dem Finger verschieben koennen aber erst nach sagen wir mal 500ms fuer den Anfang. Vorher sollte sich die Value nicht aendern.
Grund ist, dann ich mit den Button sehr viel genauer die Value einstellen kann als mit meinem Finger 

Ich habe schon einiges ausprobiert mit verschiedenen Listenern, nur hat das alles leider nix gebracht -.-...

Ich hoffe das Ihr mir weiterhelfen koennt!!!!

Besten Dank.

Gruss
Patrick


----------



## Cromewell (1. Jun 2016)

Mach doch einfach eine If-Bedingung in den Listener vom Slider, sodass er sich erst verschiebt, sobald er an einer bestimmten Position ist. Und beim Button halt pro drücken die Position erhöhen/senken.


----------



## patrick-89 (1. Jun 2016)

Danke für deine Antwort. 

Welchen Listerner soll ich denn da nehmen?


----------



## Cromewell (1. Jun 2016)

http://docs.oracle.com/javafx/2/ui_controls/slider.htm
Etwas runterscrollen (ChangeListener)


----------



## Cromewell (1. Jun 2016)

```
slider.valueProperty().addListener(new ChangeListener<Number>() {
    public void changed(ObservableValue<? extends Number> ov,
        Number old_val, Number new_val) {
            if(slider. ... >= ...){
                //code
            }
    }
});
```
Also ca. so


----------



## patrick-89 (1. Jun 2016)

Ja das habe ich auch schon versucht, nur geht das nicht...

Das ChangeEvent besagt ja das sich die Value geaendert hat. Da ist das also schon passiert. Dort kann man dann den neuen Wert nicht mehr auf den alten Wert setzen...

slider.valueProperty().addListener(new ChangeListener<Number>() {
    public void changed(ObservableValue<? extends Number> ov,
Number old_val, Number new_val) {
            if(bedingung == true){
                slider.setValue(old_val);
            }
    }
});

Das funktioniert so nicht...

Es gibt da bestimmt eine andere Loesung...

Sorry, wie fuege ich denn Code ein??? Sehe keinen Button..


----------



## Cromewell (1. Jun 2016)

Es gibt wahrscheinlich eine bessere Lösung, aber erstmal funktioniert das:

```
Slider slider = new Slider(0, 100, 0);
final long beforeTime = System.currentTimeMillis();
slider.valueProperty().addListener((observable, oldValue, newValue) -> {
    if(System.currentTimeMillis()-beforeTime < 3000 && newValue.intValue()-oldValue.intValue() != 1){
        slider.setValue(0);
    }else{
        slider.setValue(newValue.intValue());
    }
});

Button increase = new Button("add");
increase.setOnAction(e->{
    slider.setValue(slider.getValue()+1);
});
```

PS: Hier kann man nach 3s ohne Button bewegen.


----------



## patrick-89 (1. Jun 2016)

Ja stimmt so in dieser Art hatte ich es auch schon probiert, leider wird die Value dann auf 0 gesetzt. Was dann nicht der richtige Wert ist.


----------



## Cromewell (1. Jun 2016)

Ich dachte, die erste Zeit soll man den Slider nur über den Button bewegen können ?


----------



## patrick-89 (1. Jun 2016)

Nein, nein... Man soll die erste Zeit den Slider nicht per Touch bewegen duerfen. Der Button ist davon vollkommen unabhaengig, das ist ja einen extra Geschichte... Mir geht es vielmehr darum, wie kann ich verhindern das sich der Slider bewegt...


----------



## Cromewell (1. Jun 2016)

Ich verstehe nicht ganz, was du willst. Wenn ich den Code, den ich gepostet habe, ausführe, dann kann ich den Slider nicht bewegen - nur per Button - und wenn die Zeit (in meinem Code 3 Sekunden) vorüber ist, kann man den Slider auch normal bewegen?!


----------



## patrick-89 (1. Jun 2016)

Cromewell hat gesagt.:


> *if*(System.currentTimeMillis()-beforeTime < 3000 && newValue.intValue()-oldValue.intValue() != 1){
> slider.setValue(0);
> }



Das ist ja richtig, aber du setzt ja immer wieder die Value auf 0. Wenn jetzt der Slider schon auf der Value 50 steht, dann wuerde der Slider doch wieder auf 0 springen oder nicht???


----------



## Cromewell (1. Jun 2016)

patrick-89 hat gesagt.:


> Das ist ja richtig, aber du setzt ja immer wieder die Value auf 0. Wenn jetzt der Slider schon auf der Value 50 steht, dann wuerde der Slider doch wieder auf 0 springen oder nicht???


Ah, ich habe nicht viel geschlafen, man merkts - sry x)

Dann mach noch eine private double Variable position; Und in der Buttonfunktion setzt du sie dem values des Sliders gleich 
Und anstelle von 0 dann position.


----------



## patrick-89 (1. Jun 2016)

Habe ich auch schon alles versucht, nur leider hat das alles nix geholfen....


----------



## Cromewell (1. Jun 2016)

Wieso funktioniert es dann bei mir ?


----------



## patrick-89 (1. Jun 2016)

Verstehe leider nicht so ganz wie du das meinst.... Aber lassen wir einfach mal den Button oder die beider Buttons außen vor. Die haben eigentlich für die Lösung keine bewandnis.


----------



## Cromewell (1. Jun 2016)

```
private double position;

@Override
public void start(Stage primaryStage) throws Exception {
    Group root = new Group();
    VBox pane = new VBox(30);
    root.getChildren().addAll(pane);
    primaryStage.setScene(new Scene(root, 400, 400));

    Slider slider = new Slider(0, 100, 0);
    final long beforeTime = System.currentTimeMillis();
    slider.valueProperty().addListener((observable, oldValue, newValue) -> {
        if(System.currentTimeMillis()-beforeTime < 7000 && newValue.intValue()-oldValue.intValue() != 1){
            slider.setValue(position);
        }else{
            slider.setValue(newValue.intValue());
        }
    });

    Button increase = new Button("add");
    increase.setOnAction(e->{
        slider.setValue(slider.getValue()+1);
        position = slider.getValue();
    });


    pane.getChildren().addAll(slider, increase);

    primaryStage.show();
}
```



patrick-89 hat gesagt.:


> Die haben eigentlich für die Lösung keine bewandnis.


Doch - dort wird position gesetzt.


----------



## Patrick89 (1. Jun 2016)

Danke fuer den Ansatz, aber genau so hatte ich es auch schon, es hat aber nie so richtig funktioniert....

Teste deinen Code mal so: Versuche deinen Slider mal hin und her zu schieben bis er sich bewegt und dann versuche nochmal ohne den Button zu druecken deinen Slider zu bewegen. Du wirst sehen das der sich dann jedes mal sofort verschiebt...

Ich habe deinen Code mal so ueberarbeitet, das er fuer mich passend ist bzw. so wie ich mir das Verhalten wuensche 

Versuch mal mit meinem Code folgendes:

Versuche den Slider zu bewegen bis er sich bewegt, dann lass los und versuche es noch mal. Du wirst sehen es ist jedes mal das gleiche Verhalten (Bewegt sich erst nach 1sek). Dann klicke mal ein bisschen auf den Button rum und versuche danach wieder den Slider zu bewegen... Es ist wieder da gewuenschte Verhalten, das der Slider sich erst nach 1sek bewegt...

Die Zeit wird natuerlich noch verkuerzt, aber als Anschauung gut geeignet 


```
package application;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

    private double position;
    private long beforeTime;
    boolean isNewBeforeTime = true;
    boolean isButtonPressed = false;

    @Override
    public void start(Stage primaryStage) {
        Group root = new Group();
        VBox pane = new VBox(30);
        root.getChildren().addAll(pane);
        primaryStage.setScene(new Scene(root, 400, 400));

        Slider slider = new Slider(0, 100, 0);
        slider.valueProperty().addListener((observable, oldValue, newValue) -> {

            if (isButtonPressed) {
                return;
            }
            if (isNewBeforeTime) {
                beforeTime = System.currentTimeMillis();
                isNewBeforeTime = false;
            }

            if (System.currentTimeMillis() - beforeTime < 1000) {
                slider.setValue(position);
            } else {
                position = newValue.doubleValue();
                slider.setValue(position);
            }
        });

        slider.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent event) {
                isNewBeforeTime = true;

            }
        });

        Button increase = new Button("Increase");
        increase.setOnAction(e -> {
            isButtonPressed = true;
            position = slider.getValue() + 1;
            slider.setValue(position);
            isButtonPressed = false;
        });

        Button decrease = new Button("Decrease");
        decrease.setOnAction(e -> {
            isButtonPressed = true;
            position = slider.getValue() - 1;
            slider.setValue(position);
            isButtonPressed = false;
        });

        pane.getChildren().addAll(slider, increase, decrease);

        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
```


----------



## Cromewell (1. Jun 2016)

Vielleicht reden wir aneinander vorbei. Mach du einfach, wie du es für richtig hälst x)
Denn mit deinem Code kann ich den Slider gar nicht per Maus bewegen.
Wenn du jetzt einen Ansatz oder eine Lösung hast ist ja gut.


----------



## Patrick89 (1. Jun 2016)

Doch kannst du  

Halte die Maustaste einfach mal gedrueckt und versuche in einfach mal hin und herzu schieben bis er sich bewegt...


----------

