Giter VIP home page Giter VIP logo

charts's People

Contributors

antoine-guillou avatar hansolo avatar jkrude avatar markus-olbrich avatar quangctkm9207 avatar richard-woodward avatar ronsmits avatar sschuberth avatar thomasdaheim avatar thomasnield avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

charts's Issues

Charts 11.11 - further Customization

Hi there (again) :D
Thanks again for the quick implementation of issue #74 . I am very happy with it :)

I have one more wish, if that's not too much to ask for.
I´d like to have another StringProperty on the chartitem (and another constructor).
Heres why:
i got some data that i want to show on the coxcombchart that has a very long name.
i´d like to show a "succintly name" on the chart and on a label (where obviously would be enough space of showing it), the "long name".

Basically all i´d need is a stringproperty on the chartitem, a constructor so i can fill it and a getter for the new StringProperty.
The constructor should look something like this:
public ChartItem(String NAME, double VALUE, String LONGNAME, Color FILL)
"LONGNAME" might not be the best choice of name, but i think you get what i mean :D

this seems more like an feature request (for which I did not find the possibility).

RadarChart category labels

Greetings Gerrit,
I was recently trying out your amazing RadarChart, and for some reason I'm not able to reach any place where I can add category values to the radar. Are these coming directly from the YChartItem? If so, I would expect, for example in your RadarChartTest, that

YChartItem(RND.nextDouble() * 100, "P" + i);

would show P1, P2, etc as categories around the 'radar'. Or am I missing something?

Anyway, thanks for these amazing javafx libraries!
Cheers

NullpointerException - getConnection(PlotItem, PlotItem) returns null

Hello Gerrit,

In the latest Release is a Bug.

In CirularPlot.java
line 674: Connection connection = getConnection(item, outgoingItem);
Is trying to get a Connection that should be there but returns null.

line 704: connection.setTooltipText(tooltipText);
Is now trying to set the Tooltip for null.

The Problem is reproducible in the CircularPlotTest class by enabling the currently commented out Outgoings.

@Override public void init() {
    // Setup Data
    // Wahlberechtigte 61_500_000
    PlotItem australia = new PlotItem("AUSTRALIA", 1_250_000, Color.rgb(255, 51, 51));
    PlotItem india     = new PlotItem("INDIA", 750_000, Color.rgb(255, 153, 51));
    PlotItem china     = new PlotItem("CHINA", 920_000, Color.rgb(255, 255, 51));
    PlotItem japan     = new PlotItem("JAPAN", 1_060_000, Color.rgb(153, 255, 51));
    PlotItem thailand  = new PlotItem("THAILAND", 720_000, Color.rgb(51, 255, 51));
    PlotItem singapore = new PlotItem("SINGAPORE", 800_000, Color.rgb(51, 255, 153));

    // Travel flow
    australia.addToOutgoing(india, 150_000);
    australia.addToOutgoing(china, 90_000);
    australia.addToOutgoing(japan, 180_000);
    australia.addToOutgoing(thailand, 15_000);
    australia.addToOutgoing(singapore, 10_000);

    japan.addToOutgoing(australia, 70_000);

    List<PlotItem> items = List.of(australia, india, china, japan, thailand, singapore );

    // Register listeners to click on connections and items
    items.forEach(item -> {
        item.addItemEventListener(e -> {
            switch (e.getEventType()) {
                case SELECTED: System.out.println("Selected: " + e.getItem().getName()); break;
            }
        });
    });

    
    india.addToOutgoing(australia, 35_000);
    india.addToOutgoing(china, 10_000);
    india.addToOutgoing(japan, 40_000);
    india.addToOutgoing(thailand, 25_000);
    india.addToOutgoing(singapore, 8_000);

    china.addToOutgoing(australia, 10_000);
    china.addToOutgoing(india, 7_000);
    china.addToOutgoing(japan, 40_000);
    china.addToOutgoing(thailand, 5_000);
    china.addToOutgoing(singapore, 4_000);

    japan.addToOutgoing(australia, 7_000);
    japan.addToOutgoing(india, 8_000);
    japan.addToOutgoing(china, 175_000);
    japan.addToOutgoing(thailand, 11_000);
    japan.addToOutgoing(singapore, 18_000);

    thailand.addToOutgoing(australia, 70_000);
    thailand.addToOutgoing(india, 30_000);
    thailand.addToOutgoing(china, 22_000);
    thailand.addToOutgoing(japan, 120_000);
    thailand.addToOutgoing(singapore, 40_000);

    singapore.addToOutgoing(australia, 60_000);
    singapore.addToOutgoing(india, 90_000);
    singapore.addToOutgoing(china, 110_000);
    singapore.addToOutgoing(japan, 14_000);
    singapore.addToOutgoing(thailand, 30_000);
    

    // Setup Chart
    circluarPlot = CircularPlotBuilder.create()
                                      .prefSize(500, 500)
                                      .items(items)
                                      .connectionOpacity(0.75)
                                      .decimals(0)
                                      .minorTickMarksVisible(false)
                                      .build();

    ConnectionEventListener connectionListener = e -> System.out.println("From: " + e.getConnection().getOutgoingItem().getName() + " -> to: " + e.getConnection().getIncomingItem().getName() + " -> Value: " + e.getConnection().getValue());
    circluarPlot.getConnections().forEach(connection -> connection.addConnectionEventListener(connectionListener));

    if (null != circluarPlot.getConnection(australia, japan)) {
        circluarPlot.getConnection(australia, japan).setFill(Color.BLUE);
        circluarPlot.getConnection(australia, india).setFill(Color.CHOCOLATE);
        circluarPlot.getConnection(japan, australia).setFill(Color.POWDERBLUE);
    }
    circluarPlot.getConnections().forEach(connection -> {
        System.out.println(connection.getOutgoingItem().getName() + " -> " + connection.getIncomingItem().getName() + " -> Value: " + connection.getValue() + " -> Color: " + connection.getFill());
    });
}

