简体   繁体   English

Java FX中的动态条形图

[英]Dynamic Bar chart in Java FX

Hello I am trying to create bar chart which shows values of field. 您好我正在尝试创建显示字段值的条形图。 Values of field are changed by sorting algorithm and chart should show any of changes. 字段值通过排序算法更改,图表应显示任何更改。

public class FXMLDocumentController implements Initializable {

    static int[] pole = new int[10]; // field
    int hodnota;

    @FXML               // bar chart
    private BarChart barChart; 

    @FXML
    private void handleButtonAction(ActionEvent ev) { //button for filling up new random graph

        for (int i = 0; i < 10; i++) {
            hodnota = intValue((StrictMath.random() * 100));        
            pole[i] = hodnota;
        }

        final CategoryAxis osaX = new CategoryAxis();          
        final NumberAxis osaY = new NumberAxis();
        ObservableList<XYChart.Series<String, Number>> barChartData = FXCollections.observableArrayList();
        final BarChart.Series<String, Number> series1 = new BarChart.Series<>();
        series1.getData().add(new XYChart.Data<>("1", pole[0]));        
        series1.getData().add(new XYChart.Data<>("2", pole[1]));
        series1.getData().add(new XYChart.Data<>("3", pole[2]));
        series1.getData().add(new XYChart.Data<>("4", pole[3]));
        series1.getData().add(new XYChart.Data<>("5", pole[4]));
        series1.getData().add(new XYChart.Data<>("6", pole[5]));
        series1.getData().add(new XYChart.Data<>("7", pole[6]));
        series1.getData().add(new XYChart.Data<>("8", pole[7]));
        series1.getData().add(new XYChart.Data<>("9", pole[8]));
        series1.getData().add(new XYChart.Data<>("10", pole[9]));
        barChartData.add(series1);
        barChart.setData(barChartData);
    }

    @FXML // button which starts sorting algorhitm, it is changing values in field
    private void bubbleButton(ActionEvent ev) { 
        BubbleSort vlakno=new BubbleSort("vypoctoveVlakno");
        vlakno.start(); 
    }     

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }
}

I already tried to make a new thread which should load data again and again but it didn't work. 我已经尝试创建一个新的线程,它应该反复加载数据,但它不起作用。 Also tried to load them in the FXML controller but the graphics window gets stuck. 还尝试将它们加载到FXML控制器中,但图形窗口卡住了。 I am actually very new to this. 我其实很新。

FXML document, main just loads stage from fxml FXML文档,主要从fxml加载阶段

<AnchorPane id="AnchorPane" prefHeight="487.0" prefWidth="610.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="radicialgoritmy.FXMLDocumentController"> 
<children>  
<Button fx:id="button" layoutX="14.0" layoutY="14.0" onAction="#handleButtonAction" text="Vygeneruj" />  
<BarChart fx:id="barChart" animated="false" cache="true" layoutX="30.0"     layoutY="188.0" legendVisible="false" prefHeight="292.0" prefWidth="552.0">  
  <xAxis>  
    <CategoryAxis fx:id="osaX" side="BOTTOM" />  
  </xAxis>  
  <yAxis>  
    <NumberAxis fx:id="osaY" side="LEFT" />  
  </yAxis>  
</BarChart>
  <Button fx:id="bubble" layoutX="100.0" layoutY="14.0" mnemonicParsing="false" onAction="#bubbleButton" text="BubbleSort" /> 


Class for sorting Algorithm. 排序算法类。

class BubbleSort extends Thread {

    public BubbleSort(final String jmeno) {
        super(jmeno);
    }

