Overlapping of Multiple IntervalBarRenderer - jfreechart

This example demonstrates how to avoid overlapping multiple bars on dual axis by adding null series at each data set. By following the example I have created four DefaultIntervalCategoryDataset objects, each on its own separate axis (the complete code is given below).
The advantage of adding null series at each data set is visible in the following figure e.g. Series 2 is kept apart from Series 1.
But still, Series 3 is overlapped by Series 4 and that is why Series 3 is hidden (by Series 4). I could not find the reason and get the solution.
How to avoid this ovelapping, also is there any other alternative technique to demonstrate multiple category problem (having intervals as in my problem) in a more efficient and convenient way?
public class IntervalBarChartTest extends ApplicationFrame {
public IntervalBarChartTest(String title) {
super(title);
JPanel chartPanel = createDemoPanel();
chartPanel.setPreferredSize(new Dimension(900, 270));
setContentPane(chartPanel);
}
private static DefaultIntervalCategoryDataset createDataset1() {
Number[] series1_Start = new Number[] {25,50};
Number[] series1_End = new Number[] {50,75};
Number[] dymmy1_Start = new Number[] {null,null};
Number[] dummy1_End = new Number[] {null,null};
Number[][] starts = new Number[][]{series1_Start,dymmy1_Start};
Number[][] ends = new Number[][] {series1_End,dummy1_End};
String[] categoryKeys = {"50th%ile", "90th%ile"};
String[] seriesKeys = {"Series1",""};
DefaultIntervalCategoryDataset dataset= new DefaultIntervalCategoryDataset(seriesKeys,categoryKeys,starts, ends);
return dataset;
}
private static DefaultIntervalCategoryDataset createDataset2() {
Number[] dymmy1_Start = new Number[] {null,null};
Number[] dummy1_End = new Number[] {null,null};
Number[] series2_Start = new Number[] {150,150};
Number[] series2_End = new Number[] {200,200};
Number[] dymmy3_Start = new Number[] {null,null};
Number[] dummy3_End = new Number[] {null,null};
Number[][] starts = new Number[][]{dymmy1_Start,series2_Start,dymmy3_Start};
Number[][] ends = new Number[][] {dummy1_End,series2_End, dummy3_End};
String[] categoryKeys = {"50th%ile", "90th%ile"};
String[] seriesKeys = {"","Series2",""};
DefaultIntervalCategoryDataset dataset= new DefaultIntervalCategoryDataset(starts, ends);
dataset.setSeriesKeys(seriesKeys);
dataset.setCategoryKeys(categoryKeys);
return dataset;
}
private static DefaultIntervalCategoryDataset createDataset3() {
Number[] dymmy1_Start = new Number[] {null,null};
Number[] dummy1_End = new Number[] {null,null};
Number[] series2_Start = new Number[] {150,150};
Number[] series2_End = new Number[] {200,200};
Number[] dymmy2_Start = new Number[] {null,null};
Number[] dummy2_End = new Number[] {null,null};
Number[][] starts = new Number[][]{dymmy1_Start,series2_Start,dymmy2_Start};
Number[][] ends = new Number[][] {dummy1_End,series2_End,dummy2_End};
String[] categoryKeys = {"50th%ile", "90th%ile"};
String[] seriesKeys = {"","Series3",""};
DefaultIntervalCategoryDataset dataset= new DefaultIntervalCategoryDataset(starts, ends);
dataset.setSeriesKeys(seriesKeys);
dataset.setCategoryKeys(categoryKeys);
return dataset;
}
private static DefaultIntervalCategoryDataset createDataset4() {
Number[] dymmy1_Start = new Number[] {null,null};
Number[] dummy1_End = new Number[] {null,null};
Number[] series2_Start = new Number[] {50,50};
Number[] series2_End = new Number[] {100,100};
Number[][] starts = new Number[][]{dymmy1_Start,series2_Start};
Number[][] ends = new Number[][] {dummy1_End,series2_End, };
String[] categoryKeys = {"50th%ile", "90th%ile"};
String[] seriesKeys = {"","Series4"};
DefaultIntervalCategoryDataset dataset= new DefaultIntervalCategoryDataset(starts, ends);
dataset.setSeriesKeys(seriesKeys);
dataset.setCategoryKeys(categoryKeys);
return dataset;
}
private static JFreeChart createChart(CategoryDataset dataset1, CategoryDataset dataset2, CategoryDataset dataset3,CategoryDataset dataset4) {
CategoryAxis domainAxis = new CategoryAxis("Percentiles");
NumberAxis rangeAxis = new NumberAxis("ms1");
IntervalBarRenderer renderer = new IntervalBarRenderer();
rendererSettings(renderer);
//CategoryPlot plot = new CategoryPlot(dataset1, domainAxis, rangeAxis,renderer);
final CategoryPlot plot = new CategoryPlot(dataset1, domainAxis, rangeAxis, renderer) {
/**
* Override the getLegendItems() method to handle special case.
*
* #return the legend items.
*/
public LegendItemCollection getLegendItems() {
final LegendItemCollection result = new LegendItemCollection();
final CategoryDataset data = getDataset();
if (data != null) {
final CategoryItemRenderer r = getRenderer();
if (r != null) {
final LegendItem item = r.getLegendItem(0, 0);
result.add(item);
}
}
// the JDK 1.2.2 compiler complained about the name of this
// variable
final CategoryDataset dset2 = getDataset(1);
if (dset2 != null) {
final CategoryItemRenderer renderer2 = getRenderer(1);
if (renderer2 != null) {
final LegendItem item = renderer2.getLegendItem(1, 1);
result.add(item);
}
}
final CategoryDataset dset3 = getDataset(2);
if (dset3 != null) {
final CategoryItemRenderer renderer2 = getRenderer(2);
if (renderer2 != null) {
final LegendItem item = renderer2.getLegendItem(2, 1);
result.add(item);
}
}
final CategoryDataset dset4 = getDataset(3);
if (dset4 != null) {
final CategoryItemRenderer renderer2 = getRenderer(3);
if (renderer2 != null) {
final LegendItem item = renderer2.getLegendItem(3, 1);
result.add(item);
}
}
return result;
}
};
///////////
JFreeChart chart = new JFreeChart("Percentiles", plot);
// final CategoryPlot plot2 = chart.getCategoryPlot();
// CategoryAxis axis = plot2.getDomainAxis();
// final CategoryDataset dataset2 = createDataset2();
plot.setDataset(1, dataset2);
plot.mapDatasetToRangeAxis(1, 1);
final ValueAxis axis2 = new NumberAxis("ms2");
plot.setRangeAxis(1, axis2);
IntervalBarRenderer renderer2 = new IntervalBarRenderer();
rendererSettings(renderer2);
plot.setRenderer(1, renderer2);
plot.setDataset(2, dataset3);
plot.mapDatasetToRangeAxis(2, 2);
final ValueAxis axis3 = new NumberAxis("ms3");
plot.setRangeAxis(2, axis3);
IntervalBarRenderer renderer3 = new IntervalBarRenderer();
rendererSettings(renderer3);
plot.setRenderer(2, renderer3);
plot.setDataset(3, dataset4);
plot.mapDatasetToRangeAxis(3, 3);
final ValueAxis axis4 = new NumberAxis("ms4");
plot.setRangeAxis(3, axis4);
IntervalBarRenderer renderer4 = new IntervalBarRenderer();
rendererSettings(renderer4);
plot.setRenderer(3, renderer4);
ChartUtilities.applyCurrentTheme(chart);
return chart;
}
private static void rendererSettings(IntervalBarRenderer renderer){
// renderer.setItemLabelFont(new Font("Verdana",Font.PLAIN,2));
// renderer.setBaseItemLabelGenerator(new IntervalCategoryItemLabelGenerator());
// renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.INSIDE6, TextAnchor.BOTTOM_CENTER));
// renderer.setItemMargin(0.3);
renderer.setBaseItemLabelsVisible(true);
}
public static JPanel createDemoPanel() {
JFreeChart chart = createChart(createDataset1(),createDataset2(),createDataset3(),createDataset4());
return new ChartPanel(chart);
}
public static void main(String[] args) {
JFrame demo = new IntervalBarChartTest(
"Testing");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}

Related

Reference a scalar property from a string value

I have a combobox that contains a list of scalar properties of an entity. I need to do a search on the property specified by the user in the combobox.
How do I reference the property when I have it as a string?
Something similar to DBSet<> for entity.
Example:
if (order.Firstname != null && order.Firstname.ToLower().Contains(textBoxSearch.Text.ToLower()))
In the above example, I need to replace Firstname with Surname or any other property, at runtime, depending on what the user selected.
You can always use reflection, for your case you'll need something along these lines:
static void Main(string[] args)
{
var entity = new Entity {
Height = 172,
FirstName = "Foo",
Birthday = new DateTime(1, 1, 1995)
};
var firstName = GetEntityProperty<string>(entity, "FirstName");
}
public static T GetEntityProperty<T>(object entity, string propertyName)
{
var type = entity.GetType();
var property = type.GetProperty(propertyName);
return (T)property.GetValue(entity);
}
Provided solution works, but it is not strongly-typed, so it is sensible to property renaming. A strongly-typed approach can be used, but it requires some setup. However, part of the setup is so generic that it can be reused:
public class Order
{
public String OrderNo { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String Misc { get; set; }
}
// clearly define properties that allow search
public enum OrderSearchableProp
{
OrderNo = 1,
FirstName = 2,
LastName = 3
}
class Program
{
// strongly-type requires an explicit mapping between property and its expression within the order object
static Dictionary<OrderSearchableProp, Expression<Func<Order, String>>> OrderSearchableMap = new Dictionary<OrderSearchableProp, Expression<Func<Order, string>>>()
{
{ OrderSearchableProp.OrderNo, o => o.OrderNo },
{ OrderSearchableProp.FirstName, o => o.FirstName },
{ OrderSearchableProp.LastName, o => o.LastName },
};
// this gets a PropertyInfo based from an Expression. It should be placed into a generic utility class
// credit goes to Daniel - http://stackoverflow.com/a/17116267/2780791
public static PropertyInfo GetPropertyFromExpression<T, TProp>(Expression<Func<T, TProp>> GetPropertyLambda)
{
MemberExpression Exp = null;
//this line is necessary, because sometimes the expression comes in as Convert(originalexpression)
if (GetPropertyLambda.Body is UnaryExpression)
{
var UnExp = (UnaryExpression)GetPropertyLambda.Body;
if (UnExp.Operand is MemberExpression)
{
Exp = (MemberExpression)UnExp.Operand;
}
else
throw new ArgumentException();
}
else if (GetPropertyLambda.Body is MemberExpression)
{
Exp = (MemberExpression)GetPropertyLambda.Body;
}
else
{
throw new ArgumentException();
}
return (PropertyInfo)Exp.Member;
}
public static IList<Order> getFilteredOrders(int propFilterValue, IList<Order> orders, String needle)
{
var filterValue = (OrderSearchableProp)propFilterValue;
var filterProp = OrderSearchableMap[filterValue];
var lowNeedle = needle?.ToLower() ?? String.Empty;
return orders.Where(o =>
{
var propInfo = GetPropertyFromExpression<Order, String>(filterProp);
var propValue = (String) propInfo.GetValue(o) ?? String.Empty;
return propValue.ToLower().Contains(lowNeedle);
}).ToList();
}
static void Main(string[] args)
{
// can be used to populate the combo items
// otherwise, not used in this example
OrderSearchableProp[] enumValues = (OrderSearchableProp[])Enum.GetValues(typeof(OrderSearchableProp));
// test orders
var orderList = new List<Order>()
{
new Order() { OrderNo = "1234ABC", FirstName = "George", LastName = "Taylor", Misc = "Extra information"},
new Order() { OrderNo = "AB10", FirstName = "Anonymous", LastName = "X", Misc = "No comment"}
};
// test OrderNo search
var searchProp = (int) OrderSearchableProp.OrderNo;
var foundOrders = getFilteredOrders(searchProp, orderList, "ABC");
// test FirstName search
searchProp = (int)OrderSearchableProp.FirstName;
foundOrders = getFilteredOrders(searchProp, orderList, "a");
// test LastName search with empty string
searchProp = (int)OrderSearchableProp.LastName;
foundOrders = getFilteredOrders(searchProp, orderList, "");
// empty return
searchProp = (int)OrderSearchableProp.OrderNo;
foundOrders = getFilteredOrders(searchProp, orderList, null);
}
}

As3 addChild from Array

I want to add a Child which I loaded into an Array.
I got a Math.random function which returns a Number and should trigger the addChild.
And later I want to splice it into an other Array.
var ground1: MovieClip = new Ground_01;
var ground2: MovieClip = new Ground_02;
var ground3: MovieClip = new Ground_03;
var groundArray: Array = new Array();
var groundMoveArray: Array = new Array();
public function loadGroundArray() {
groundArray.push(ground1);
groundArray.push(ground2);
groundArray.push(ground3);
}
public function randomGround(minNum: Number, maxNum: Number): Number {
minNum = 0;
maxNum = groundArray.length;
return (Math.ceil(Math.random() * (0 + maxNum)));
}
ok, you are almost there... you just need a tweak to your random method to actually add the clip...
var ground1: MovieClip = new Ground_01();
var ground2: MovieClip = new Ground_02();
var ground3: MovieClip = new Ground_03();
var groundArray: Array = new Array();
var groundMoveArray: Array = new Array();
public function loadGroundArray() {
groundArray.push(ground1);
groundArray.push(ground2);
groundArray.push(ground3);
}
public function addRandomGroundToStage(): void {
var randomGroundIndex:int = Math.round(Math.random*(groundArray.length-1));
addChild(groundArray[randomGroundIndex]);
}

how to use pos in MigLayout?

This is my code:
public class InfoPanel extends JPanel{
... ... ...
... ... ...
public InfoPanel(){
... ... ...
... ... ...
MigLayout lManager = new MigLayout();
setLayout(lManager);
add(lblName,new CC().pos("50", "80"));
add(txtName, new CC().pos("90","80").width("170").wrap().gap("r"));
add(lblOccupation,"pos 20 100");
add(txtOccupation,"pos 91 100,w 170,wrap,gap r");
and it has the right output.
but I want to use any built in code for calculate pos() for txtName, txtOccupation.
can anybody help me to do that.
From the image as template:
public class MigLayoutTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MigLayoutTest().start();
}
});
}
private void start() {
JFrame frame = new JFrame();
Container contentPane = frame.getContentPane();
contentPane.setLayout(new MigLayout("wrap 4, debug", "[][fill, grow 1][][fill, grow 4]", ""));
//Declaration
JLabel nameLabel, employmenLabel, ssnLabel, taxIDLabel;
JTextField nameField, ssnField, taxIDField;
JComboBox<String> employmentBox;
JCheckBox checkbox;
JButton save, cancel, upload;
JPanel imagePlaceholder;
//Initialization
nameLabel = new JLabel("Name");
employmenLabel = new JLabel("Employment");
ssnLabel = new JLabel("Social Security Number");
taxIDLabel = new JLabel("tax ID");
nameField = new JTextField();
ssnField = new JTextField();
taxIDField = new JTextField();
save = new JButton("Save");
cancel = new JButton("Cancel");
upload = new JButton("Upload");
checkbox = new JCheckBox("Checkbox");
imagePlaceholder = new JPanel();
employmentBox = new JComboBox<String>();
//Some editing
imagePlaceholder.setBackground(Color.GREEN);
employmentBox.addItem("Some");
employmentBox.addItem("items");
employmentBox.addItem("to");
employmentBox.addItem("fill");
employmentBox.addItem("this");
//Adding to contentPane
contentPane.add(nameLabel, "alignx right");
contentPane.add(nameField, "");
contentPane.add(ssnLabel, "alignx right");
contentPane.add(ssnField, "");
contentPane.add(employmenLabel, "alignx right");
contentPane.add(employmentBox, "");
contentPane.add(upload, "");
contentPane.add(imagePlaceholder, "spany 3, grow");
contentPane.add(checkbox, "split 2");
contentPane.add(taxIDLabel, "");
contentPane.add(taxIDField, "wrap");
contentPane.add(save, "");
contentPane.add(cancel, "growx 0, wrap");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Unable to populate a DataGridViewComboBoxColumn created at design time

I have a DataGridViewComboBoxColumn being craeted at design time.But I want to polulate it at runtime. But it is not happening.
Here is the entire code
public partial class Form1 : Form
{
private List<FileInformation> FileInformationList;
public Form1()
{
InitializeComponent();
PrepareGrid();
DisplayResult();
}
private void PrepareGrid()
{
var fileNameColumn = new DataGridViewTextBoxColumn
{
Name = #"FileName",
HeaderText = "File Name",
DataPropertyName = #"FileName",
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
ReadOnly = false,
Frozen = false
};
dataGridView1.Columns.Add(fileNameColumn);
var downloadColumn = new DataGridViewLinkColumn
{
Name = #"Download",
HeaderText = #"Download",
DataPropertyName = #"Download",
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
ReadOnly = true
};
dataGridView1.Columns.Add(downloadColumn);
var dropdownColumn = new DataGridViewComboBoxColumn
{
Name = #"Test",
HeaderText = #"Country",
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
ReadOnly = true
};
dataGridView1.Columns.Add(dropdownColumn);
}
private void DisplayResult()
{
FileInformationList = LoadItems();
dataGridView1.DataSource = FileInformationList;
((DataGridViewComboBoxColumn)dataGridView1.Columns["Test"]).DataSource = GetCountryList();
((DataGridViewComboBoxColumn)dataGridView1.Columns["Test"]).ValueMember = "id";
((DataGridViewComboBoxColumn)dataGridView1.Columns["Test"]).DisplayMember = "Name";
}
private List<FileInformation> LoadItems()
{
var lstScriptInfo = new List<FileInformation>();
for (int i = 1; i <= 5; i++)
{
lstScriptInfo.Add(new FileInformation { FileName = "File" + i.ToString() + ".txt" });
}
return lstScriptInfo;
}
private DataTable GetCountryList()
{
DataTable CountryDt = new DataTable();
CountryDt.Columns.Add("id");
CountryDt.Columns.Add("Name");
CountryDt.Rows.Add("1", "Canada");
CountryDt.Rows.Add("2", "USA");
return CountryDt;
}
}
public class FileInformation
{
public string FileName { get; set; }
public string Download { get { return "Download File"; } }
}
}
The output is
Please help me to identity what has went wrong?
Two ways to achieve that:
Setting defualt null value for column (skipped null checks):
var cbColumn = (DataGridViewComboBoxColumn)dataGridView1.Columns["Test"];
var ds = GetCountryList();
cbColumn.DataSource = ds;
cbColumn.ValueMember = "id";
cbColumn.DisplayMember = "Name";
cbColumn.DefaultCellStyle.NullValue = ds.Rows[0][0];
cbColumn.DefaultCellStyle.DataSourceNullValue = ds.Rows[0][1];
Second is to iterate after DataBinding and set it manually:
private void DataGridDataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
var hasValue = row.Cells["Test"].Value != null;
if (!hasValue)
{
row.Cells["Test"].Value = 1;
}
}
}
also I'd change binding order:
private void DisplayResult()
{
var cbColumn = (DataGridViewComboBoxColumn)dataGridView1.Columns["Test"];
var ds = GetCountryList();
cbColumn.DataSource = ds;
cbColumn.ValueMember = "id";
cbColumn.DisplayMember = "Name";
cbColumn.DefaultCellStyle.NullValue = ds.Rows[0][0];
cbColumn.DefaultCellStyle.DataSourceNullValue = ds.Rows[0][1];
FileInformationList = LoadItems();
dataGridView1.DataSource = FileInformationList;
}

