2016-11-01 2 views
1

Also ich bin wirklich auf diesem fest, ich muss die Algorithmen, die am Ende meines Codes sind in JavaFX ausgeben, die zeigt, wie der Algorithmus funktioniert, dh Blase Sort bewegt sich kleinerer Balken an der Vorderseite des Paares usw. Das Problem, das ich habe, ist, dass ich nicht herausfinden kann, wie ich meine Algorithmen richtig in JavaFX anzeigen lassen kann. Die Tauschhälften und zufällige Arbeit, aber ich arbeitete nicht diesen Teil des Codes oder die oberen Stücke, also bin ich immer noch im Dunkeln, ich bin immer noch neu in Java und JavaFX ist irgendwie komisch für mich im MomentJavaFX Visualisierungsalgorithmen in Balkendiagrammen mit Animationen

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.stage.Stage; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.FlowPane; 
import javafx.scene.chart.BarChart; 
import javafx.scene.chart.CategoryAxis; 
import javafx.scene.chart.NumberAxis; 
import static javafx.scene.chart.XYChart.*; 
import javafx.geometry.Insets; 

import java.lang.reflect.Array; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Random; 

public class hamrickP2 extends Application { 
public static void main(String[] args) { 
    hamrickP2.launch(args); 
} 

private static final int 
    BAR_COUNT = 14, 
    MAX_BAR_HEIGHT = 50; 

private static final String 
    COLOR_ACTIVE = "-fx-bar-fill: #f64", 
    COLOR_INITIAL = "-fx-bar-fill: #888", 
    COLOR_FINALIZED = "-fx-bar-fill: #3cf"; 

private static final int 
    DELAY_MILLIS = 700; 

@Override 
public void start(Stage stage) { 
    stage.setTitle("Sorting Animations"); 
    stage.setWidth(800); 
    stage.setHeight(600); 

    final BorderPane pane = new BorderPane(); 
    pane.setPadding(new Insets(10)); 

    final BarChart<String,Number> chart = new BarChart<>(new  CategoryAxis(), new NumberAxis(0, MAX_BAR_HEIGHT, 0)); 
    chart.setLegendVisible(false); 
    chart.getYAxis().setTickLabelsVisible(false); 
    chart.getYAxis().setOpacity(0); 
    chart.getXAxis().setTickLabelsVisible(false); 
    chart.getXAxis().setOpacity(0); 
    chart.setHorizontalGridLinesVisible(false); 
    chart.setVerticalGridLinesVisible(false); 

    bars = new ArrayList<Data<String,Number>>(); 
    final Series<String,Number> data = new Series<>(); 
    chart.getData().add(data); 
    for (int i = 0; i < BAR_COUNT; i++) { 
     bars.add(new Data<>(Integer.toString(i+1), 1)); 
     data.getData().add(bars.get(i)); 
     paint(i, COLOR_INITIAL); 
    } 
    pane.setCenter(chart); 

    inputs = new FlowPane(); 
    inputs.setHgap(5); 
    inputs.setVgap(5); 
    createButton("Randomize",() -> randomizeAll()); 
    createButton("Swap Halves",() -> swapHalves()); 
    createButton("Reverse ",() -> reverse()); 
    createButton("Selection Sort",() -> selectionSort()); 


    pane.setBottom(inputs); 

    stage.setScene(new Scene(pane)); 
    stage.show(); 

    Platform.runLater(() -> randomizeAll()); 
} 

    private ArrayList<Data<String,Number>> bars; 
    private FlowPane inputs; 