    @Override
    public void run() {
        for (int i = 0; i < pole.length - 1; i++) {
            for (int j = 0; j < pole.length - i - 1; j++) {
                if (pole[j] < pole[j + 1]) {
                    final int tmp = pole[j];
                    pole[j] = pole[j + 1];
                    pole[j + 1] = tmp;
                }
                try {
                    Thread.sleep(250);
                } catch (final InterruptedException ex) {
                    Logger.getLogger(BubbleSort.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
}

Here is mcve demonstrating a mechanism to couple changing data to a BarChart . 这是mcve演示将更改数据耦合到BarChart的机制。
There are other ways to achieve this "binding", but I tried to keep is simple. 还有其他方法可以实现这种“绑定”,但我试图保持简单。
The bubble sort algorithm is not relevant to the question, not the answer , so it is better left out. 冒泡排序算法与问题无关,而与答案无关,因此最好省略。 An mcve needs to demonstrate the question / answer, and not the application: mcve需要演示问题/答案,而不是应用程序:

import java.util.Random;
import javafx.beans.Observable;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;

public class FXMLDocumentController {

    @FXML private BarChart barChart;
    private ObservableList<XYChart.Series<String, Number>> barChartData;
    private ObservableList<DataItem> items;
    private  Random rnd = new Random();
    private static  int SIZE = 10;

    @FXML
    void initialize(){
        //an observable collection of DataItem objects, each representing data of one bar 
        items = FXCollections.observableArrayList(
                dataItem -> new Observable[] { dataItem.nameProperty(), dataItem.valueProperty()});
        //initialize with random values 
        for (int i = 0; i < SIZE; i++) {
            items.add(new DataItem(String.valueOf(i), rnd.nextInt(100)));
        }
    }

    @FXML
    private void handleButtonAction( ActionEvent ev) {

         ObservableList<Data<String, Number>> seriesData = new DataConvertor(items).getData();
         CategoryAxis osaX = new CategoryAxis();
         NumberAxis osaY = new NumberAxis();
        barChartData = FXCollections.observableArrayList();
         BarChart.Series<String, Number> series1 = new BarChart.Series<>();
        series1.setData(seriesData);
        barChartData.add(series1);
        barChart.setData(barChartData);
    }

    @FXML
    private void bubbleButton( ActionEvent ev) {
        BubbleSort vlakno=new BubbleSort(items);
        vlakno.start();
    }
}

//pojo to represent items of one bar
class DataItem {

    private StringProperty name = new SimpleStringProperty(this, "name");
    private IntegerProperty value = new SimpleIntegerProperty(this, "value");

    public DataItem( String name,  int value) {
        setName(name);
        setValue(value);
    }
    public StringProperty nameProperty() {
        return name;
    }
    public String getName() {
        return this.nameProperty().get();
    }
    public void setName( String name) {
        this.nameProperty().set(name);
    }
    public  IntegerProperty valueProperty() {
        return value;
    }
    public int getValue() {
        return this.valueProperty().get();
    }
    public void setValue( int value) {
        this.valueProperty().set(value);
    }
}

//simple coupling between items and graph data 
class DataConvertor{

    ObservableList<DataItem> items;
    ObservableList<Data<String, Number>>data;
     DataConvertor( ObservableList<DataItem> items) {
        super();
        this.items = items;
        data =  FXCollections.observableArrayList();
        items.forEach(item -> data.add(new Data<>(item.getName(), item.getValue())));
        items.addListener( ( Change<? extends DataItem> arg0 ) ->   update());
    }

    void update() {
        for(int i =0; i < data.size(); i++){
             Data<String, Number> d = data.get(i);
            d.setYValue(items.get(i).getValue());
        }
        data.clear();
        items.forEach(item -> data.add(new Data<>(item.getName(), item.getValue())));
    }

    ObservableList<Data<String, Number>>getData(){
        return data;
    }
}

The BubbleSort class does not really sort. BubbleSort类并没有真正排序。 It only changes data periodically and randomly: 它只是定期和随机地更改数据:

import java.util.Random;
import javafx.animation.PauseTransition;
import javafx.collections.ObservableList;
import javafx.util.Duration;

class BubbleSort  {

    private ObservableList<DataItem> items;
    private Random rnd = new Random();
    private PauseTransition periodicTask;
    private static final long CYCLE = 500;

    public BubbleSort(final ObservableList<DataItem> items) {
        this.items = items;
        periodicTask = new PauseTransition(Duration.millis(CYCLE));
        periodicTask.setOnFinished((e) -> {
            calculateNewValues();
            periodicTask.playFromStart();
        });
    }

    private void calculateNewValues() {
        for(DataItem d : items){
            d.setValue(rnd.nextInt(100));
        }
    }

    void start(){
        periodicTask.playFromStart();
    }
}

Note that the posted fxml file in not complete. 请注意,发布的fxml文件未完成。 Those two tags are missing: 缺少这两个标签:

</children>   
</AnchorPane> 

I altered your program just to give you an idea of one way to accomplish this. 我改变了你的程序只是为了让你了解实现这个目标的一种方法。 I used Timeline to implement the BubbleSort . 我使用Timeline来实现BubbleSort

Main 主要

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 *
 * @author sedri
 */
public class RradiciAlgoritmy extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

Controller 调节器

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.util.Duration;
import static oracle.jrockit.jfr.events.Bits.intValue;

public class FXMLDocumentController implements Initializable {

    Timeline timeline;
    static int[] pole = new int[10]; // field
    int hodnota;
    int ii;

    @FXML               // bar chart
    private BarChart barChart; 

    @FXML
    private void handleButtonAction(ActionEvent ev) { //button for filling up new random graph

        for (int i = 0; i < 10; i++) {
            hodnota = intValue((StrictMath.random() * 100));        
            pole[i] = hodnota;
        }

        final CategoryAxis osaX = new CategoryAxis();          
        final NumberAxis osaY = new NumberAxis();
        ObservableList<XYChart.Series<String, Number>> barChartData = FXCollections.observableArrayList();
        final BarChart.Series<String, Number> series1 = new BarChart.Series<>();
        series1.getData().add(new XYChart.Data<>("1", pole[0]));        
        series1.getData().add(new XYChart.Data<>("2", pole[1]));
        series1.getData().add(new XYChart.Data<>("3", pole[2]));
        series1.getData().add(new XYChart.Data<>("4", pole[3]));
        series1.getData().add(new XYChart.Data<>("5", pole[4]));
        series1.getData().add(new XYChart.Data<>("6", pole[5]));
        series1.getData().add(new XYChart.Data<>("7", pole[6]));
        series1.getData().add(new XYChart.Data<>("8", pole[7]));
        series1.getData().add(new XYChart.Data<>("9", pole[8]));
        series1.getData().add(new XYChart.Data<>("10", pole[9]));
        barChartData.add(series1);
        barChart.setData(barChartData);

        ii = 0;
        timeline = new Timeline(new KeyFrame(Duration.seconds(1), (event) -> {
            System.out.println(ii + ": " + Arrays.toString(pole));
            for (int j = 0; j < pole.length - (ii) - 1; j++) {
                if (pole[j] < pole[j + 1]) {
                    final int tmp = pole[j];
                    pole[j] = pole[j + 1];
                    pole[j + 1] = tmp;
                }               
            }

            //Create new data and set it to the series
            List<XYChart.Data<String, Number>> tempData = new ArrayList();
            for(int i = 0; i < pole.length; i++)
            {
                tempData.add(new XYChart.Data(Integer.toString(i), pole[i]));
            }            
            barChartData.get(0).getData().setAll(tempData);

            ii++;
        }));
        timeline.setCycleCount(pole.length - 1);
    }

    @FXML // button which starts sorting algorhitm, it is changing values in field
    private void bubbleButton(ActionEvent ev) { 
        timeline.play();

    }     

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }
}

FXML FXML

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.chart.BarChart?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane id="AnchorPane" prefHeight="487.0" prefWidth="610.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="radicialgoritmy.FXMLDocumentController"> 
<children>  
<Button fx:id="button" layoutX="14.0" layoutY="14.0" onAction="#handleButtonAction" text="Vygeneruj" />  
<BarChart fx:id="barChart" animated="false" cache="true" layoutX="30.0" layoutY="188.0" legendVisible="false" prefHeight="292.0" prefWidth="552.0">  
  <xAxis>  
    <CategoryAxis fx:id="osaX" side="BOTTOM" />  
  </xAxis>  
  <yAxis>  
    <NumberAxis fx:id="osaY" side="LEFT" />  
  </yAxis>  
</BarChart>
  <Button fx:id="bubble" layoutX="100.0" layoutY="14.0" mnemonicParsing="false" onAction="#bubbleButton" text="BubbleSort" /> 
</children>
</AnchorPane>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM