2016-04-21 13 views
0

Ich versuche, die Tasten des folgenden Programms einzurichten, aber sie werden das Programm nicht richtig steuern. Ich bin mir nicht sicher, warum sie nicht arbeiten. Der Rückwärts-Button funktioniert, aber die Start- und Stop-Buttons nicht.Tasten funktionieren nicht Programm

import javafx.animation.KeyFrame; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Arc; 
import javafx.scene.shape.ArcType; 
import javafx.scene.shape.Circle; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class ch30 extends Application { 
    @Override // Override the start method in the Application class 
    public void start(Stage primaryStage) {  
    FanPane fan = new FanPane(); 

    HBox hBox = new HBox(5); 
    Button btPause = new Button("Pause"); 
    Button btResume = new Button("Resume"); 
    Button btReverse = new Button("Reverse"); 
    hBox.setAlignment(Pos.CENTER); 
    hBox.getChildren().addAll(btPause, btResume, btReverse); 

    BorderPane pane = new BorderPane(); 
    pane.setCenter(fan); 
    pane.setBottom(hBox); 

    // Create a scene and place it in the stage 
    Scene scene = new Scene(pane, 200, 200); 
    primaryStage.setTitle("Exercise15_28"); // Set the stage title 
    primaryStage.setScene(scene); // Place the scene in the stage 
    primaryStage.show(); // Display the stage 

    //Runnable first = new Begin(); 

    //Thread first = new Thread(); 

    //t1.start(); 


     Thread first = new Thread(new Runnable() { 
      @Override public void run() { 
       while (true) { 
        try { 
         //Pause 
         Thread.sleep(100); 

        } catch (InterruptedException ex) { 
         ex.printStackTrace(); 
        } 
        Platform.runLater(new Runnable() { 
         @Override public void run() { 

          fan.move(); 

         } 
        }); 
       } 
      } 
     }); 

       first.start(); 



    //Timeline animation = new Timeline(
     //new KeyFrame(Duration.millis(100), e -> fan.move())); 
    //animation.setCycleCount(Timeline.INDEFINITE); 
    //animation.play(); // Start animation 

    scene.widthProperty().addListener(e -> fan.setW(fan.getWidth())); 
    scene.heightProperty().addListener(e -> fan.setH(fan.getHeight())); 

    //btPause.setOnAction(e -> first.wait()); 
    btResume.setOnAction(e -> first.start()); 
    btReverse.setOnAction(e -> fan.reverse()); 
    } 

    /** 
    * The main method is only needed for the IDE with limited 
    * JavaFX support. Not needed for running from the command line. 
    */ 
    public static void main(String[] args) { 
    launch(args); 


    } 
} 

class FanPane extends Pane { 
    private double w = 200; 
    private double h = 200; 
    private double radius = Math.min(w, h) * 0.45; 
    private Arc arc[] = new Arc[4]; 
    private double startAngle = 30; 
    private Circle circle = new Circle(w/2, h/2, radius); 

    public FanPane() { 
    circle.setStroke(Color.BLACK); 
    circle.setFill(Color.WHITE); 
    getChildren().add(circle); 

    for (int i = 0; i < 4; i++) { 
     arc[i] = new Arc(w/2, h/2, radius * 0.9, radius * 0.9, startAngle + i * 90, 35); 
     arc[i].setFill(Color.RED); // Set fill color 
     arc[i].setType(ArcType.ROUND); 
     getChildren().addAll(arc[i]); 
    } 
    } 

    private double increment = 5; 

    public void reverse() { 
    increment = -increment; 
    } 

    public void move() { 
    setStartAngle(startAngle + increment); 
    } 

    public void setStartAngle(double angle) { 
    startAngle = angle; 
    setValues(); 
    } 

    public void setValues() { 
    radius = Math.min(w, h) * 0.45; 
    circle.setRadius(radius); 
    circle.setCenterX(w/2); 
    circle.setCenterY(h/2); 

    for (int i = 0; i < 4; i++) { 
     arc[i].setRadiusX(radius * 0.9); 
     arc[i].setRadiusY(radius * 0.9); 
     arc[i].setCenterX(w/2); 
     arc[i].setCenterY(h/2); 
     arc[i].setStartAngle(startAngle + i * 90); 
    }  
    } 

    public void setW(double w) { 
    this.w = w; 
    setValues(); 
    } 

    public void setH(double h) { 
    this.h = h; 
    setValues(); 
    } 
} 
+0