HeatMap: Why ColorMapping enum?

To customize color of heatmap it has property typed as ColorMapping which represented by enum. And it has only method which is getter for JavaFX Built-in javafx.scene.paint.LinearGradient. So why can't you just use LinearGradient-property to set colors in HeatMap? Enums are final so that it is impossible to set custom ColorMapping. Extracting an interface from ColorMapping might be the solution which won't break existing code that much.

Same for AreaHeatMap

CircularPlot and PlotItems

Hello Gerrit,

I have a Question to the CircularPlot and PlotItems.

Example:
I have 10 PlotItems and add those to the CircularPlot.
The CircularPlot gets drawn with these 10 PlotItems.
Now I want to click any PlotItem and trigger the ItemEvent of this specific PlotItem.
This way I could Identify the specific PlotItem.

Is this already possible or is it planned?

Support for empty data points

Image a graph displaying some data from the last X days. Where some data is not available for whatever reason.

It would be great, if we could display a "broken" line etc. indicating the data point is actually missing instead of missing either a day or set the data to a zero value, so the line just drops to the bottom - which is not the same as "there is no data".

I propose to allow to set "empty" data items that specifically exist only to allow the graph to be incomplete.

LineChart items xySeries couldn't be cleared in a simple way

Hello, if i need to clear dots in chart for a while (in case of dynamic charts building via XYSeriesBuilder with empty items and calling clear() on items causes

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:372)
	at java.base/java.util.ArrayList.get(ArrayList.java:459)
	at javafx.base/com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
	at eu.hansolo.fx.charts.XYPane.drawLine(XYPane.java:717)
	at eu.hansolo.fx.charts.XYPane.drawChart(XYPane.java:675)
	at eu.hansolo.fx.charts.XYPane.redraw(XYPane.java:636)
	at eu.hansolo.fx.charts.XYPane.lambda$registerListeners$8(XYPane.java:229)
	at eu.hansolo.fx.charts.series.Series.fireSeriesEvent(Series.java:467)
	at eu.hansolo.fx.charts.series.Series.lambda$new$0(Series.java:134)
	at javafx.base/com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
	at javafx.base/com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
	at javafx.base/javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
	at javafx.base/javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
	at javafx.base/javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
	at javafx.base/javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
	at javafx.base/com.sun.javafx.collections.ObservableListWrapper.clear(ObservableListWrapper.java:157)

is that normal?

Pareto Chart

Do you have any plans to create a Pareto Chart? This is a very common bar chart used in industry to plot the N largest items by count or percentage decreasing left to right. A line chart showing cumulative values is superimposed on the bar chart thus increasing left to right. Clicking on a bar provides an event for "drilling down" into more detail.

request to add candle chart

You are excellent. These charts are very beautiful, but I want to ask if it is possible to add a candle chart, which is the K-line chart of stocks. Thank you!

Suggestion: Helper on axis creation

Hello,

Nice work on the Charts (and JavaFX in general).
Based on your examples, I thought it would be nice to have helpers to create the axis. In each of your test you repeat the functions createABCAxis(....) for which in lot of cases it would be the same function.
I think it would be nice to have these functions directly in the lib.

