vendredi 27 mars 2015

paint not saving to bufferedimage



The code below was properly plotting a chart to a JPanel when I had all the drawing code inside paintComponent(). But I want to save the result to an image file on the hard drive for use elsewhere. I therefore moved the drawing code into the updatePaint() method and took other steps shown below to draw to a bufferedimage first and then have the bufferedimage available to print to the JPanel and to a saved file. The problem is that the code below just prints a black JPanel instead of the chart that was being painted before I rearranged the code.


How can I change the code below so that the bufferedimage shows the expected chart, and is properly painted to the JPanel, without interfering with its ability to save to the file?



package somepackage;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ChartPanel extends JPanel {
private BufferedImage paintImage = new BufferedImage(500, 400, BufferedImage.TYPE_3BYTE_BGR);

private double[] values;
private String[] names;
private String title;
private double fac_result;

public ChartPanel(double[] v, String[] n, String t, double fac_res) {
names = n;
values = v;
title = t;
fac_result = fac_res;
}

public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(paintImage, 0, 0, null);
}

// draw painting
public void updatePaint(){
Graphics g = paintImage.createGraphics();

// draw on paintImage using Graphics
if (values == null || values.length == 0)
return;
double minValue = 0;
double maxValue = 0;
for (int i = 0; i < values.length; i++) {
if (minValue > values[i])
minValue = values[i];
if (maxValue < values[i])
maxValue = values[i];
}

Dimension d = getSize();
int clientWidth = d.width;
int clientHeight = d.height;
int barWidth = clientWidth / values.length;

Font titleFont = new Font("SansSerif", Font.BOLD, 20);
FontMetrics titleFontMetrics = g.getFontMetrics(titleFont);
Font labelFont = new Font("SansSerif", Font.PLAIN, 10);
FontMetrics labelFontMetrics = g.getFontMetrics(labelFont);
int titleWidth = titleFontMetrics.stringWidth(title);
int y = titleFontMetrics.getAscent();
int x = (clientWidth - titleWidth) / 2;
g.setFont(titleFont);
g.drawString(title, x, y);

int top = titleFontMetrics.getHeight();
int bottom = labelFontMetrics.getHeight();
if (maxValue == minValue)
return;
double scale = (clientHeight - top - bottom) / (maxValue - minValue);
y = clientHeight - labelFontMetrics.getDescent();
g.setFont(labelFont);
System.out.println("fac_result in paintComponent() is: "+fac_result);
for (int i = 0; i < values.length; i++) {
int valueX = i * barWidth + 1;
int valueY = top;
int height = (int) (values[i] * scale);
if (values[i] >= 0)
valueY += (int) ((maxValue - values[i]) * scale);
else {
valueY += (int) (maxValue * scale);
height = -height;
}
System.out.println("names["+i+"] is: "+names[i]);
if((Double.parseDouble(names[i])<=(fac_result+0.5))&&(Double.parseDouble(names[i])>=(fac_result-0.5))){
g.setColor(Color.cyan);
g.fillRect(valueX, valueY, barWidth - 2, height);
System.out.println("condition met.");
}
else{
g.setColor(Color.red);
g.fillRect(valueX, valueY, barWidth - 2, height);
}
g.setColor(Color.black);
g.drawRect(valueX, valueY, barWidth - 2, height);
if(i%5==0){
int labelWidth = labelFontMetrics.stringWidth(names[i]);
x = i * barWidth + (barWidth - labelWidth) / 2;
g.drawString(names[i], x, y);
}
}
///////////
g.dispose();
// repaint panel with new modified paint
repaint();
}

public void save() throws IOException{
ImageIO.write(paintImage, "PNG", new File("C:\\Temp\\filename.png"));
}

public void load() throws IOException {
paintImage = ImageIO.read(new File("C:\\Temp\\filename.png"));
// update panel with new paint image
repaint();
}

}


Note: The above code is called from another class using the following line:



new ChartPanel(values, names, label, fac_result));




EDIT#1




You can recreate the problem with simple data using the following code:



String[] names = {"zero", "one", "two", "three"};
double[] values = {24,43,12,32};
String label = "somelabel";
fac_result = 12;




EDIT#2




Per @MadProgrammer's comment, I added the following code to the above:



@Override
public void invalidate(){
super.invalidate();
updatePaint();
}


I also changed the BufferedImage type to BufferedImage.TYPE_INT_ARGB, which removed the black background.


The remaining problem is that the title is printed twice, with one printing in the proper location, and the other printing somewhat offscreen, as if a translation had not yet been performed.


These incremental improvements are promising. What else do I have to do to remove the redundant/mis-placed title?


To make it easier. I have simplified the code required to reproduce the remaining problem to the following, which includes only 18 lines of updatePaint():



public class ChartPanel extends JPanel {
private BufferedImage paintImage = new BufferedImage(600, 450, BufferedImage.TYPE_INT_ARGB);

private double[] values;
private String[] names;
private String title;
private double fac_result;

public ChartPanel(double[] v, String[] n, String t, double fac_res) {
names = n;
values = v;
title = t;
fac_result = fac_res;
}

public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(paintImage, 0, 0, null);
}

@Override
public void invalidate(){
super.invalidate();
updatePaint();
}

// draw painting
public void updatePaint(){
Graphics g = paintImage.createGraphics();

Dimension d = getSize();
int clientWidth = d.width;
int clientHeight = d.height;
int barWidth = clientWidth / values.length;

Font titleFont = new Font("SansSerif", Font.BOLD, 20);
FontMetrics titleFontMetrics = g.getFontMetrics(titleFont);
Font labelFont = new Font("SansSerif", Font.PLAIN, 10);
FontMetrics labelFontMetrics = g.getFontMetrics(labelFont);
int titleWidth = titleFontMetrics.stringWidth(title);
int y = titleFontMetrics.getAscent();
int x = (clientWidth - titleWidth) / 2;
g.setFont(titleFont);
g.setColor(Color.blue);//jim added 3/27 test
g.drawString(title, x, y);
repaint();
}
}



Aucun commentaire:

Enregistrer un commentaire