I am trying to implement grouped MPAndroid Bar chart. I have a group of 2 datasets that i want to display. The problem is that the xaxis values are not center aligned with the bar chart (as per the screenshot). I checked other questions as well and implemented the following answers provided.
I want to make the labels center aligned with the grouped bars.
float barSpace = 0.02f;
float groupSpace = 0.3f;
int groupCount = 2;
data.setBarWidth(0.155f);
pvaAmount_chart.getXAxis().setAxisMinimum(0);
pvaAmount_chart.getXAxis().setAxisMaximum(0 + pvaAmount_chart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount);
pvaAmount_chart.groupBars(0, groupSpace, barSpace);
pvaAmount_chart.getXAxis().setCenterAxisLabels(true);
pvaAmount_chart.notifyDataSetChanged();
When entering groupcount=2 as 2 types of bars:
When entering groupcount=4 number of grouped charts:
i'm doing it like this :
String [] values = new String[insert the lenght of your array]
for (int blabla=0;i<values[lenght];blabla++){
String dayOfTheWeek = dateFormat.format(mydate);
vales[blabla] = dayOfTheWeek //in my case
}
xAxis.setGranularity(1.0f); //
xAxis.setCenterAxisLabels(false);
xAxis.setGranularityEnabled(true);
xAxis.setLabelCount(values.length,false); //
List<String> stringList = new ArrayList<String>(Arrays.asList(values));
xAxis.setGranularityEnabled(true);
xAxis.setLabelCount(values.length,false); //
xAxis.setValueFormatter(new IndexAxisValueFormatter(getXAxisValues((ArrayList<String>) stringList)));
i'm using : 'com.github.PhilJay:MPAndroidChart:v3.1.0'
Related
My current java code generates a stacked-bar chart using Apache POI 4.0.1 as shown in following diagram.
I don't want to print a line for future dates (for example: In following chart, I don't want those zeros from 04/04 date); but I want those dates below X-axis.
My question is how to remove/disable line drawing for Zero ?
Code sample
// line chart
// axis must be there but must not be visible
bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setVisible(false);
leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setVisible(false);
// set correct cross axis
bottomAxis.crossAxis(leftAxis);
leftAxis.crossAxis(bottomAxis);
data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFLineChartData.Series series4 = (XDDFLineChartData.Series)data.addSeries(date, category);
series4.setTitle("Total", null);
series4.setSmooth(false);
series4.setMarkerStyle(MarkerStyle.STAR);
chart.plot(data);
// correct the id and order, must not start 0 again because there are three bar series already
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getIdx().setVal(3);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getOrder().setVal(3);
solidLineSeries(data, 0, PresetColor.YELLOW);
// add data labels
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).addNewDLbls();
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls()
.addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(new byte[]{(byte)255,(byte)255,0});
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls()
.addNewDLblPos().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos.CTR);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowVal().setVal(true);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowLegendKey().setVal(false);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowCatName().setVal(false);
chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowSerName().setVal(false);
First you've to write following lines of code before chart.plot(data);.
This will set blank values as gaps in the chart so you can accurately plot data series of different lengths
CTDispBlanksAs disp = CTDispBlanksAs.Factory.newInstance();
disp.setVal(STDispBlanksAs.GAP);
chart.getCTChart().setDispBlanksAs(disp);
Imports
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDispBlanksAs;
import org.openxmlformats.schemas.drawingml.x2006.chart.STDispBlanksAs;
Then after Drawing code and outside loop, write a code to set those zeros as BLANK.
int rownum = 0;
// loop start
Row rowT = sheetTestcasenBurndown.getRow(rownum);
for (int cellnumStart = 1; cellnumStart <= cellnumEnd; cellnumStart++) {
Cell cell = rowT.getCell(cellnumStart);
cell.setCellType(CellType.BLANK);
}
// loop end
rownum++;
Output
I have tried the following with the default renderer
CategorySeries series = new CategorySeries("First test");
int numSlide = portions.length;
for (int i = 0; i < numSlide; i++){
series.add(seriesNames[i]+" ("+portions[i]+" %)", portions[i]);
}
DefaultRenderer defaultRenderer = new DefaultRenderer();
SimpleSeriesRenderer simpleSeriesRenderer = null;
for (int i = 0; i < numSlide; i++){
simpleSeriesRenderer = new SimpleSeriesRenderer();
simpleSeriesRenderer.setColor(colors[i]);
simpleSeriesRenderer.setChartValuesFormat(new DecimalFormat("###,###,##0.0"));
defaultRenderer.addSeriesRenderer(simpleSeriesRenderer);
}
defaultRenderer.setInScroll(true);
defaultRenderer.setZoomButtonsVisible(false);
defaultRenderer.setZoomEnabled(true);
defaultRenderer.setLabelsTextSize(18); //value size
defaultRenderer.setLabelsColor(R.color.primary_dark);
defaultRenderer.setShowLegend(false);
defaultRenderer.setClickEnabled(true);
defaultRenderer.setPanEnabled(true);
defaultRenderer.setShowLabels(true);
defaultRenderer.setShowLegend(true);
//return the pie chart view
return ChartFactory.getPieChartView(context, series, defaultRenderer);
Now the above produces
What am looking forward to get is to have the percentage values eg: 2% inside the chart area something which looks like this
How do i get the percentage values to be displayed inside the charts?
You want to display values and hide labels. Do that like so in your renderer:
defaultRenderer.setShowLabels(false);
defaultRenderer.setDisplayValues(true);
Also, your series names should probably not contain the values, so change the following line
series.add(seriesNames[i]+" ("+portions[i]+" %)", portions[i]);
to
series.add(seriesNames[i], portions[i]);
I have to implement an histogram using JFreeChart API. This histogram has to represent the datas of this JTable:
So I have a JTable with three columns: "thea", "type", "Number of occurrences". My histogram has two targets: the first is to count the number of occurrences of each thea field; the second is to mark with different colors the bars corresponding to JTable records with different types.
To implement my histogram I used a DefaultCategoryDataset:
private DefaultCategoryDataset createDataset(ArrayList<String>fieldsOccs) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for(int i = 0; i<this.fieldsOccs.size() && i<end; i++) {
String thea = fieldsOccs.get(i).getFieldName();
String type = fieldsOccs.get(i).getType();
int occurrences = fieldsOccs.get(i).getOccurrences();
dataset.setValue(occurrences, type, thea);
}
return dataset;
}
Anf then I create my chart using a createChart method:
private JFreeChart createChart(DefaultCategoryDataset dataset) {
JFreeChart chart = ChartFactory.createBarChart(
"",
"", //X-axis title
"", //Y-axis title
dataset, //dataset
PlotOrientation.HORIZONTAL, //plot orientation
true, //show legends
true, //use tooltips
false //generate URLs
);
return chart;
}
This is what I get:
As you can see in the picture it is not nice to see. The values on x axes are not formatted correctly.
How can I solve this rendering problem?
--edit
I have this problem just in case of more types in the JTable. For example if my JTable is:
and there is just String, the correspondig histogram is nice:
--edit1
What dou you think about StackedBarChart3D? I get this output:
My histogram has two targets:
You may get a more appealing result with ChartFactory.createHistogram() and a SimpleHistogramDataset, seen here.
To get diverse colors, override the getItemPaint() method in a custom XYBarRenderer, as suggested here.
I'm trying to make a simple 3-column TableView:
One icon column containing a fixed size icon. This column must not be resizable, and must have a fixed size.
One text column with a predefined prefered size, which can be resized if needed.
One last column taking all available space.
Unfortunatly, this simple use case seems to be really complicated with Java FX 8. I tried the following, which should work according to my understanding of the documentation:
TableColumn<DebuggerItem, ImageView> iconColumn = new TableColumn<>("ICON");
TableColumn<DebuggerItem, String> typeColumn = new TableColumn<>("TEXT");
TableColumn<DebuggerItem, String> textColumn = new TableColumn<>("DATA");
setColumnResizePolicy(CONSTRAINED_RESIZE_POLICY);
// Fixed size column
iconColumn.setPrefWidth(40);
iconColumn.setMinWidth(40);
iconColumn.setMaxWidth(40);
iconColumn.setResizable(false);
// Predefined preferred size of 100px
typeColumn.setPrefWidth(100);
getColumns().addAll(iconColumn, typeColumn, textColumn);
This results in the following TableView:
We can see that if the first column has a correct size, the second and the hird have the same size, which is not what I expected. The second column should be 100px wide, and the last one take the rest of the space.
What did I miss ?
According to #kleopatra link, the solution is to use properties to compute last column width, and NOT use CONSTRAINED_RESIZE_POLICY :
LastColumnWidth = TableViewWidth - SUM(Other Columns Widths)
Which, according to my example give the following Java code:
TableColumn<DebuggerItem, ImageView> iconColumn = new TableColumn<>("ICON");
TableColumn<DebuggerItem, String> typeColumn = new TableColumn<>("TEXT");
TableColumn<DebuggerItem, String> textColumn = new TableColumn<>("DATA");
// Fixed size column
iconColumn.setPrefWidth(40);
iconColumn.setMinWidth(40);
iconColumn.setMaxWidth(40);
iconColumn.setResizable(false);
// Predefined preferred size of 100px
typeColumn.setPrefWidth(100);
// Automatic width for last column
textColumn.prefWidthProperty().bind(
widthProperty().subtract(
iconColumn.widthProperty()).subtract(
typeColumn.widthProperty()).subtract(2)
);
getColumns().addAll(iconColumn, typeColumn, textColumn);
Please note that we need to substract 2 pixels to get the exact width, it's not clear why.
I created a more general solution, that pixel-perfectly calculates width of last column for TableViews that:
have any number of columns
possibly hide or show columns at runtime
possibly have custom insets
possibly have scrollbar, possibly showing and hiding at runtime.
Usage:
bindLastColumnWidth(tableView);
Source:
public static <T> void bindLastColumnWidth (TableView<T> tableView) {
List<TableColumn<T,?>> columns = tableView.getColumns();
List<TableColumn<T,?>> columnsWithoutLast = columns.subList(0, columns.size() - 1);
TableColumn lastColumn = columns.get(columns.size() - 1);
NumberExpression expression = tableView.widthProperty();
Insets insets = tableView.getInsets();
expression = expression.subtract(insets.getLeft() + insets.getRight());
for (TableColumn column : columnsWithoutLast) {
NumberExpression columnWidth = Bindings.when(column.visibleProperty())
.then(column.widthProperty())
.otherwise(0);
expression = expression.subtract(columnWidth);
}
ScrollBar verticalScrollBar = getScrollBar(tableView, Orientation.VERTICAL);
if (verticalScrollBar != null) {
NumberExpression scrollBarWidth = Bindings.when(verticalScrollBar.visibleProperty())
.then(verticalScrollBar.widthProperty())
.otherwise(0);
expression = expression.subtract(scrollBarWidth);
}
expression = Bindings.max(lastColumn.getPrefWidth(), expression);
lastColumn.prefWidthProperty().bind(expression);
}
private static ScrollBar getScrollBar (Node control, Orientation orientation) {
for (Node node : control.lookupAll(".scroll-bar")) {
if (node instanceof ScrollBar) {
ScrollBar scrollBar = (ScrollBar)node;
if (scrollBar.getOrientation().equals(orientation)) {
return scrollBar;
}
}
}
return null;
}
You can call this below code after you add all columns to table.
This is nice when the code that resizes does not have a explicit list of columns.
public static void makeLastColumnGrow(TableView<?> items) {
var last = items.getColumns().get(items.getColumns().size() - 1);
var aBinding = Bindings.createDoubleBinding(() ->{
double width = items.getWidth();
for (int i = 0; i < items.getColumns().size() - 1 ; i++) {
width = width - items.getColumns().get(i).getWidth();
}
return width - 2; // minus -2 to account for border i think
}, items.widthProperty());
last.prefWidthProperty().bind(aBinding);
}
I have a table in libgdx which is supposed to have 6 buttons, organised into 2 rows. Here's my code:
elementsTable.clear();
String[] colors = new String [6];
colors[0] = "red";
colors[1] = "orange";
colors[2] = "yellow";
colors[3] = "purple";
colors[4] = "blue";
colors[5] = "green";
String category = currentCategory.name();
category = category.substring(0, category.length()-1).toLowerCase(); //removes the last character because otherwise there would be an extra 's'
int count = 0;
for(String color : colors) {
ButtonStyle buttonStyle = new ButtonStyle();
buttonStyle.up = cellsSkin.getDrawable(category + "_" + color);
Button button = new Button(buttonStyle);
button.addListener(toolBoxListener);
button.setName(category + "_" + color);
button.setSize(toolBoxButtonSize, toolBoxButtonSize);
elementsTable.add(button).pad(toolBoxButtonPadding);
count ++;
if (count == Math.ceil((colors.length/2d))) elementsTable.row();
}
That's the filling. My buttons are of 6 different colors so I loop over the array with the color names to access the skin to get the drawable for the buttons. This part seems to work because when I debug and look at the table, it has the 6 buttons in there with the right size.
Then I set the position and size of my table and add it to the stage.:
elementsTable.setSize(toolBoxWidth, 500/(float)(3*toolBoxButtonSize+6*toolBoxButtonPadding)*elementsTable.getHeight());
elementsTable.setPosition(195, 30);
stage.addActor(elementsTable);
The stage has an orthographic camera set that should scale things down just fine.
However, what I get is this:
Another strange thin is that when I look at the table's height and width in debug mode, it says 0 even thoug there are elements in it that all have the corrct size.
Can anyone help me?
If you have any further questions on the problem, please ask! I tried to give a detailed description, but I am happy to answer your questions.
It seemsits just the position. 30 is too low for the Y:
elementsTable.setPosition(195, 30);
Try 150 for example:
elementsTable.setPosition(195, 150);
Remember the coordinate system that Libgdx (and OpenGL) use is with Y going up.