Thanks

Gradle build problem

Hello,

I'm not too familiar with gradle and this is the first time I've attempted download and check out the charts library. If I'm not mistaken, in order to run the demo (Debian Bullseye), I should:

./gradlew demo

But when doing so, I get the following. Is it enough to help determine the problem? Thanks in advance.

Configure project :
Project : => 'eu.hansolo.fx.charts' Java module

FAILURE: Build failed with an exception.

Where:
Build file '/testdir/charts-17.1.2/build.gradle' line: 149

What went wrong:
A problem occurred evaluating root project 'charts'.
Could not get unknown property 'ossrhUsername' for Credentials [username: null] of type org.gradle.internal.credentials.DefaultPasswordCredentials_Decorated.

CircularPlot: Connection fill Color

Hello Gerrit,

I know I allready asked for this and you implemented it because of me, but I have a slight problem with it.
When I try to change the color of the Connections, it only allows it for max. 1 Connection per PlotItem its coming from.
So if I have 2 Connections going from X to Y and from X to Z, I can only decide the color of one of those.
The other Connection will have the color of the PlotItem.
My wish would be to change the color of all Connections.

It would also be very helpful if the Connection would hold the value it has.
At this moment it only has incoming, outgoing and the color.

Thanks in advance :)

MatrixPane update on new data

I'm trying to use MaxtrixPane for incoming data, so I add new matrixItems in to the ArrayList, but the data won't appear.
This problem is resolving with redrawing matrix with recreating the MatrixPane.
Is it possible to redraw matrix on series change event?

Charts 11.7 - Customization

Hello :)
I rellay like the CoxCombChart, but i see no way of customizing it (or am i wrong?!).

Basically i´d like to change the MouseEvent from MOUSE_PRESSED to MOUSE_ENTERED.
I´d also like to add something to the "...%" text on the ChartItems and change the size and text
on the canvas showing after the MOUSE_PRESSED-Event.

Observations with AxisBuilder / Axis?

When trying to build the following axis:

        xAxisElev = AxisBuilder.create(Orientation.HORIZONTAL, Position.BOTTOM)
                .autoScale(false)
                .type(AxisType.LINEAR)
                .minorTickMarksVisible(false)
                .mediumTickMarksVisible(false)
                .minorTickSpace(5)
                .majorTickSpace(5)
                .tickLabelFontSize(16)
                .title("")
                .build();

I run into various points that I would like to check before trying to change code :-)

  • No matter what I pass as majorTickSpace its always overwritten during redraw() since both calcAutoScale() and calcScale() set minor / major tick space (in my case its always set to 20 after build() and can't be changed afterwards since setMajorTickSpace() is protected).
  • The variables of Axis are not independent of each other, e.g. what happens during redraw() (used in most setXXX methods) depends on autoScale. So I would need to set autoScale first, but AxisBuilder uses a HashMap and not a LinkedHashMap - so I can't influence the order of setting of Axis variables.
  • The above build() triggers redraw() 6 times. Especially for the builder it would be nice to have some "transactional" bracket to call redraw() after all the setXXX have been done?

How to change font for the axis?

Hello @HanSolo ,

I try to change the font for the axis but it's not working for the moment (I've tried through css).
image

.axis .yaxis {
    -fx-font-family: "Arial";
    -fx-font-size: 18px;
}

I could change the size with the setAutoFontSize(false) and setTickLabelFontSize() methods but I would like to change the font also.

Do you have a sample on how to change it for the axis on a simple XYChart ?

Thanks,
Gerald

Canvas alignment with XYChart

I ran into an issue when programming a custom chart based on the code in the XYChart and XYPane classes. It seems that if your chart has a left y and a bottom y axis, then if you remove one the graph canvas shifts to overlap the other. So, removing the y means the bottom of the canvas is the bottom of the x axis, and removing the x means the left of the canvas is the left of the y axis. In addition to this, the canvas seems to be squashed into a smaller area focused around the remaining axis.
Here are examples:
With both
image

With X only
image

With Y only
image

JDK16 Branch

Am i understanding this correctly that the JDK16 branch is a Modular JavaFX while the Master branch is non-Modular. If not, why there is such distinguish?
Thanks,

LineChart - am i dumb?

Hi thereeee,
started using your linechart. Its simple and beautiful.

As i started playing around i couldnt get behind the following:

xAsisBottom.maxValue(13)
image

xAsisBottom.maxValue(5)
image

Questions:
why has every categorie changed to "Jan" when changing maxValue from 13 to 5?
why has maxvalue(13) nut begun at the beginning of the chart but maxvalue(5) did?

