I create a BufferedImage in a parent class method and use Graphics2D to set options (Paint, RenderingHints, etc.). Another class inherits this base class and overrides the method but calls the superclass method to acquire the BufferedImage instance.
How do I keep the Graphics2D settings from the superclass method?
class Parent {
BufferedImage draw() {
BufferedImage image = new BufferedImage(...)
Graphics2D g2 = (Graphics2D) image.getGraphics()
g2.setColor(new Color(255, 0, 0))
return image;
}
}
class Child extends Parent {
#Override
BufferedImage draw() {
BufferedImage image = super.draw()
Graphics2D g2 = (Graphics2D) image.getGraphics()
System.out.println(g2.getColor()) // 255, 255, 255
return image;
}
}
Related
I'm writing paint on screen program using Java Swing. It working on ubuntu linux. But windows shows black screen instead of transparent panel. I included similar example code. What is wrong in my code?
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Example {
public static final Color COLOR_TRANSPARENT = new Color(0,0,0,0);
public Example() {
Canvas drawArea = new Canvas();
drawArea.setBackground(COLOR_TRANSPARENT);
drawArea.setOpaque(true);
JWindow drawingFrame = new JWindow();
drawingFrame.setBackground(COLOR_TRANSPARENT);
drawingFrame.setContentPane(drawArea);
drawingFrame.pack();
drawingFrame.setSize(640, 460);
drawingFrame.setVisible(true);
drawingFrame.setLocationRelativeTo(null);
drawingFrame.setAlwaysOnTop(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(Example::new);
}
class Canvas extends JPanel{
private Image image;
private Graphics2D g2;
public Canvas() {
super();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
g2.setPaint(Color.RED);
g2.fillOval(x-10, y-10, 20, 20);
repaint(x-10, y-10, 20, 20);
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null){
image = createImage(getWidth(), getHeight());
g2 = (Graphics2D) image.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setBackground(COLOR_TRANSPARENT);
clear();
}
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image, 0,0, null);
}
public void clear(){
System.out.println("clearing canvas ");
g2.setComposite(AlphaComposite.Clear);
g2.setBackground(COLOR_TRANSPARENT);
g2.setColor(COLOR_TRANSPARENT);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.clearRect(0, 0, getWidth(), getHeight());
g2.setPaint(Color.RED);
g2.setComposite(AlphaComposite.SrcOver);
repaint();
}
}
}
Here is screenshot what I wanted.
Example code updated. Now code should work without any other additional code.
For windows I made a couple of changes:
image = createImage(getWidth(), getHeight());
image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
I used a BufferedImage to you can set the alpha values of the image to be transparent.
//public static final Color COLOR_TRANSPARENT = new Color(0,0,0,0);
public static final Color COLOR_TRANSPARENT = new Color(0,0,0,1);
I made the alpha value non-zero, because a value of zero means the Java application won't receive the MouseEvent because it is passed to the application under the window.
graphics2D is returning "NULL" always in below code. Due to that putPixel() method is not being called. I am calling PictureBox from form design.
public class PictureBox extends JPanel {
Graphics2D graphics2D;
static BufferedImage image;
int imageSize = 300;
public PictureBox(){
setDoubleBuffered(false);
this.setBorder(UIManager.getBorder("ComboBox.border"));
this.repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
if(image == null){
image = new BufferedImage(imageSize, imageSize, BufferedImage.TYPE_INT_RGB);
graphics2D = (Graphics2D)image.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(image, 0, 0, this);
repaint();
}
public final void putPixel(int x, int y, Color color) {
if(graphics2D != null){
graphics2D.setColor(color);
graphics2D.drawLine(x, y, x, y);
repaint();
}
}
public void clear() {
graphics2D.setPaint(Color.WHITE);
graphics2D.fillRect(0, 0, imageSize,imageSize);
repaint();
}
}
putPixel method is being called from main where i have (x,y) coordinate stored in Point2D array.
Since you have called putPixel from outside the class and you have not initialised the graphics2D and image in the constructor it may be that when you all calling putPixel method the class may not have been displayed. So you are getting graphics2D to be null as it initialises only when the paintComponent is called and it is called when this class gets displayed.
The solution could be that you shift the initialisation code for the image and graphics2D to the constructor so that you do not encounter null while calling putPixel.
NOTE
You have indiscriminately called the method repaint(). You should keep in mind that repaint() calls paint() method which in turn calls paintComponent() method. So if you call repaint() inside paintComponent() method, you run into the risk of creating an infinite loop. Here you have called it twice once in paintComponent and again in clear method which is called by paintComponent.
What's the easiest way in Java SE 7 to obtain an instance just to plot a few points for debugging? Desktop environment.
You could use a BufferedImage:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = image.createGraphics();
The easiest and safest way is to use to cast the Graphics reference in paintComponent and cast it as needed. That way the Object is correctly initialized. This reference can be passed to other custom painting methods as required.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
...
}
You should probably just create a JPanel and paint on it.
public class MyPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
.... // my painting
}
}
My small Java program is trying to darken a png image. It's working fine on my Mac but when I try to run it on a Windows PC with java 1.7_07 installed but it doesn't show anything at all except an empty JPanel, the image is completely disappeared.
Here is the code:
class MapCanvas extends JPanel {
private Color color;
RescaleOp op;
BufferedImage sourceImage, bi;
public MapCanvas() {
try {
sourceImage = ImageIO.read(new File(MAP_FILENAME));
bi = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
op = new RescaleOp(.8f, 0, null);
bi = op.filter(bi, null);
Graphics2D g = bi.createGraphics();
g.drawImage(sourceImage, 0, 0, 500, 382, null);
g.dispose();
} catch (Exception e) {
e.printStackTrace();
}
// set size for the panel
Dimension size = new Dimension(500, 382);
this.setBackground(new Color(34, 102, 187));
setPreferredSize(size);
setSize(size);
setLayout(null);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.drawImage(bi, op, 0, 0);
}
}
Anyone know why I'm getting this? Many thanks.
I don't seem to have any issues, BUT, several things jump out at me about this example...
Firstly, I don't see why you've done this...
try {
sourceImage = ImageIO.read(new File("C:/Users/shane/Dropbox/issue453.jpg"));
bi = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
op = new RescaleOp(.1f, 0, null);
bi = op.filter(bi, null);
Graphics2D g = bi.createGraphics();
g.drawImage(sourceImage, 0, 0, 500, 382, null);
g.dispose();
} catch (Exception e) {
e.printStackTrace();
}
Then done this...
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.drawImage(bi, op, 0, 0);
}
You're basically double apply the RescaleOp.
It could simply just apply the RescaleOp directly to the sourceImage...
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.drawImage(sourceImage, op, 0, 0);
}
Unless you're concerned about performance, in which case you should simple draw the bi without any BufferedImageOp
g2d.drawImage(bi, 0, 0, this);
Secondly, your example won't compile because you've not defined g2d in your paintComponent method. This is either an oversight (which is fine) OR you are caching the Graphics object, which is not fine.
Graphics objects are stateless, they do not persist between repaints, you should NEVER cache them or rely on getGraphics.
Thank you for pointing out my mistakes. There is some missing code in my question (the Graphics2D g2d - it's just an unassigned variable) so it doesn't compile. Sorry about that.
This is how I fixed it:
`sourceImage = ImageIO.read(new File(MAP_FILENAME));
bi = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
float[] scales = { .5f, .5f, .5f, 1f };
float[] offsets = new float[4];
op = new RescaleOp(scales, offsets, null);
Graphics2D g1 = bi.createGraphics();
g1.drawImage(sourceImage, 0, 0, 500, 382, null);
g1.dispose();
op.filter(sourceImage, bi);`
I just use the same value for RGB in the scales array (that's how it supposed to be) then draw the filtered image.
`g2d.drawImage(bi, 0, 0, 500, 382, null);`
Cheers
I've been using the new com.sun.awt.AWTUtilities class and am intrigued. I got com.sun.awt.AWTUtilities/setWindowOpacity(java.awt.Window window, float f) to work perfectly, but am now wondering if there is any way to change the opacity of an individual component, such as a javax.swing.JInternalFrame or javax.swing.JButton.
Try this:
class TransparentButton extends JButton {
public TransparentButton(String text) {
super(text);
setOpaque(false);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
super.paint(g2);
g2.dispose();
}
}