'wait' hält den Thread nicht an, sondern lässt den aktuellen (aufrufenden) Thread warten, bis jemand' notify' auf demselben Objekt aufruft. Werfen Sie einen Blick auf [diese Frage] (http://stackoverflow.com/questions/19894607/java-how-to-stop-thread) – Itai

Antwort

2

Dies sollte mit einer Timeline getan werden, ich weiß es Ihre Hausaufgaben ist und aus irgendeinem verrückten Grund hat Ihre Hausaufgaben nicht eine Timeline verwenden angegeben wurde. Aber für jeden anderen tun Sie es nicht so, benutzen Sie einfach eine Zeitleiste.

Das heißt ...

Sie erwähnen, Start- und Stopp-Tasten, von denen Sie keine haben. Ich nehme an, dass Start bedeutet, dass Sie fortfahren und anhalten bedeutet, dass Sie anhalten, da dies die Tasten sind, die Sie haben. Also werde ich entsprechend antworten.

Der einfachste Weg, dies zu umgehen, ist die Verwendung einer booleschen Variablen, um zu steuern, ob sich der Lüfter bewegt oder nicht.

ein Mitglied Ihrer Anwendung definieren:

private boolean paused = false; 

nur in Ihrem Thread den Lüfter bewegen, wenn nicht angehalten:

Platform.runLater(() -> { if (!paused) fan.move(); }); 

Ihre Tasten Konfigurieren Sie Ihre Flag zu setzen:

btPause.setOnAction(e -> paused = true); 
btResume.setOnAction(e -> paused = false); 

Ich habe gerade die Pause-Variable direkt in der aufrufenden Anwendung, aber Sie könnten die Pause statu kapseln s innerhalb des Fan-Objekts, wenn Sie es wünschen.

Normalerweise müssen Sie beim Umgang mit Multithread-Material vorsichtig sein, dass Daten aufgrund von Racebedingungen beschädigt werden. Zum Beispiel würden Sie Konstrukte wie AtomicBoolean oder synchronisierte Anweisungen verwenden. Aber runLater setzt alles auf den JavaFX-Anwendungs-Thread, so dass Sie sich nicht unbedingt darum kümmern müssen.

Es gibt alternative Mechanismen Sie verwenden, um sicherzustellen könnte, dass der Thread nicht halten Looping und und schlafen, wie wait/notify oder Conditions, aber für eine Probe wie diese, müssen Sie wahrscheinlich nicht, dass hier.

aktualisiert Anwendung

aktualisiert Probe die vorgeschlagenen Änderungen zeigen, getestet auf JDK 8u60, OS X 10.11.4.

public class ch30 extends Application { 
    private boolean paused = false; 

    @Override 
    public void start(Stage primaryStage) { 
     FanPane fan = new FanPane(); 

     HBox hBox = new HBox(5); 
     Button btPause = new Button("Pause"); 
     Button btResume = new Button("Resume"); 
     Button btReverse = new Button("Reverse"); 
     hBox.setAlignment(Pos.CENTER); 
     hBox.getChildren().addAll(btPause, btResume, btReverse); 

     BorderPane pane = new BorderPane(); 
     pane.setCenter(fan); 
     pane.setBottom(hBox); 

     Thread first = new Thread(() -> { 
      while (true) { 
       try { 
        Thread.sleep(100); 
       } catch (InterruptedException ex) { 
        break; 
       } 
       Platform.runLater(() -> { if (!paused) fan.move(); }); 
      } 
     }); 
     first.setDaemon(true);  
     first.start(); 

     btPause.setOnAction(e -> paused = true); 
     btResume.setOnAction(e -> paused = false); 
     btReverse.setOnAction(e -> fan.reverse()); 

     Scene scene = new Scene(pane, 200, 200); 
     scene.widthProperty().addListener(e -> fan.setW(fan.getWidth())); 
     scene.heightProperty().addListener(e -> fan.setH(fan.getHeight())); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 
} 

Neben

die daemon status des Threads so einstellen, dass Ihre Anwendung wird sauber nach unten, wenn jemand auf der Hauptbühne geschlossen wird.

first.setDaemon(true); 
+0

Dies funktioniert eigentlich nicht. Jetzt verwende ich first.stop(), um das Programm anzuhalten. Ich kann den Thread jedoch nicht neu starten, nachdem ich ihn beendet habe. Weißt du, warum die Wiederaufnahme-Taste nicht funktioniert? – milliehol

+0

Die in dieser Antwort vorgestellte Lösung funktioniert.Sie sollten nie [thread.stop()] (https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#stop--) aufrufen, es ist veraltet und die Dokumentation notiert dass seine Verwendung unsicher ist. Wenn Sie dies getan haben, wird der Thread-Status zu [Thread.State.TERMINATED] (https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html#TERMINATED) weitergeleitet. . Dies ist ein [Endzustand] (http://www.uml-diagrams.org/examples/java-6-thread-state-machine-diagram-example.html). Ein abgeschlossener Thread wird für immer beendet bleiben, er kann die Verarbeitung nie fortsetzen. – jewelsea

+0

Wenn ich versuche, Ihre Lösung zu verwenden, heißt es, dass ich die boolesche Variable nicht verwenden kann, wenn sie nicht endgültig ist. Wenn ich es als endgültig deklariere, kann ich es im Schaltflächenbereich nicht als wahr oder falsch festlegen. Weißt du, warum ich diesen Fehler bekomme? – milliehol

Verwandte Themen