xAsisBottom.maxValue(7)
image

Questions:
this is basically what i want, except the fact that theres useless space in the chart because i always want to display just 5 values on the x-asis. why do i need the space in order for the categories to be kinda right?

Explanation for how i got there:
sooo... the thing is, i played around in your test and all i did was only using 1 instead of 3 series and displaying only 5 values on the x asis instead of 13.

the following code is from your LineChartTest but with my changes (i left your original code commented)
at the //TODO might be the problem or my own stupidness, lets find out

`public class LineChartTest extends Application {
private static final Random RND = new Random();
private static final Double AXIS_WIDTH = 25d;
private XYChartItem p1;
private XYChartItem p2;
private XYChartItem p3;
private XYChartItem p4;
private XYChartItem p5;
private XYChartItem p6;
private XYChartItem p7;
private XYChartItem p8;
private XYChartItem p9;
private XYChartItem p10;
private XYChartItem p11;
private XYChartItem p12;
private XYSeries xySeries1;
private XYSeries xySeries2;
private Axis xAxisBottom;
private Axis yAxisLeft;
private XYChart lineChart;
private long lastTimerCalled;
private AnimationTimer timer;

@Override public void init() {
    p1  = new XYChartItem(1, RND.nextDouble() * 300 + 200, "Jan");
    p2  = new XYChartItem(2, RND.nextDouble() * 300 + 200, "Feb");
    p3  = new XYChartItem(3, RND.nextDouble() * 300 + 200, "Mar");
    p4  = new XYChartItem(4, RND.nextDouble() * 300 + 200, "Apr");
    p5  = new XYChartItem(5, RND.nextDouble() * 300 + 200, "May");
    /*
    p6  = new XYChartItem(6, RND.nextDouble() * 300 + 200, "Jun");
    p7  = new XYChartItem(7, RND.nextDouble() * 300 + 200, "Jul");
    p8  = new XYChartItem(8, RND.nextDouble() * 300 + 200, "Aug");
    p9  = new XYChartItem(9, RND.nextDouble() * 300 + 200, "Sep");
    p10 = new XYChartItem(10, RND.nextDouble() * 300 + 200, "Oct");
    p11 = new XYChartItem(11, RND.nextDouble() * 300 + 200, "Nov");
    p12 = new XYChartItem(12, RND.nextDouble() * 300 + 200, "Dec");
     */


    xySeries1 = XYSeriesBuilder.create()
            .items(p1, p2, p3, p4, p5)
            //.items(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)
            .chartType(ChartType.SMOOTH_AREA)
            .fill(Color.web("#00AEF520"))
            .stroke(Color.web("#00AEF5"))
            .symbolFill(Color.web("#00AEF5"))
            .symbolStroke(Color.web("#293C47"))
            .symbolSize(10)
            .strokeWidth(3)
            .symbolsVisible(true)
            .build();

    /*
    xySeries2 = XYSeriesBuilder.create()
            .items(new XYChartItem(1, 280, "Jan"),
                    new XYChartItem(2, 190, "Feb"),
                    new XYChartItem(3, 280, "Mar"),
                    new XYChartItem(4, 300, "Apr"),
                    new XYChartItem(5, 205, "May"),
                    new XYChartItem(6, 430, "Jun"),
                    new XYChartItem(7, 380, "Jul"),
                    new XYChartItem(8, 180, "Aug"),
                    new XYChartItem(9, 300, "Sep"),
                    new XYChartItem(10, 440, "Oct"),
                    new XYChartItem(11, 300, "Nov"),
                    new XYChartItem(12, 390, "Dec"))
            .chartType(ChartType.SMOOTH_AREA)
            .fill(Color.web("#4EE29B20"))
            .stroke(Color.web("#4EE29B"))
            .symbolFill(Color.web("#4EE29B"))
            .symbolStroke(Color.web("#293C47"))
            .symbolSize(10)
            .strokeWidth(3)
            .symbolsVisible(true)
            .build();
     */

    xAxisBottom = AxisBuilder.create(Orientation.HORIZONTAL, Position.BOTTOM)
            .type(AxisType.TEXT)
            .prefHeight(AXIS_WIDTH)
            .categories("Jan", "Feb", "Mar", "Apr", "May")
            //.categories("", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
            .minValue(1)
            //TODO whats wrong here? try maxValue(13), maxValue(5) and maxValue(7)
            .maxValue(7)
            //.maxValue(13)
            .autoScale(true)
            .axisColor(Color.web("#85949B"))
            .tickLabelColor(Color.web("#85949B"))
            .tickMarkColor(Color.web("#85949B"))
            //.tickMarksVisible(false)
            .build();
    AnchorPane.setBottomAnchor(xAxisBottom, 0d);
    AnchorPane.setLeftAnchor(xAxisBottom, AXIS_WIDTH);
    AnchorPane.setRightAnchor(xAxisBottom, AXIS_WIDTH);

    yAxisLeft = AxisBuilder.create(Orientation.VERTICAL, Position.LEFT)
            .type(AxisType.LINEAR)
            .prefWidth(AXIS_WIDTH)
            .minValue(0)
            .maxValue(1000)
            .autoScale(true)
            .axisColor(Color.web("#85949B"))
            .tickLabelColor(Color.web("#85949B"))
            .tickMarkColor(Color.web("#85949B"))
            //.tickMarksVisible(false)
            .build();
    AnchorPane.setTopAnchor(yAxisLeft, 0d);
    AnchorPane.setBottomAnchor(yAxisLeft, AXIS_WIDTH);
    AnchorPane.setLeftAnchor(yAxisLeft, 0d);

    Grid grid = GridBuilder.create(xAxisBottom, yAxisLeft)
            .gridLinePaint(Color.web("#384C57"))
            .minorHGridLinesVisible(false)
            .mediumHGridLinesVisible(false)
            .minorVGridLinesVisible(false)
            .mediumVGridLinesVisible(false)
            .gridLineDashes(4, 4)
            .build();

    XYPane lineChartPane = new XYPane(xySeries1);
    //XYPane lineChartPane = new XYPane(xySeries1, xySeries2);

    lineChart = new XYChart<>(lineChartPane, grid, yAxisLeft, xAxisBottom);

    /*
    lastTimerCalled = System.nanoTime();
    timer = new AnimationTimer() {
        @Override public void handle(final long now) {
            if (now > lastTimerCalled + 2_000_000_000l) {
                p1.setY(RND.nextDouble() * 300 + 200);
                p2.setY(RND.nextDouble() * 300 + 200);
                p3.setY(RND.nextDouble() * 300 + 200);
                p4.setY(RND.nextDouble() * 300 + 200);
                p5.setY(RND.nextDouble() * 300 + 200);
                p6.setY(RND.nextDouble() * 300 + 200);
                p7.setY(RND.nextDouble() * 300 + 200);
                p8.setY(RND.nextDouble() * 300 + 200);
                p9.setY(RND.nextDouble() * 300 + 200);
                p10.setY(RND.nextDouble() * 300 + 200);
                p11.setY(RND.nextDouble() * 300 + 200);
                p12.setY(RND.nextDouble() * 300 + 200);
                lastTimerCalled = now;
            }
        }
    };
     */
}

@Override public void start(Stage stage) {
    StackPane pane = new StackPane(lineChart);
    pane.setPadding(new Insets(10));
    pane.setBackground(new Background(new BackgroundFill(Color.web("#293C47"), CornerRadii.EMPTY, Insets.EMPTY)));

    Scene scene = new Scene(pane);

    stage.setTitle("Line Chart");
    stage.setScene(scene);
    stage.show();

    //lineChart.getXYPane().getListOfSeries().add(createSeries());

    //timer.start();
}

@Override public void stop() {
    System.exit(0);
}

private XYSeries createSeries() {
    XYSeries xySeries = XYSeriesBuilder.create()
            .items(new XYChartItem(1, 600, "Jan"),
                    new XYChartItem(2, 760, "Feb"),
                    new XYChartItem(3, 585, "Mar"),
                    new XYChartItem(4, 410, "Apr"),
                    new XYChartItem(5, 605, "May"),
                    new XYChartItem(6, 825, "Jun"),
                    new XYChartItem(7, 595, "Jul"),
                    new XYChartItem(8, 300, "Aug"),
                    new XYChartItem(9, 515, "Sep"),
                    new XYChartItem(10, 780, "Oct"),
                    new XYChartItem(11, 570, "Nov"),
                    new XYChartItem(12, 620, "Dec"))
            .chartType(ChartType.SMOOTH_AREA)
            .fill(Color.web("#AE00F520"))
            .stroke(Color.web("#AE00F5"))
            .symbolFill(Color.web("#AE00F5"))
            .symbolStroke(Color.web("#293C47"))
            .symbolSize(10)
            .strokeWidth(3)
            .symbolsVisible(true)
            .build();
    return xySeries;
}

private Axis createLeftYAxis(final double MIN, final double MAX, final boolean AUTO_SCALE, final double AXIS_WIDTH) {
    Axis axis = new Axis(Orientation.VERTICAL, Position.LEFT);
    axis.setMinValue(MIN);
    axis.setMaxValue(MAX);
    axis.setPrefWidth(AXIS_WIDTH);
    axis.setAutoScale(AUTO_SCALE);

    AnchorPane.setTopAnchor(axis, 0d);
    AnchorPane.setBottomAnchor(axis, AXIS_WIDTH);
    AnchorPane.setLeftAnchor(axis, 0d);

    return axis;
}
private Axis createCenterYAxis(final double MIN, final double MAX, final boolean AUTO_SCALE, final double AXIS_WIDTH) {
    Axis axis = new Axis(Orientation.VERTICAL, Position.CENTER);
    axis.setMinValue(MIN);
    axis.setMaxValue(MAX);
    axis.setPrefWidth(AXIS_WIDTH);
    axis.setAutoScale(AUTO_SCALE);

    AnchorPane.setTopAnchor(axis, 0d);
    AnchorPane.setBottomAnchor(axis, AXIS_WIDTH);
    AnchorPane.setLeftAnchor(axis, axis.getZeroPosition());

    return axis;
}
private Axis createRightYAxis(final double MIN, final double MAX, final boolean AUTO_SCALE, final double AXIS_WIDTH) {
    Axis axis = new Axis(Orientation.VERTICAL, Position.RIGHT);
    axis.setMinValue(MIN);
    axis.setMaxValue(MAX);
    axis.setPrefWidth(AXIS_WIDTH);
    axis.setAutoScale(AUTO_SCALE);

    AnchorPane.setRightAnchor(axis, 0d);
    AnchorPane.setTopAnchor(axis, 0d);
    AnchorPane.setBottomAnchor(axis, AXIS_WIDTH);

    return axis;
}

private Axis createBottomXAxis(final double MIN, final double MAX, final boolean AUTO_SCALE, final double AXIS_WIDTH) {
    Axis axis = new Axis(Orientation.HORIZONTAL, Position.BOTTOM);
    axis.setMinValue(MIN);
    axis.setMaxValue(MAX);
    axis.setPrefHeight(AXIS_WIDTH);
    axis.setAutoScale(AUTO_SCALE);

    AnchorPane.setBottomAnchor(axis, 0d);
    AnchorPane.setLeftAnchor(axis, AXIS_WIDTH);
    AnchorPane.setRightAnchor(axis, AXIS_WIDTH);

    return axis;
}
private Axis createCenterXAxis(final double MIN, final double MAX, final boolean AUTO_SCALE, final double AXIS_WIDTH) {
    Axis axis = new Axis(Orientation.HORIZONTAL, Position.CENTER);
    axis.setMinValue(MIN);
    axis.setMaxValue(MAX);
    axis.setPrefHeight(AXIS_WIDTH);
    axis.setAutoScale(AUTO_SCALE);

    AnchorPane.setBottomAnchor(axis, axis.getZeroPosition());
    AnchorPane.setLeftAnchor(axis, AXIS_WIDTH);
    AnchorPane.setRightAnchor(axis, AXIS_WIDTH);

    return axis;
}
private Axis createTopXAxis(final double MIN, final double MAX, final boolean AUTO_SCALE, final double AXIS_WIDTH) {
    Axis axis = new Axis(Orientation.HORIZONTAL, Position.TOP);
    axis.setMinValue(MIN);
    axis.setMaxValue(MAX);
    axis.setPrefHeight(AXIS_WIDTH);
    axis.setAutoScale(AUTO_SCALE);

    AnchorPane.setTopAnchor(axis, AXIS_WIDTH);
    AnchorPane.setLeftAnchor(axis, AXIS_WIDTH);
    AnchorPane.setRightAnchor(axis, AXIS_WIDTH);

    return axis;
}

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

}`