I have a LegendItemEntity, how do I get the LegendItem?

I have code that hides/shows a series when the LegendItemEntity is clicked. The code works, except I use the index of the series as the index of the LegendItem in the LegendItemCollection. The problem is that sometimes there are more series than LegendItems and their respective indices are not the same. How do I get the LegendItem given that I have the LegendItemEntity?
private final ChartMouseListener chartMouseListener = new ChartMouseListener() {
public void chartMouseClicked(ChartMouseEvent cme) {
ChartEntity entity = cme.getEntity();
if (entity instanceof LegendItemEntity) {
LegendItemEntity itemEntity = (LegendItemEntity) entity;
int index = dataset.getSeriesIndex(itemEntity.getSeriesKey());
XYPlot plot = (XYPlot) chart.getPlot();
XYItemRenderer renderer = plot.getRenderer();
renderer.setSeriesVisible(index, !renderer.isSeriesVisible(index));
LegendItem legendItem = plot.getLegendItems().get(index);
if (renderer.isSeriesVisible(index)) {
legendItem.setLinePaint(renderer.getSeriesPaint(index));
} else {
legendItem.setLinePaint(Color.WHITE);
}
}
}
public void chartMouseMoved(ChartMouseEvent cme) {
}
};
You can use renderer.getLegendItem(). The result will be null for a non-visible series. Given a JFreeChart chart, a chartMouseClicked() implementation might look like this:
#Override
public void chartMouseClicked(ChartMouseEvent e) {
ChartEntity entity = e.getEntity();
if (entity instanceof LegendItemEntity) {
LegendItemEntity itemEntity = (LegendItemEntity) entity;
Comparable key = itemEntity.getSeriesKey();
XYDataset dataset = (XYDataset) itemEntity.getDataset();
int seriesIndex = dataset.indexOf(key);
XYPlot plot = (XYPlot) chart.getPlot();
int datasetIndex = plot.indexOf(dataset);
XYItemRenderer renderer = plot.getRenderer();
LegendItem legendItem = renderer.getLegendItem(datasetIndex, seriesIndex);
System.out.println(key + " " + datasetIndex + " " + seriesIndex);
System.out.println(legendItem);
}
}

Resources