    private void createButton(String label, Runnable method) { 
    final Button test = new Button(label); 
    test.setOnAction(event -> new Thread(() -> { 
     Platform.runLater(() -> inputs.setDisable(true)); 
     method.run(); 
     Platform.runLater(() -> inputs.setDisable(false)); 
    }).start()); 
    inputs.getChildren().add(test); 
} 



// CHART ACCESSORS AND MUTATORS 

private void assign(int index, int value) { 
    bars.get(index).setYValue(value); 
} 

private int retrieve(int index) { 
    return (int) bars.get(index).getYValue(); 
} 

// ANIMATION CONTROLS 

private void paint(int index, final String style) { 
    Platform.runLater(() -> { 
     bars.get(index).getNode().setStyle(style); 
    }); 
} 

private void paintAll(final String style) { 
    Platform.runLater(() -> { 
     for (int i = 0; i < BAR_COUNT; i++) paint(i, style); 
    }); 
} 

private void delay() { 
    try { 
     Thread.sleep(DELAY_MILLIS); 
    } 
    catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

// ALGORITHMS FOR BUTTONS 

private void randomizeAll() { 
    Random random = new Random(); 
    for (int i = 0; i < BAR_COUNT; i++) { 
     assign(i, random.nextInt(MAX_BAR_HEIGHT) + 1); 
    } 
} 

private void swapHalves() { 
    final int half = bars.size()/2; 
    final int offset = bars.size() % 2; 
    for (int i = 0; i < half; i++) { 
     final int j = i + half + offset; 

     paint(i, COLOR_ACTIVE); 
     paint(j, COLOR_ACTIVE); 

     int temp = retrieve(i); 
     assign(i, retrieve(j)); 
     assign(j, temp); 

     delay(); 

     paint(i, COLOR_FINALIZED); 
     paint(j, COLOR_FINALIZED); 
    } 
    paintAll(COLOR_INITIAL); 
}// Start of algorithms 

/** 
* Reverse algorithm 
* @param array 
* @return 
*/ 
public void reverse(){ 
    int array [] = new int [BAR_COUNT]; 
    for(int pos = 0; pos < array.length; pos++) 
    { 

     int generic = array[pos]; 
     array[pos] = array[array.length - 1 - pos]; 
     array[array.length -1 - pos] = generic; 

     int temp = array[array.length -1 - pos]; 

     assign(array[pos] , retrieve(array[array.length - 1 - pos])); 
     assign(temp , generic); 

     delay(); 


     paint(pos, COLOR_FINALIZED); 
     paint(temp, COLOR_FINALIZED); 


    } 
    paintAll(COLOR_INITIAL); 

} 



/** 
* Selection Sort algorithm 
* @param words 
*/ 
public void selectionSort(){ 
    int arr [] = new int [BAR_COUNT]; 

    for (int i = 0; i < arr.length - 1; i++) 
    { 
     paint(i, COLOR_ACTIVE); 

     int index = i; 
     for (int j = i + 1; j < arr.length; j++) 
      if (arr[j] < arr[index]) 
       index = j; 

     int smallerNumber = arr[index]; 
     arr[index] = arr[i]; 
     arr[i] = smallerNumber; 

     int temp = retrieve(i); 
     assign(i, retrieve(i)); 
     assign(index, temp); 

     delay(); 

     paint(i, COLOR_FINALIZED); 
     paint(index, COLOR_FINALIZED); 

    } 
    paintAll(COLOR_INITIAL); 
} 
     /** 
     * Bubble Sort algorithm 
     * @param words 
     */ 
     public void bubbleSort(){ 
      int array [] = new int [BAR_COUNT]; 
      int temp; 
      for(int i = 0; i <array.length; i++){ 

       for(int j = 1; j <array.length -i; j++){ 
        if(array[j-1] > array[j]){ 
         temp = array[j -1]; 
         array[j-1] = array[j]; 
         array[j] = temp; 
        } 
       } 
      } 
     } 

        /** 
      * Insertion Sort algorithm 
      * @param array 
      */ 
    public void insertionSort(){ 

     int array [] = new int [BAR_COUNT]; 
     for (int i = 1; i < array.length; i++) { 
      int temp = array[i]; 
      int j; 
      for(j = i -1; j>= 0 && temp < array[j]; j--){ 
       array[j +1 ] = array[j]; 
      array[j + 1 ] =temp; 
     } 
      paintAll(COLOR_INITIAL);  
    } 
} 
} 
+0

eine Erklärung dafür, wie ich die Daten für das Balkendiagramm in die Algorithmen übertrage, wäre hilfreich für mich. –

+0

Siehe meine Antwort.Ich fügte einen Beispielcode hinzu, der zeigt, wie man auf Daten zugreift und sie an das Diagramm zurücksendet. Wenn es nützlich war, akzeptieren Sie es bitte als Antwort oder machen Sie einen Kommentar, wenn Sie weitere Hilfe benötigen. – Zerlono

Antwort

0

Ich habe einige Probleme in Ihrem Code gefunden. Betrachten Sie die folgenden Dinge:

  1. Make bars ein ObservableList und verwenden Sie diese für Ihre Serie. Die Series-Instanz nimmt diese Liste und verwendet sie intern. Auf diese Weise können Sie die Liste beobachten und die Liste später ändern, während sich das Diagramm automatisch aktualisiert. Der Zugriff auf Ihre Daten ist so einfach wie die Verwendung von Balken als Liste oder das Extrahieren eines Arrays aus Balken. Ich habe zwei bubblesort Versionen gemacht. Ein Zugriff auf Bars als Liste (Inplace) und ein Extrahieren eines Arrays (nicht vorhanden).
  2. Nachdem Sie Balken ein neues Datenobjekt hinzugefügt haben, können Sie auf den Knoten zugreifen, um die Farbe zu ändern. Sie müssen Platform.runlater nicht verwenden. Runlate wird trotzdem missbraucht, da es keine Garantie gibt, dass die Ressource, auf die Sie warten, zu einem späteren Zeitpunkt vorhanden sein wird. Wenn Sie eine Aktion an einer Ressource ausführen möchten, die zu einem unbekannten Zeitpunkt vorhanden sein wird, beobachten Sie, ob es sich um einen beobachtbaren Wert handelt. Verwenden Sie addListener und achten Sie auf Änderungen.
  3. Verwenden Sie KEINE Threads und ändern Sie die Daten Ihrer GUI nicht. Runalter zu verwenden, um die Schaltfläche zu deaktivieren, ist in Ordnung, aber Sie tun eine Menge anderer Dinge in Ihrem Thread. Außerdem kann der Körper Ihres Runlater später aufgerufen werden (O.o). So viel später, dass dein Thread schon fertig ist. Runlater ist ein asynchroner Aufruf.
  4. Verwenden Sie die JavaFX-Animationsklassen, wenn Sie die GUI in geplanten Zeitrahmen ändern möchten. Die Timeline ist vielleicht wat Sie suchen. This tutorial führt das Konzept ein.

Ich machte ein Beispiel aus Ihrem Code. Ich ein paar Sachen löschen, um es deutlicher zu machen:

import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.geometry.Insets; 
import javafx.scene.Node; 
import javafx.scene.Scene; 
import javafx.scene.chart.BarChart; 
import javafx.scene.chart.CategoryAxis; 
import javafx.scene.chart.NumberAxis; 
import javafx.scene.control.Button; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.FlowPane; 
import javafx.stage.Stage; 

import java.util.List; 
import java.util.Random; 

import static javafx.scene.chart.XYChart.Data; 
import static javafx.scene.chart.XYChart.Series; 

public class Main extends Application { 
    public static void main(String[] args) { 
     launch(args); 
    } 

    private static final int 
     BAR_COUNT = 14, 
     MAX_BAR_HEIGHT = 50; 

    private static final String 
     COLOR_ACTIVE = "-fx-bar-fill: #f64", 
     COLOR_INITIAL = "-fx-bar-fill: #888", 
     COLOR_FINALIZED = "-fx-bar-fill: #3cf"; 

    private static final int 
     DELAY_MILLIS = 700; 


    private ObservableList<Data<String, Number>> bars; 
    private BarChart<String, Number> chart; 
    private FlowPane inputs; 


    @Override 
    public void start(Stage stage) { 
     stage.setTitle("Sorting Animations"); 
     stage.setWidth(800); 
     stage.setHeight(600); 

     final BorderPane pane = new BorderPane(); 
     pane.setPadding(new Insets(10)); 

     makeChart(pane); 
     makeButtons(pane); 

     stage.setScene(new Scene(pane)); 
     stage.show(); 

     randomizeAll(); 
    } 

    private void makeChart(BorderPane pane) { 
     chart = new BarChart<>(new CategoryAxis(), new NumberAxis(0, MAX_BAR_HEIGHT, 0)); 
     chart.setLegendVisible(false); 
     chart.getYAxis().setTickLabelsVisible(false); 
     chart.getYAxis().setOpacity(0); 
     chart.getXAxis().setTickLabelsVisible(false); 
     chart.getXAxis().setOpacity(0); 
     chart.setHorizontalGridLinesVisible(false); 
     chart.setVerticalGridLinesVisible(false); 

     bars = FXCollections.observableArrayList(); 
     chart.getData().add(new Series<>(bars)); 

     for (int i = 0; i < BAR_COUNT; i++) { 
      Data<String, Number> dataObject = new Data<>(Integer.toString(i + 1), 1); 
      bars.add(dataObject); // node will be present after this 
      addPainting(dataObject.getNode(), COLOR_INITIAL); // do this after bars.add 
     } 
     pane.setCenter(chart); 
    } 