Trouble understandig the usage

Hi first of all great work!
I am not too familiar with Java9 modules, but if eu.hansolo.fx.charts.data is not exported how can one create the necessary data-structure (e.g. a tree with TreeNode and ChartData) required for the chart (e.g. SunburstBuilder.setTree)?

CircularPlot.getConnections() isEmpty() when from.addToOutgoing(to, ...) is done after CircularPlotBuilder.create()

Hi Gerrit,
i got the following problem ....

CircularPlot.getConnections() isEmpty() when from.addToOutgoing(to, ...) is done after CircularPlotBuilder.create()

There seams to be a dependency in order of method calls, see validateData().
Its very surprising that allthougt the appearance on screen ist totally fine, there is an empty conenctions list.

This all is upcoming only, because Connections are only internal in CircularPlot.

Another previous mistake was to create Connections outside the plot and using them.
Everything seems ok, the appearance on screen ist totally fine, but i never got the idea that these are totally unused.
I only wondered why i could not get any ConnectionEvent.

IMO it would be great to have Interfaces for PlotItem(NODE) and Connection(EDGE) in order to add own Properties
or even to use existing Graph Structures to implement PlotItem and Connection Interface for Charts.

But thanks for your work,
great FX framework!!

Change min/max Axis Values on XYChart dynamically?

