I am trying to merge multiple graphs to create a single chart. The individual graphs have White background but somehow my merged chart end up getting gray background despite using setBackgroundpaint api.
public static String mergeXYGraphs(List<XYPlot> plots, String title, boolean legend, int width, int height) throws IOException
{
if(plots != null && !plots.isEmpty())
{
XYPlot base = plots.get(0);
for(int i = 1; i< plots.size(); i++)
{
base.setDataset(i, plots.get(i).getDataset());
base.setRenderer(i, plots.get(i).getRenderer());
}
JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, base, legend);
setDateAxis(base);
chart.getXYPlot().setBackgroundPaint(Color.WHITE);
return saveImageFile(chart, "merged", "charts", width, height);
}
return "";
}
private static void setDateAxis(XYPlot plot)
{
DateAxis domainAxis = new DateAxis();
domainAxis.setAutoTickUnitSelection(true);
domainAxis.setDateFormatOverride(new SimpleDateFormat("dd/MM"));
plot.setDomainAxis(domainAxis);
}
PS : base.setBackgroundPaint(Color.WHITE); doesn't work either
So it turns out that we have to set colors on different levels on jfreechart to control the colors of different parts.
In the image above the background color of the panel is white but the background color of the chart isn't. So, I had to use:
chart.setBackgroundPaint(Color.WHITE);
Related
I don't know if it is even possible, but maybe someone found a way to do this...
I have a tab control to which I allow the user to add tabs with a button click.
I want to show some icons on the tab so I added an ImageList, but I can show only one icon at a time, and I need to show at least 3 icons together.
I thought about having an image of 3 icons together, but the icons are shown after some actions the use do. For example: at first I show icon_1 and if the user clicks some where I add icon_2 etc...
Can someone come up with a way to do this ?
Thank you very much in advance...
No. It's not possible. Using the standard WinForms TabControl component you only can show one image at the same time.
The solution here, is using overlay icons. You have a base icon, and you add decorators. This is how Tortoise SVN, for example,
The following code builds an overlayed image in C#:
private static object mOverlayLock = new object();
public static Image GetOverlayedImage(Image baseImage, Image overlay)
{
Image im = null;
lock (mOverlayLock)
{
try
{
im = baseImage.Clone() as Image;
Graphics g = Graphics.FromImage(im);
g.DrawImage(overlay, 0, 0, im.Width, im.Height);
g.Dispose();
}
catch
{
// log your exception here
}
}
return im;
}
NOTE: The overlayed image must have the same size than the base image. It must have transparent color, and the decorator in the overlayed image must be placed in the right place, for example bottom-right or top-right.
I found this code:
private Bitmap CombineImages(params Image[] images)
{
int width = 0;
for (int i = 0; i < images.Length; i++)
width += images[i].Width + 3;
int height = 0;
for (int i = 0; i < images.Length; i++)
{
if (images[i].Height > height)
height = images[i].Height;
}
int nIndex = 0;
Bitmap fullImage = new Bitmap(width, height);
Graphics g = Graphics.FromImage(fullImage);
g.Clear(SystemColors.AppWorkspace);
foreach (Image img in images)
{
if (nIndex == 0)
{
g.DrawImage(img, new Point(0, 0));
nIndex++;
width = img.Width;
}
else
{
g.DrawImage(img, new Point(width, 0));
width += img.Width;
}
}
return fullImage;
//img3.Save(finalImage, System.Drawing.Imaging.ImageFormat.Jpeg);
//img3.Dispose();
//imageLocation.Image = Image.FromFile(finalImage);
}
from this link http://www.codeproject.com/Articles/502249/Combineplusseveralplusimagesplustoplusformplusaplu
Im trying to override the getItemPaint() method of XYLineAndShapeRenderer by creating a subclass:
private class MultiRenderer extends XYLineAndShapeRenderer{
#Override
public Paint getItemPaint(int row, int column) {
if(row==2){
float x = getAmplitude()[column];
return floatToColor(x);
}
return super.getItemPaint(row, column);
}
private Color floatToColor(float val){...}
}
And calling:
XYPlot xyPlot = (XYPlot) myJFreeChartObject.getPlot();
MultiRenderer r = (MultiRenderer) xyPlot.getRenderer();
But im getting a ClassCastException. Is there a way I can cast this properly or override getItemPaint without creating a subclass? Im trying to plot 2 series as regular line plots and a 3rd series without a line and different color points. The first 2 series should have a line but no point markers.
Note getAmplitude() just returns an array of floats between 0 and 1
You can either use an Anonymous Inner Class
plot.setRenderer(new XYLineAndShapeRenderer() {
#Override
public Paint getItemPaint(int row, int column) {
if(row==2){
float x = getAmplitude()[column];
return floatToColor(x);
}
return super.getItemPaint(row, column);
}
private Color floatToColor(float val){...}
});
Or use a DrawingSupplier for your plot
Hi i have a JFreeChart that i want to be able to plot and add series to without losing old data.
For example I initially generate the JFreeChart from:
public JFreeChart plot(Number[] x, Number[] y, String title, String xLabel,
String yLabel) {
XYSeries series = new XYSeries(title);
if (x.length == y.length) {
for (int i = 0; i < x.length; i++) {
series.add(x[i], y[i]);
}
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);
JFreeChart chart = ChartFactory.createXYLineChart(title, xLabel,
yLabel, dataset, PlotOrientation.VERTICAL, false, false,
false);
return chart;
} else {
System.out.println("Error: [plot] X&Y Vectors of different lengths");
return null;
}
}
Then i would add it to a ChartPanel and to my ContentPane:
ChartPanel cp = new ChartPanel(chart);
contentPane.add(cp, BorderLayout.CENTER);
now i need a function that can add an extra series to the plot without forgetting the series already in the dataset (so i cannot just call my plot function again)
how do I do this?
As long as you have a referance to your dataset you can add a new series at any time using dataset.addSeries(series)
I've got a fairly straightforward pixel shader—set alpha channel to zero and return.
sampler2D tex : register(s0);
float4 PS(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D(tex, uv);
color.a = 0;
return color;
}
I'd assume this would cause the image it's applied to to be completely invisible. However that's not what appears to be happening. Instead, the resulting image will become invisible over a white background, but over a black background it'll be unchanged. It appears that this shader is somehow causing an "add" function to be called between the foreground and the background.
For example, the following code loads a foreground and background image, applies the above shader effect to the foreground, renders them to a bitmap, and writes the bitmap to file.
public sealed partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
void Button_Click(object sender, RoutedEventArgs e)
{
const int width = 1024;
const int height = 768;
var sz = new Size(width, height);
var background = new Image { Source = new BitmapImage(new Uri(#"c:\background.jpg")) };
background.Measure(sz);
background.Arrange(new Rect(sz));
var foreground = new Image { Source = new BitmapImage(new Uri(#"c:\foreground.jpg")), Effect = new Alpha() };
foreground.Measure(sz);
foreground.Arrange(new Rect(sz));
var target = new RenderTargetBitmap(width, height, 96d, 96d, PixelFormats.Default);
target.Render(background);
target.Render(foreground);
var jpg = new JpegBitmapEncoder();
jpg.Frames.Add(BitmapFrame.Create(target));
using (var fileStream = File.OpenWrite(#"c:\output.jpg"))
{
jpg.Save(fileStream);
}
}
}
// Standard ShaderEffect stuff here, nothing exciting.
public sealed class Alpha : ShaderEffect
{
static readonly PixelShader Shader = new PixelShader{UriSource = new Uri("pack://application:,,,/Alpha.ps", UriKind.RelativeOrAbsolute)};
public static readonly DependencyProperty InputProperty = RegisterPixelShaderSamplerProperty("Input", typeof(Alpha), 0);
public Alpha()
{
PixelShader = Shader;
UpdateShaderValue(InputProperty);
}
public Brush Input
{
get { return (Brush)GetValue(InputProperty); }
set { SetValue(InputProperty, value); }
}
}
This produces the following when applied to two of the Win7 sample pictures:
This is the same behavior I see on the screen when I apply the effect to one Image in XAML, with another Image or anything else behind it.
Note the image is the same if foreground and background are reversed, so if it's not "add", it's at least something commutative. I think it's "add".
Computers are usually right, so I assume this is user error, but why is setting alpha to zero not giving me a transparent image? And how do I get a transparent image if so? (I obviously want to do something more complex with the shader eventually (specifically greenscreen), but to get that to work I have to get this shader to work first, so don't just say "Set the Opacity property").
Gah, stackoverflow is better than google. The top "related question" had the answer. Handling alpha channel in WPF pixel shader effect
I have an array of horizontal fields which contains a bitmap and a labelfield each. The whole row should be clickable which is working so far, but how can I set the focus color properly? At the moment the onFocus and onUnfocus functions are being completely ignored.
This is the definition of my array:
for (int i = 0; i < listSize; i++) {
logInDetailManager[i] = new HorizontalFieldManager(
Manager.USE_ALL_WIDTH | Field.FOCUSABLE) {
protected void onFocus(int direction) {
super.onFocus(direction);
background_color = Color.RED;
invalidate();
}
protected void onUnfocus() {
invalidate();
background_color = Color.GREEN;
}
And this is how I add my horizontal fields:
logInDetailManager[i].setChangeListener(this);
logInDetailManager[i].add(dummyIcon[i]);
logInDetailManager[i].add(new LabelField("hello"));
logInDetailManager[i].add(new NullField(Field.FOCUSABLE));
add(logInDetailManager[i]);
Sorry, I couldn't comment to my own post yesterday since I'm new to Stackoverflow ;)
Here's how I solved it:
I removed onFocus() and onUnfocus() from the HFM and set the background color in the paint method so the whole row color is changed when focused:
protected void paint(Graphics graphics) {
graphics.setBackgroundColor(isFocus() ? Color.RED : Color.GREEN);
graphics.clear();
invalidate();
super.paint(graphics);
}
I also found out that if you want to set more complex backgrounds (i.e. with a gradient) you can also use the setBackground(int visual, Background background) method:
Background bg_focus = (BackgroundFactory
.createLinearGradientBackground(Color.GREEN, Color.LIGHTGREEN,
Color.LIGHTGREEN, Color.GREEN));
loginDetailManager[i].setBackground(VISUAL_STATE_FOCUS, bg_focus);
Make sure to delete you're paint method when using the setBackground function like that!