    private void makeButtons(BorderPane pane) { 
     inputs = new FlowPane(); 
     inputs.setHgap(5); 
     inputs.setVgap(5); 
     createButton("Randomize",() -> randomizeAll()); 
     createButton("Bubble Sort 1",() -> bubbleSort1()); 
     createButton("Bubble Sort 2",() -> bubbleSort2()); 
     pane.setBottom(inputs); 
    } 

    private void addPainting(Node newNode, String colorInitial) { 
     if (newNode != null) { 
      newNode.setStyle(colorInitial); 
     } 
    } 

    private void createButton(String label, Runnable method) { 
     final Button test = new Button(label); 
     test.setOnAction(event -> method.run()); 
     inputs.getChildren().add(test); 
    } 


    private void randomizeAll() { 
     Random random = new Random(); 
     for (Data<String, Number> bar : bars) { 
      bar.setYValue(random.nextInt(MAX_BAR_HEIGHT) + 1); 
     } 
    } 


    /** 
    * Bubble Sort algorithm 
    */ 
    private void bubbleSort1(){ 
     List<Data<String, Number>> list = bars; 

     double temp;   
     for(int i = 0; i < list.size(); i++){ 
      for(int j = 1; j < list.size() - i; j++){ 
       if (getValue(list, j - 1) > getValue(list, j)){ 
        temp = getValue(list, j - 1); 
        list.get(j - 1).setYValue(list.get(j).getYValue()); 
        list.get(j).setYValue(temp); 
       } 
      } 
     } 
    } 

    private double getValue(List<Data<String, Number>> list, int index) { 
     return list.get(index).getYValue().doubleValue(); 
    } 


    /** 
    * Bubble Sort algorithm 
    */ 
    private void bubbleSort2(){ 
     double[] array = bars.stream().mapToDouble(data -> data.getYValue().doubleValue()).toArray(); 

     double temp; 
     for(int i = 0; i <array.length; i++){ 
      for(int j = 1; j <array.length -i; j++){ 
       if(array[j-1] > array[j]){ 
        temp = array[j -1]; 
        array[j-1] = array[j]; 
        array[j] = temp; 
       } 
      } 
     } 
     for (int i = 0; i < array.length; i++) { 
      bars.get(i).setYValue(array[i]); 
     } 
    } 

} 

Update 1 zuordnen und Abrufen von Arbeiten, wie Sie bereits in Ihrer Frage gemacht haben, wenn Sie es im beobachtbaren Weise umgesetzt.

private void assign(int index, int value) { 
    bars.get(index).setYValue(value); 
} 

private int retrieve(int index) { 
    return (int) bars.get(index).getYValue(); 
} 

Ich machte es auf die gleiche Weise; z.B. siehe den Körper der letzten for-Schleife.

Um das Diagramm zu animieren, müssen Sie den Algorithmus so umschreiben, dass er nur einen Schritt pro Aufruf ausführt, anstatt das gesamte Array auf einmal zu sortieren. Eg. Der Funktionsaufruf von bubblesort kehrt zurück, nachdem er seinen ersten Swap durchgeführt hat.

Der letzte Schritt wäre, eine TimeLine (Timer) zu initialisieren, um alle t Sekunden den One-Step-Only-Bubblesort-Algorithmus aufzurufen.

Der schwierige Teil ist, wie man sich erinnert, wo der letzte Lauf des Algorithmus aufhört und wie man es fortsetzt.

+0

Danke, aber ich frage mich, ob Sie mir die Methode assign() und retrieve() erklären könnten, da ich erfolglose Ergebnisse hatte, da ich angeblich diese Methoden verwenden könnte, um die Daten von den Balken und zurück zu übergeben heraus zum Diagramm. Dein Weg funktioniert, aber ich bin nicht in der Lage, die Algorithmen richtig zu animieren. Danke für deine Hilfe, wie ich es wirklich schätze. –

+0

Ich aktualisierte meine Antwort mit einer spezifischeren Erklärung, wie Animation gemacht wird. – Zerlono

Verwandte Themen