First of all thanks for the library! Speed improvements against the standard implementation are great.

I would like to replace a chart that I have where the user can change the min/max X/Y Axis values by dragging, zooming, ... So far I have not found any way to do that with this XYChart. As far as I can see its using a method private void adjustChartRange() that is using the axis values once during init to set the XYPanes bounds.

I will start fiddling around in the code now but would like to ask in parallel:

  • Are there any reason why this isn't binding the panes bounds to the axis min/max values to update automatically?
  • Alternatively: Would be calling adjustChartRange() repeatedly break anything?

Zoom support

Are there any plans to support zooming with mouse? I know this can be very complex in detail but probably it can be extended in steps?
I have an idea to realize this with a zoom-able data filter, do you think this could be a working approach?

Choose fonts and color for the description of PlotItems in a Circular chart

Hello Gerrit,

Is it possible to choose the color and/or the font for the description of the PlotItems in a Circular chart?
Here is an example:
Example
I would like to choose color and font for the names (Australia, India, China, etc...) as well as for the Tick marks and Tick mark labels.

Is there currently a way to do this?

Next Release

Hello Gerrit,

I would like to know when the next Release for the Charts Library is planned.

Thanks in advance

Update Problem with Maven

Hello Gerrit,

with the new Release there is a Problem with the download via Maven Update.
Files
I and others that I asked can only download the .lastUpdated Files.
From what I can tell that means that the download was unsuccessful.

