How to decrease the size of horizontal bar at report? - jasper-reports

I'm creating a Jasper report with horizontal bar, and I have a problem with one of my bars from the chart; the last one is very much bigger than the others, and it is cutting in half of the value of the label.
How can I adjust to not surpass a specific value of the chart?

Thanks #trashgod for your help, with the setUpperMargin() method it worked to decrease the size of the horizontal bar.
To anyone with the same problem as I was having, my code to fix it is below:
public void customize(JFreeChart chart, JRChart jasperChart) {
NumberAxis numAxis = (NumberAxis) chart.getCategoryPlot().getRangeAxis();
numAxis.setUpperMargin(0.25);
}
Documentation:
ValueAxis - JFreeChart

Related

Growing menu with scrollbar

I hate to ask such a generic question but I'm really stuck and super hoping someone can help me along the way. Here is the situation:
I'm making the GUI for a mobile app, portrait mode. I'm using canvas scalers to scale my canvasses with a reference width of 1080. This means I effectively don't know the height of my screen space.
What I want to create is a menu with a variable amount of items. The menu must be anchored to the bottom (with an offset margin) and grow upwards. So far I've been able to manage this using VerticalLayoutGroup and anchoring the rect transform to the bottom.
But my last requirement is that if the content would grow too big, a scrollbar would appear. The definition of the content being too big is: if it would extend the (unknown) screen height ( minus the offset margin of course). I hope the following image illustrates this much clearer:
I have a unity project here: https://ufile.io/v31br
Did you give a try to scrollView? here it is: https://unity3d.com/learn/tutorials/topics/user-interface-ui/scroll-view
You can use your vertical layout inside it and you will probably want to deactivate horizontal scroll and delete the horizontal slider.
Via script you can check its rectTransform height and compare it to your container's size, when reached maxHeight you can start managing your item's sizes
I assume you use the ScrollRect component as it is the right component to use in your case.
You can check the screen height with the Screen.height property.
Once you know the screen height you can compare it with your rect height and toggle the scrollbar with the ScrollRect.vertical property. You may have to change the ScrollRect.verticalScrollbarVisibility to permanent in order to make it work for you.
The answer Dave posted was close, but the problem is that the scrollview doesn't expand. I fixed it eventually by stretching the scrollview and resizing the parent manually as items are added. I set the anchors to the maximum size and adjust the sizeDelta.
public class MenuScript : MonoBehaviour
{
public int MenuItemCount;
public GameObject MenuItemPrefab;
public Transform MenuItemParent;
private RectTransform _rectTransform;
void Start()
{
_rectTransform = GetComponent<RectTransform>();
for (var i = 0; i <= MenuItemCount; i++)
{
GameObject instance = Instantiate(MenuItemPrefab, MenuItemParent, false);
instance.GetComponent<Text>().text = instance.name = "Item " + i;
float size = instance.transform.GetComponent<RectTransform>().sizeDelta.y;
TryExpandBy(size + 10);
}
}
private void TryExpandBy(float size)
{
var deltaY = _rectTransform.sizeDelta.y + size;
if (deltaY > 0) deltaY = 0;
_rectTransform.sizeDelta = new Vector2(_rectTransform.sizeDelta.x, deltaY);
}
}

javafx: How can I put slider tick labels above its sliding track in horizontal slider?

I am trying to customize the horizontal slider such that its major tick labels appear above sliding track (by default they appear below sliding track) and major tick label values appear in reverse order. Do I need to use CSS somehow to display the labels above sliding track?
So far I have reversed the labels ordering using setLabelFormatter:
final double sliderMax = slider.getMax();
slider.setLabelFormatter(new StringConverter<Double>() {
#Override
public String toString(Double d) {
return String.valueOf((int)(sliderMax - d));
}
#Override
public Double fromString(String str) {
return (sliderMax - Double.parseDouble(str));
}
});
Any pointers will be helpful.
This is certainly possible with CSS.
This will only work for horizontal Slider though. Theoretically there is the pseude CSS class horizontal on the Slider which could be used to restict the CSS to horizontal Sliders, but I was unable to test this, maybe you can make it work.
Check out the CSS-Refrence and inspect your application with ScenicView.

