我正在使用Barchart和Piechart处理此代码。
import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableObjectValue;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class MainApp extends Application
{
@Override
public void start(Stage stage) throws Exception
{
Scene scene = new Scene(initGeneralAgentsData(), 800, 800);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
launch(args);
}
private final StackPane stackPane = new StackPane();
private List<DownloadTrafficObj> obj = new LinkedList<>();
public StackPane initGeneralAgentsData() throws Exception
{
stackPane.setAlignment(Pos.TOP_RIGHT);
stackPane.setStyle("-fx-background-color: white;");
SQLSelect(30);
stackPane.getChildren().addAll(chartChoose());
return stackPane;
}
private List<DownloadTrafficObj> SQLSelect(int history_value)
{
for (int i = 0; i < history_value; i++)
{
obj.add(new DownloadTrafficObj(String.valueOf(randomDate()), Long.valueOf(randomNumber())));
}
return obj;
}
private Timestamp randomDate()
{
long offset = Timestamp.valueOf("2012-01-01 00:00:00").getTime();
long end = Timestamp.valueOf("2013-01-01 00:00:00").getTime();
long diff = end - offset + 1;
Timestamp rand = new Timestamp(offset + (long) (Math.random() * diff));
return rand;
}
private int randomNumber()
{
Random rand = new Random();
int n = rand.nextInt(50) + 1;
return n;
}
public StackPane chartChoose()
{
final ComboBox comboBox = new ComboBox();
comboBox.getItems().addAll("Bar Chart", "Pie Chart");
ComboBox cb = new ComboBox();
cb.getItems().addAll(10, 20, 30, 60);
cb.setValue(30);
final StackPane stack = new StackPane();
comboBox.getSelectionModel().selectedIndexProperty()
.addListener((ObservableValue<? extends Number> observable,
Number oldValue, Number newValue)
-> setVisibility(stack, comboBox)
);
cb.getSelectionModel().selectedIndexProperty()
.addListener((ObservableValue<? extends Number> observable,
Number oldValue, Number newValue)
->
{
SQLSelect((int) cb.getSelectionModel().getSelectedItem());
bc.getData().clear();
generateBarChartData();
}
);
stack.getChildren().add(generateBarChart());
stack.getChildren().add(generatePieChart());
// Placing it after adding rectangle to stack
// will trigger the changelistener to show default rectangle
comboBox.setValue("Bar Chart");
VBox vBox = new VBox();
vBox.setPadding(new Insets(10, 10, 10, 10));
vBox.setSpacing(5);
Label labelon = new Label("Chart type");
Label label = new Label("Days history");
HBox hBossx = new HBox(15, labelon, comboBox, label, cb);
hBossx.setAlignment(Pos.CENTER_RIGHT);
ProgressIndicator progress = new ProgressIndicator();
progress.setMaxSize(90, 90);
Task<ObservableList<DownloadTrafficObj>> task = new Task<ObservableList<DownloadTrafficObj>>()
{
@Override
protected ObservableList<DownloadTrafficObj> call() throws Exception
{
for (int i = 0; i < 99; i++)
{
Thread.sleep(20);
}
return (FXCollections.observableArrayList(obj));
}
};
progress.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(ev ->
{
});
new Thread(task).start();
BorderPane bp = new BorderPane();
bp.centerProperty().bind(
Bindings
.when(task.runningProperty())
.then(progress)
.otherwise((ObservableObjectValue<ProgressIndicator>) stack));
vBox.getChildren().addAll(hBossx, bp);
StackPane root = new StackPane();
root.getChildren().add(vBox);
return root;
}
public void setVisibility(Pane pane, ComboBox comboBox)
{
// Make all children invisible
pane.getChildren().stream().forEach((node) ->
{
node.setVisible(false);
});
// make the selected rectangle visible
int selectedIndex = comboBox.getSelectionModel()
.selectedIndexProperty().getValue();
pane.getChildren().get(selectedIndex).setVisible(true);
}
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final BarChart<String, Number> bc = new BarChart<>(xAxis, yAxis);
XYChart.Series series1 = new XYChart.Series();
public BarChart<String, Number> generateBarChart()
{
bc.setTitle("Network Download");
xAxis.setLabel("Groups");
yAxis.setLabel("Value");
series1.setName("Network Download");
generateBarChartData();
// TO DO... Very quick fix.
bc.widthProperty().addListener((obs, b, b1) ->
{
// Chart Bar column is not automatically resized. We need to wait for next JavaFX releases to fix this.
Platform.runLater(() -> setMaxBarWidth(bc, xAxis, 40, 10));
});
bc.getData().addAll(series1);
return bc;
}
private void generateBarChartData()
{
obj.stream().map((get) -> new XYChart.Data(get.getDate(), get.getDownloadTraffic())).map((data) ->
{
data.nodeProperty().addListener(new ChangeListener<Node>()
{
@Override
public void changed(ObservableValue<? extends Node> ov, Node oldNode, final Node node)
{
if (node != null)
{
//setNodeStyle(data);
displayLabelForData(data);
}
}
});
return data;
}).forEach((data) ->
{
series1.getData().add(data);
});
}
private void setMaxBarWidth(BarChart<String, Number> bc, CategoryAxis xAxis, double maxBarWidth, double minCategoryGap)
{
double barWidth = 0;
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap());
barWidth = (avilableBarSpace / bc.getData().size()) - bc.getBarGap();
if (barWidth > maxBarWidth)
{
avilableBarSpace = (maxBarWidth + bc.getBarGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getBarGap());
}
}
while (barWidth > maxBarWidth);
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (minCategoryGap + bc.getBarGap());
barWidth = Math.min(maxBarWidth, (avilableBarSpace / bc.getData().size()) - bc.getBarGap());
avilableBarSpace = (barWidth + bc.getBarGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getBarGap());
}
while (barWidth < maxBarWidth && bc.getCategoryGap() > minCategoryGap);
}
public PieChart generatePieChart()
{
ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList();
obj.stream().forEach((activeAgentGroup) ->
{
pieChartData.add(new PieChart.Data(activeAgentGroup.getDate(), activeAgentGroup.getDownloadTraffic()));
});
final PieChart chart = new PieChart(pieChartData);
chart.setTitle("Label");
return chart;
}
private void displayLabelForData(XYChart.Data<String, Number> data)
{
final Node node = data.getNode();
final Text dataText = new Text(data.getYValue().toString());
node.parentProperty().addListener(new ChangeListener<Parent>()
{
@Override
public void changed(ObservableValue<? extends Parent> ov, Parent oldParent, Parent parent)
{
Group parentGroup = (Group) parent;
parentGroup.getChildren().add(dataText);
}
});
node.boundsInParentProperty().addListener(new ChangeListener<Bounds>()
{
@Override
public void changed(ObservableValue<? extends Bounds> ov, Bounds oldBounds, Bounds bounds)
{
dataText.setLayoutX(
Math.round(
bounds.getMinX() + bounds.getWidth() / 2 - dataText.prefWidth(-1) / 2
)
);
dataText.setLayoutY(
Math.round(
bounds.getMinY() - dataText.prefHeight(-1) * 0.5
)
);
}
});
}
}
我想在切换图表和加载数据期间添加循环进度条。通常从数据库加载数据需要2-3秒,因此我需要一种方法来显示进度托架,因为图表是堆叠的。 还有什么简单的方法来实现图表的切换?
答案 0 :(得分:2)
短而甜蜜:
BorderPane
作为图表的父容器。Bindings
,Task.runningProperty()
和BorderPane.centerProperty()
例如:
myBorderPane.centerProperty().bind(
Bindings
.when(myLongTask.runningProperty())
.then(myProggressIndicator)
.otherwise(myChart));