Maybe you know how to solve this problem.

Box-plot request

Hi,

Thanks a lot for your contribution to charts with JavaFX. It would be great if boxplot is added to this repertoire (unless it is already there and I missed it somehow).

Regards,
gunjanthesystem

Parallel coordinates performance

I tested the parallel coordinates charts, I really like it 👍
However as soon as the data gets bigger the performance drops quickly. On my machine, more than 500 samples take several seconds to refresh.

I changed the way drawConnections works, by using Lines instead of Paths and it greatly improved the performance. Plotting 100000 samples with Lines takes roughly the same time as plotting 500 samples with Paths.

I'll submit a pull request with this change.

LocalDate and LocalDateTime Axis types

Hey Gerrit,

There doesn't seem to be any good LocalDate and LocalDateTime axis types. Would this be something that's in scope for this library?

I'm coming across this need a lot as I play with your charts and JavaFX charts in general.

Thomas Nield

eu.hansolo.fx:charts:17.1.21 no longer found in maven central?

Hi,

I have added eu.hansolo.fx:charts:17.1.21 just a few days ago in my build.gradle and it worked fine. But when I'm checking maven now, there are no more versions 17.* available and the only one is 11.0? E.g. heatmap is still there in versions 17.0.

Maybe its just too late for me today...

Flow Circle

No pressure Gerrit, I showed my coworkers some of your work. One of them has asked if creating a flow circle graph is doable. This is something that would be really killer for connection-driven flow problems (e.g. transportation, trade economics, etc).

What do you think?

image

Add a PolarChart

Add a PolarChart, like the one that comes with JFreeChart.
You mentioned on Twitter that you already had one you could add.

Add ability to be used in Scenebuilder

These are great charts (and of course, thank you very much for your effort), is it possible to add whatever is required to use these in FXML layouts / Scenebuilder

Bugs and improvements for the SunburstChart

Bug in SunburstChart:

Occurs if there is only one node in the first-level (below root) whose value is != 0.
Effect: Segment missing (if interactive). Segment to big(if not interactive and no further child nodes != 0)
Currently, whole circles cannot be drawn because (in this instance) x2 and x3 are equal in createSegment. I guess this happens because startAngleRad == 0 and endAngleRad == 2pi, but sin(0) = 0 ==sin(2pi)

Further improvements:

  • only redraw on TreeNodeEvents if the type is not SELECTED
  • currently the chart is drawn 9 times for the default example, because after every attribute change an event-handler is triggered. This could be avoided by some extra code in the builder class
  • register listener for the node values and redraw on change
    • something like: tree.stream().forEach(tTreeNode -> tTreeNode.getItem().valueProperty().addListener((observable -> redraw())));
  • let users decide what tooltip to display on segments

Add a Parallel Coordinates Plot

I've got a crippling need for a Parallel Coordinates plot on our JavaFX/TornadoFX desktop application.

Parallel Coordinates Plots (PCPs) are a very simple abstraction on a standard many-column matrix. A PCP graphs each row in the table as a horizontal line across the chart. Each column is represented as a vertical axies, and where that axis intersects each horizontal line, the height of the intersection from the bottom fo the chart is proportional to that rows value at that column.

A picture is worth a thousand words:

Our applications Parallel Coordinates chart:
image

The corresponding Matrix:
image

a D3JS implementation:
https://bl.ocks.org/jasondavies/1341281

Parallel Coordintes represents a superbly general chart as it allows you to graphically represent data at arbitrarily high dimensionality.

There is a long list of features such a chart might have, which I'll outline below.

Our implementation is not worth sharing primarily because its use of bindings is inefficient abusive. We write an optimization algorithm which can redline the CPU for prolonged periods of time, but in many cases our profiling has indicated that the actual problematic hot loop is binding updates for our PCP implementation. Thus we would very much like another one, but we simply cant afford the time it would take to re-write it.


shameless plug: find out more about this product at empowerops.com

SelectionEvent support for SankeyPlot

Hi Gerrit!

Could you please implement a SelectionEvent for the SankeyPlot chart (like you've done for the ArcChart) so that when the user clicks a on the chart connections (or endpoints) then the event would contain the in/out connection ?

Best regards and keep up the great work !
Carstein

NoSuchMethodException when adding dependency to POM

Note: NO code was added, this issue occurs when adding the dependency to the POM.

After adding the dependency

<dependency>
    <groupId>eu.hansolo.fx</groupId>
    <artifactId>charts</artifactId>
    <version>11.3</version>
    <type>pom</type>
</dependency>

to the POM the application fails to start.

Immediately upon start-up (even before spring kicks in) the following exception is thrown:

java.lang.NoSuchMethodError: 'com.sun.javafx.geom.transform.GeneralTransform3D com.sun.prism.d3d.D3DContext.getPerspectiveTransformNoClone()'
	at com.sun.prism.d3d.D3DContext.updateShaderTransform(D3DContext.java:290)
	at com.sun.prism.impl.ps.BaseShaderContext.checkState(BaseShaderContext.java:662)
	at com.sun.prism.impl.ps.BaseShaderContext.validateTextureOp(BaseShaderContext.java:583)
	at com.sun.prism.impl.ps.BaseShaderContext.validateTextureOp(BaseShaderContext.java:500)
	at com.sun.prism.impl.BaseGraphics.drawTexture(BaseGraphics.java:426)
	at com.sun.prism.impl.ps.BaseShaderGraphics.drawTexture(BaseShaderGraphics.java:139)
	at com.sun.javafx.sg.prism.NGImageView.renderContent(NGImageView.java:123)
	at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
	at com.sun.javafx.sg.prism.NGImageView.doRender(NGImageView.java:103)
	at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
	at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
	at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:578)
	at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
	at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
	at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:479)
	at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:328)
	at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
	at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
	at java.base/java.lang.Thread.run(Thread.java:832)

Once the application has loaded a StackOverflowException is eventually thrown as the above is recursively thrown.

Usage Instructions

Hi To the HanSolo Charts Developers,

I am interested experiment with your library of plots the polar and the radar plots in particular. I am quite new to Java. I tried to best to update my Java development environment to OpenJDK16 with javaFX-sdk-16. Latest Eclipse Oomph and grade 7.1.1 to try to run the radar chart test application. I messed with with on the fly when running into problems and trying to solve it by googling.

Had spent ~1 day on it without any luck to get the test application working. I am at a point where at least entire project is imported into Eclipse and the the radar test application is no longer showing a bunch of red lines. When run, I encountered below error:

WARNING: Unknown module: charts specified to --patch-module
Error: Could not find or load main class eu.hansolo.fx.charts.RadarChartTest
Caused by: java.lang.ClassNotFoundException: eu.hansolo.fx.charts.RadarChartTest

Also tried googling for a solution but I got no where so far.

Your vast supported plots are so valuable for the scientific community. I am wondering if there is any documentation to guide one to at least get pass the setting up of development environment (the basic toolchain required to run/develop with your library) so one can develop their FX app to consume your library.

Any help would be greatly appreciated in this regards,
Thanks,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.