ios-charts Charts for Swift - purposely bleed/overflow chart bars

I'm using a Bar Chart that I'm trying to make look like a design. The design's bars overflow a bit at the bottom and have a transparency gradient on them. I can't find any property that you can use for this and I guess I'll have to override somewhere. I've also tried to draw layers on top of the graph at the bars positions/bounds without success.
I tried overriding the BarChartRenderer and change the Y-positions, but since the graph is supposed to be "scrollable" by default it clips the bar.
I've already disabled the scrolling/moving/zooming functions because I don't need them:
doubleTapToZoomEnabled = false
highlightPerDragEnabled = false
highlightPerTapEnabled = false
clipValuesToContentEnabled = false
You can set the minimum axis value so that it set the bottom line correct try this code as
barChartView.leftAxis.axisMinimum = __Your minimum bar value__ i.e. 17000 //that is mention in your above graph
Solved it by drawing my own layers over the bars and then remove the old bars because of their anti-aliasing. This way it will be easier to implement the gradient too, and it works because you won't be able to move/scale the chart.
let bottomY = self.contentRect.maxY - leftAxis.gridLineWidth
for (_, bar) in self.barData!.dataSets.enumerated() {
let layer = CALayer(),
barBounds = self.getBarBounds(entry: bar.entryForIndex(0)! as! BarChartDataEntry),
// 30 extra height at bottom
frame = CGRect(x: barBounds.minX, y: barBounds.minY, width: barBounds.width, height: (bottomY - barBounds.minY) + 30)
// Set the new frame size, Z position and background
layer.frame = frame
layer.zPosition = 10
layer.backgroundColor = bar.color(atIndex: 0).cgColor
// Add the new bar layer and remove old bar
self.layer.addSublayer(layer)
bar.clear()
}

How to set multiple Renderers on a single XYDataSet in jaspersoft reports customizer for jFreeChart

We have a jfreechart in jaspersoft reports community edition where we want to apply two renderers to the same DataSet. The approach we are currently using is not working as expected.
Our current approach is as follows where we attempt to copy the DataSet from index 0 into index 1 and then set a renderer for each index.
xyplot.setDataset( 1, xyplot.getDataset(0) );
xyplot.setRenderer( 1, XYLineAndShapeRenderer_DashedLines );
xyplot.setRenderer( 0, xYDifferenceRenderer_GrayBand );
We don't get any errors, but the line is not dashed and we do get the gray band but it is not drawn correctly.
However when we comment out one or the other, they work fine on their own.
It kinda feels like the second one overwrites the first one.
Is this the right approach to setting multiple renderers on a single DataSet and if so what are we doing wrong?
Or should a different approach be taken and if so what is it?
For the renderers to work correctly you need 2 different dataset (2:nd needs to be another object in your case a clone not a pointer) and 2 different renderer's (seems that you already have this).
XYDataset xyDataset1 = .... //I'm a dataset
XYDataset xyDataset2 = .... //I'm a another dataset if same values I need to be a clone
//you can't do xyDataset2 = xyDataset1 since like this I become xyDataset1
XYPlot plot = chart.getXYPlot();
plot.setDataset(0, xyDataset1);
plot.setDataset(1, xyDataset2);
XYLineAndShapeRenderer renderer0 = new XYLineAndShapeRenderer();
//do you personalizzation code
XYLineAndShapeRenderer renderer1 = new XYLineAndShapeRenderer();
//do you personalizzation code
plot.setRenderer(0, renderer0);
plot.setRenderer(1, renderer1);
Ok, so here is what finally solved it. I was attempting to use two renderers, one for the grey band and one for the dashed lines, but I only needed to use one.
So the final code ended up being:
package gprCustomizer;
import org.jfree.chart.JFreeChart;
import net.sf.jasperreports.engine.JRChart;
import net.sf.jasperreports.engine.JRChartCustomizer;
import org.jfree.chart.renderer.xy.XYDifferenceRenderer;
import java.awt.BasicStroke;
import org.jfree.chart.plot.XYPlot;
import java.awt.Color;
public class GPRCustomizations implements JRChartCustomizer {
public void customize(JFreeChart chart, JRChart jrChart) {
// Get Plot
XYPlot plot = (XYPlot)chart.getPlot();
// Apply Gray Band Style
XYDifferenceRenderer xYDifRnd_GrayBand = new XYDifferenceRenderer();
xYDifRnd_GrayBand.setNegativePaint(Color.lightGray);
xYDifRnd_GrayBand.setPositivePaint(Color.lightGray);
xYDifRnd_GrayBand.setShapesVisible(false);
xYDifRnd_GrayBand.setRoundXCoordinates(true);
// Apply Dashed Style to Series 0,1
xYDifRnd_GrayBand.setSeriesStroke(0,
new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f
)
);
xYDifRnd_GrayBand.setSeriesStroke(1,
new BasicStroke(
2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f
)
);
plot.setRenderer(xYDifRnd_GrayBand);
// Remove Borders from Legend
if(chart.getLegend() != null)
{
chart.getLegend().setBorder(0.0, 0.0, 0.0, 0.0);
}
}
}
Which produced the expected outcome of the grey band and the dashed lines either side:

JavaFX Charting - CategoryAixis Resize Issue

I have a user-resizable chart. When the chart gets smaller the CategoryAxis rotates and you can no longer see most of the category labels. Here is a gif showing the problem:
Is there any way to stop the labels from rotating?
I know I can add a listener to the rotation property and rotate it back to 0 if the rotation changes. However, when I do that it doesn't prevent the spacing from adjusting, so the labels just get cut off (you only see the last few characters of the label).
Here is the code for the included gif, you'll see the problem as you resize the window:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
public class HorizontalBarExample extends Application {
#Override
public void start(Stage stage) {
NumberAxis xAxis = new NumberAxis();
CategoryAxis yAxis = new CategoryAxis();
BarChart<Number, String> bc = new BarChart<Number, String>(xAxis, yAxis);
bc.setBarGap(0d);
bc.setCategoryGap(0);
xAxis.setTickLabelRotation(90);
yAxis.tickLabelRotationProperty().set(0d);
XYChart.Series<Number, String> series1 = new XYChart.Series<>();
series1.setName("example");
for (int i = 0; i < 10; i++)
series1.getData().add(new XYChart.Data<Number, String>(Math.random() * 5000, "long data label number" + i));
bc.getData().add(series1);
Scene scene = new Scene(bc, 800, 600);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This issue is not easily fixable (IMO).
What's going on
The CategoryAxis code for Java 8u60 internally maintains a private effectiveTickLabelRotation member. This member can at times, due to the internal implementation, override whatever value you set for the publicly available tickLabelRotationProperty. So you don't really have much control over the functionality.
Various (failed) attempts to fix it using public API
One way that it overrides is when the the category axis is set to autoRanging, so you can set autoRanging to false and also manually set the categories using the CategoryAxis::setCategory method. This kind of fixes the issue because then the effectiveRotation is not used when the graph gets small, it respects the rotation you want and the text stays vertical.
However, even with switching auto ranging off and manually setting categories, there are other quirks in the implementation which prevent a reasonable result. The internal layout algorithm for the CategoryAxis still thinks that the category labels have been rotated, so it does not allocate enough space for the labels when the chart gets smaller. The CategoryAxis class is final so the layout logic can't be overridden in a subclass. A quick hack would be set a minimum width for the axis, yAxis.setMinWidth(200);. Unfortunately the CategoryAxis layout algorithm does not respect the min width setting either.
Options to get this functionality
In short, it's all kind of broken ... you either:
Accept the default behavior as is, OR
You log a bug requesting a fix, OR
You copy the CategoryAxis code to a new class, e.g. HorizontallyLabelledCategoryAxis, make some modifications to allow the layout algorithm to work as you wish and use that new class in place of the original CategoryAxis.
Option 3 is a bit tricky, but doable.
Suggested Work-around
All that said, the approach (e.g. work-around) I'd recommend, if it is acceptable for your UI, is simply not to let the chart get small enough that its layout screws up.
VBox chartHolder = new VBox(bc);
VBox.setVgrow(bc, Priority.ALWAYS);
bc.setMinHeight(300);
Scene scene = new Scene(chartHolder, 800, 600);