Transparency not working in java - java

I have an image, with a complete transparent background. However when I draw this image, ingame, it has a kind of shade to it, and I have no clue why. I would like to get that out of there. Does anyone have an idea? I don't have the reputation to post images of it apparently... So I'll try to give some more information.
I have the Color.DARK_GRAY as background, and when I draw the image, you see a lighter gray square around it.
Then when I draw a couple of these images ontop of eachother, that square gets lighter and lighter.
If I draw the image ontop of another image however, this effect does not occur.
Here I load the image
public BlackChip() {
this.value = 500;
this.url = "res/images/poker/blackchip.png";
this.file = new File(url);
BufferedImage bi;
try {
bi = ImageIO.read(file);
this.image = bi;
} catch (IOException e) {
e.printStackTrace();
}
}
Here I draw the image
public void renderChip(Chip chip, int x, int y) {
g.drawImage(chip.getImage(), x, y, null);
}
Here I call that method
public void render() {
screen.renderBackground(Color.DARK_GRAY);
pokertable.render(Game.width / 2 - pokertable.getImage().getWidth(null) / 2, 50);
screen.renderChip(cs.getWhiteChip(), 380, 310);
screen.renderChip(cs.getRedChip(), 430, 310);
screen.renderChip(cs.getGreenChip(), 480, 310);
screen.renderChip(cs.getBlueChip(), 530, 310);
screen.renderChip(cs.getBlackChip(), 580, 310); //this one is it
}
link to the images:
https://drive.google.com/file/d/0Bz-4pfUssUeHRWkxaUhodWNILWc/edit?usp=sharing
Well... this doesn't work either because i need 10 reputation to post more then 1 link
you can see the effect on this link, it's the image with full transparent background, drawn multiple times.

I can't tell if this is the exact cause of the problem, because you haven't provided a MCVE but this method
public void renderChip(Chip chip, int x, int y) {
g.drawImage(chip.getImage(), x, y, null);
}
Just looks wrong. All custom painting should be done within the context of the provided Graphics object in the overridden paintComponent method. If you have not overriden paintComponent in a JPanel or a JComponent then you are likely not painting correctly. You may be doing something like
public class SomePanel extends JPanel {
private Graphics g;
public SomePanel() {
g = getGraphics();
}
}
Which is completely wrong. You should instead be doing something like
public class SomePanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// do painting here
}
}
You Classes can then have it's own render method that takes a Graphics object as an argument. Then can be called in the paintComponent method. Maybe something like
public class Chip {
private JComponent imageObserver;
private BufferedImage chipImage;
int x, y;
public Chip(BufferedImage chipImage, int x, int y, JComponent imageObserver){
this.chipImage;
this.x = x;
this.y = y;
this.imageObserver = imageObserver;
}
public void renderChip(Graphics g) {
g.getImage(chipImage, x, y, imageObserver);
}
}
And your panel
public class SomePanel extends JPanel {
private List<Chip> chips;
public SomePanel() {
chips = new ArrayList<Chip>();
// add new Chips
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Chip chip: chips) {
chip.renderChip(g);
}
}
}

Related

How to paint components in layers in Java?

I have big problem with coding graphic part of my app, where I need to have components one on top of each other:
First I have JFrame (with fixed size)
In it I have two JPanel components. I want them to have colour background.
That's the easy part.
On one of the JPanel components I want to draw fixed shapres - rectangles, lanes, etc. Here I have problem, that I have two classes: one extends JPanel and is background for this part and second extends JComponent and represents element I draw (there is several elements). I don't know how to draw the elements in the JPanel - I tried several methods and nothing showed up. It's important to me that the JComponents should be drawn and conected only with this JPanel, not with whole frame.
On top of that I want to have moving shapes. It's easy when I have only frame and let's say rectangle, because I only change position and call repaint() method, but how to do this to make the moving shapes be connected to and be inside JPanel and to left previous layers in their place?
For my tries I created few classes with rectangles:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class Main{
public Main() {
JFrame frame = new JFrame();
frame.setSize(1200, 900);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
JPanel background = new JPanel();
background.setBackground(Color.lightGray);
GreenRect gr = new GreenRect();
gr.setPreferredSize(new Dimension(500,800));
background.add(gr, BorderLayout.WEST);
RedRect rr = new RedRect();
rr.setPreferredSize(new Dimension(500,800));
background.add(rr, BorderLayout.EAST);
frame.add(background);
}
public static void main(String[] args) {
new Main();
}
}
class GreenRect extends JPanel {
ArrayList<BlackRect> r = new ArrayList<>();
ArrayList<MovingRec> m = new ArrayList<>();
public GreenRect() {
setBackground(Color.green);
addRec(10,10);
addRec(50,50);
addRec(100,100);
addRec(1000,1000);
}
public void addRec(int x, int y) {
r.add(new BlackRect(x,y));
}
}
class RedRect extends JPanel {
public RedRect() {
setBackground(Color.red);
}
}
class BlackRect extends JComponent {
int x, y;
int w = 100, h = 100;
public BlackRect (int x, int y){
this.x = x;
this.y = y;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.fillRect(x, y, w, h);
}
}
class MovingRec extends JComponent {
int x, y;
int w = 20, h = 20;
public MovingRec (int x, int y){
this.x = x;
this.y = y;
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE);
g2d.fillRect(x, y, w, h);
}
public void update() {
x += 5;
y += 5;
}
}
and now I have problems with points 3 and 4, because I can't place black rectangles on background and moving rectangles on the top.
I will be grateful for all help :)
You do not need to (and shouldn’t) extend BlackRect and MovingRect from JComponent.
For example, BlackRect could be a simple object, like:
class BlackRect {
int x, y;
int w = 100, h = 100;
public BlackRect(int x, int y) {
this.x = x;
this.y = y;
}
public void paint(Graphics2D g2d) {
g2d.setColor(Color.BLACK);
g2d.fillRect(x, y, w, h);
}
}
You should override GreenRect’s paint method, to paint rectangles on that panel:
public GreenRect extends JPanel {
// Existing members
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (BlackRect black_rect : r) {
black_rect.paint(g2d);
}
// Also paint list of moving rectangles here
}
}
When GreenRect.repaint() is called, it will paint its background, and all rectangles from the r (and m list when you add that code). If the m rectangles have had their positions updated, they will be drawn at their new positions, so they will appear to be moving. Since moving rectangles are drawn last, they would appear “on top”.
Use a Swing Timer to drive the animation. When the timer expires, it should move all of the moving rectangles slightly (ie, call MovingRec.update()), and call repaint() on GreenRect.

JAVA drawImage is drawing the Image at the wrong location

I am playing around with the Graphics class. Here is my code for drawing an image at a certain location:
public class PixelManager extends JPanel {
private ArrayList<Pixel> pixels = new ArrayList<Pixel>();
public PixelManager() { }
public void addPixel(int posX, int posY, BufferedImage texture) {
pixels.add(new Pixel(posX, posY, texture));
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Pixel pixel : pixels) {
g2d.drawImage(pixel.getTexture(), pixel.getX(), pixel.getY(), 20, 20, null);
}
g2d.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400,400);
}
}
Explanation: I am using this class as kind of an Pixel or Texture Manager. In the ArrayList I am saving some Pixels, which include a position and a texture. in de paintComponent Method I am iterating through the ArrayList and trying to draw them.
Pixel class:
public class Pixel extends JPanel{
private int _posX, _posY;
private static int _width = 20;
private BufferedImage _texture;
public Pixel(int posX, int posY, BufferedImage texture) {
_posX = posX;
_posY = posY;
_texture = texture;
}
//Getter und Setter
public int getPosY() {
return _posY;
}
public int getPosX() {
return _posX;
}
public void setPosY(int posY) {
_posY = posY;
}
public void setPosX(int posX) {
_posX = posX;
}
public BufferedImage getTexture() {
return _texture;
}
public void setTexture(BufferedImage texture) {
_texture = texture;
}
}
And the JFrame extending class:
public class Zeichnen extends JFrame {
static PixelManager pman;
public Zeichnen()
{
setTitle("Tutorial");
setSize(400, 400);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args)
{
Zeichnen fenster = new Zeichnen();
pman = new PixelManager();
fenster.add(pman);
try {
pman.addPixel(100, 100, ImageIO.read(new File("C:\\Users\\Cronax3\\Documents\\grass.jpg")));
pman.addPixel(200, 200, ImageIO.read(new File("C:\\\\Users\\\\Cronax3\\\\Documents\\\\blue.png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
So here is the problem. The two images will be drawn to the panel/frame but ALWAYS to the postion x=0,y=0. I debuged everything until this line:
g2d.drawImage(pixel.getTexture(), pixel.getX(), pixel.getY(), 20, 20, null);
The values provided by pixel are correct. drawImage will receive the correct position and the correct texture/Image.
Becaus I am new to Graphics I would like to ask you guys helping me out with this problem.
Big Thanks in advance!
Greetz
Cronax3
So, your basic problem comes down to...
public static class Pixel extends JPanel {
Why does Pixel need to extend from JPanel?
If you remove extends JPanel, it will trigger a compile error, saying "can not find symbol getX" etc, but it's not the method you had defined, getPosX was.
getX is a property of JPanel, but since I can't see any need to use JPanel in this way, there's simply not need for it. In fact, you could have Pixel just paint itself, but that's a discussion for another day
The short answer:
use g2d.drawImage(pixel.getTexture(), pixel.getPosX(), pixel.getPosY(), 20, 20, null);
and not g2d.drawImage(pixel.getTexture(), pixel.getX(), pixel.getY(), 20, 20, null);
(To use the values assigned to posX and posY in Pixel)
The long and better answer: implement what suggested by MadProgrammer and Andrew Thompson (see comments):
//see :https://stackoverflow.com/help/mcve
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Zeichnen extends JFrame {
PixelManager pman;
public Zeichnen(){
setTitle("Tutorial");
//setSize(400, 400); //not needed. see pack()
pman = new PixelManager();//add pixle manager to frame
add(pman);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack(); //Causes this Window to be sized to fit the preferred size of content
}
//add this method to allow adding pixels
void addPixel(int posX, int posY, BufferedImage texture) {
pman.addPixel(posX, posY, texture);
}
public static void main(String[] args)
{
Zeichnen fenster = new Zeichnen();
try {
//to make it mcve use links as suggested by Andrew Thompson
fenster.addPixel(100, 100, ImageIO.read(new URL("http://i.stack.imgur.com/gYxHm.png")));
fenster.addPixel(200, 200, ImageIO.read(new URL("http://i.stack.imgur.com/5v2TX.png")));
} catch (Exception e) { e.printStackTrace(); }
}
}
//as posinted out by MadProgrammer this class is just a data structure to hold
//pixel information. It does not need to extend JPanel
class Pixel {
private int _posX, _posY;
private BufferedImage _texture;
public Pixel(int posX, int posY, BufferedImage texture) {
_posX = posX;
_posY = posY;
_texture = texture;
}
//Getter und Setter
public int getPosY() { return _posY; }
public int getPosX() { return _posX; }
public void setPosY(int posY) { _posY = posY; }
public void setPosX(int posX) { _posX = posX; }
public BufferedImage getTexture() { return _texture; }
public void setTexture(BufferedImage texture) { _texture = texture; }
}
class PixelManager extends JPanel {
private ArrayList<Pixel> pixels = new ArrayList<>();
PixelManager() { }
void addPixel(int posX, int posY, BufferedImage texture) {
pixels.add(new Pixel(posX, posY, texture));
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Pixel pixel : pixels) {
g2d.drawImage(pixel.getTexture(), pixel.getPosX(), pixel.getPosY(), 20, 20, null);
}
g2d.dispose();
}
#Override
public Dimension getPreferredSize() { return new Dimension(400,400); }
}
Thanks guys for your answers.
Yeah, thats a dumb mistake by me. It was not intended that Pixel extends JPanel. This line was added for testing some stuff and I forgot to delete it -.- Because of this I didnt notice that getX() is wrong, too. Totaly messed up because I didnt take care of cleaning my test Pixel-class.
Thank you guys!

JFrame not displaying anything

I cannot seem to get a rectangle to be displayed in the JFrame. Per the parameters of this project, I have to have this class implement the Icon interface. When I run the code as is, I get the JFrame, but nothing shows up inside. It should display a black square. I'm assuming the problem has something to do with how I am initializing the graphics instance variable. I don't have much experience working with GUI graphics, so I'm not entirely clear on how to do this correctly.
And yes, I do know that the getIconWidth and getIconHeight methods are redundant since I am using constants, but I have to have these methods in order to implement the interface.
public class MugDisplay extends JFrame implements Icon {
private int width;
private int height;
private JPanel panel;
private Graphics graphics;
private static final int ICON_WIDTH = 100;
private static final int ICON_HEIGHT = 100;
public MugDisplay() {
this.configureGui();
this.panel = new JPanel();
this.panel.setLayout(new BorderLayout());
this.add(this.panel, BorderLayout.CENTER);
this.graphics = this.getGraphics();
int xPos = (this.panel.getWidth() - this.getIconWidth()) / 2;
int yPos = (this.panel.getHeight() - this.getIconHeight()) / 2;
this.paintIcon(this.panel, this.graphics, xPos, yPos);
}
#Override
public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.fillRect(x, y, ICON_WIDTH, ICON_HEIGHT);
}
#Override
public int getIconWidth() {
return ICON_WIDTH;
}
#Override
public int getIconHeight() {
return ICON_HEIGHT;
}
private void configureGui() {
this.setPreferredSize(new Dimension(600, 600));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().setLayout(new BorderLayout());
this.pack();
this.setVisible(true);
}
}
In the interest of having a MCVE, here is the driver class that calls this class.
public class Main {
public static void main(String[] args) {
MugDisplay md = new MugDisplay();
md.setVisible(true);
}
}
this.graphics = this.getGraphics() is not how custom painting works in Swing. What you should do is create a panel, override its paintComponent method, make the call to super, and then do your painting. For instance:
panel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int xPos = ...
paintIcon(this, g, xPos, yPos);
}
}
Calling getGraphics will provide you with a short-lived Graphics object that can soon become invalid, which is why you should opt for overriding paintComponent instead, which will always give you a usable Graphics object. See Performing Custom Painting.
On a separate note, it looks like you're calling setVisible(true) before you're finished adding the necessary components to the JFrame. To ensure that your components show up, call setVisible(true) after adding them all to the frame.

Problems writing to image, then printing to SVG in Java

As part of a program I am writing, I wish to print an image to SVG format. I need it to be in SVG format, so that I can modify it using Adobe Illustrator later on. As it stands, although I can draw a rectangle directly in the print method and export that successfully to SVG format.
When I draw the same rectangle in my getTagCloud method, the result (when printed to SVG) is a rectangle made up of a huge number of tiny rectangles. I am at a loss as to why this might be so, though hopefully the answer will be blindingly obvious to someone reading this!
Ultimately, I need to print out more than just a rectangle but the exported "Group" in Illustrator is so large (containing as it does all these tiny rectangles of varying sizes) that I am unable to find the other objects I have drawn (as everything, no matter what colour I originally used, is rendered in black). Any help would be greatly appreciated.
Below is the relevant code. I have not included the import statements as I don't have any problems compiling the code.
public class TagCloud {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
System.out.println("Created GUI on EDT? "+
SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Tag Cloud Generator");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyPanel myPanel = new MyPanel();
Toolkit tk = f.getToolkit();
Dimension wndSize = tk.getScreenSize();
f.setBounds(0, 0,
wndSize.width, wndSize.height);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
f.add("Center",myPanel);
f.pack();
f.setVisible(true);
myPanel.printTagCloud();
}
}
class MyPanel extends JPanel implements Printable{
private int squareX = 50;
private int squareY = 50;
private int squareW = 20;
private int squareH = 20;
private int x_offset = 30;
private int y_offset = 30;
private BufferedImage img = null;
private int defaultFontSize = 16;
public int print(Graphics g, PageFormat pf, int page) throws
PrinterException {
if (page > 0) { /* We have only one page, and 'page' is zero-based */
return NO_SUCH_PAGE;
}
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
if (img == null){
getTagCloudImage();
}
g.setColor(Color.red);
g.fillRect(0, 0, 250, 400);
//g.drawImage(img, 0, 0, null);
g.dispose();
return PAGE_EXISTS;
}
public void printTagCloud(){
PrinterJob job = PrinterJob.getPrinterJob();
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
PageFormat pf = job.pageDialog(aset);
job.setPrintable(this);
boolean ok = job.printDialog(aset);
if (ok) {
try {
job.print(aset);
} catch (PrinterException ex) {
}
}
}
public MyPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
moveSquare(e.getX(),e.getY());
}
});
}
private void moveSquare(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
squareX=x;
squareY=y;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
}
}
public Dimension getPreferredSize() {
return new Dimension(1000,800);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img == null){
getTagCloudImage();
}
else{
g.drawImage(img, x_offset, y_offset, null);
}
}
public void getTagCloudImage(){
img = new BufferedImage(250, 250, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics();
Graphics2D g2 = (Graphics2D)g;
Rectangle r = new Rectangle (0,0,250,250);
g2.draw(r);
g2.setColor(Color.black);
g2.fill(r);
g2.dispose();
}
I can't help much without knowledge about Java BufferedImage,Graphics, PrinterJob and other related classes implementation. (You may start a bounty for this question to possibly draw attention of people having more intristic knowledge about java awt graphic stuff).
As you obviously must have noticed using BufferedImage (or not using it) is what makes a difference in SVG output. In the version that works you draw the rectangle directly on Graphic context provided to you as print() method argument and I believe that's how it was designed to be used by authors of Printable interface and printing framework.
In the second approach (that doesn't work correct) you first draw rectangle onto new BufferedImage object and then draw this image on the provided Graphic context. So you do something much less straightforward than just drawing directly on the context. There is well known truth or intuition among developers that the less straightforward way do you use some API, the bigger is a chance that you do something unexpected by its authors :(.
My hypotesis is following: BufferedImage is (as you can deduce from its Javadocs)just a raster image, ie. grid of pixels. That's why svg file is populated with lots of small rectangles (trying to mimic pixels). The Graphics object provided by draw() method may be more abstract and operate on shapes rather than pixels, which is much more appropriate to be written to vector graphics formats like SVG. But that's just hypotesis.
The question is, do you really need to use BufferedImage? If I understand correctly, you want user to be able to edit rectangle on screen and when ready export it to SVG. Can't you just remember for example upper left corner and dimensions of rectangle edited by user and then use this data to recreate this rectangle directly on Graphics object provided by print(), like:
public int print(Graphics g, PageFormat pf, int page)
throws PrinterException {
...
g.fillRect(userRect.x,userRect.y,userRect.width,userRect.height);
...
}
?
(userRect is object of your own custom class which just stores data about image edited by user)

Java making a 'dot/pixel' In swing/awt

I want to know how to make a dot/pixel at a certain x,y co-ordinate on my JFrame.
Anyone know some simple code for this?
I have created a small example program:
public class Test extends JFrame {
public Test() {
this.setPreferredSize(new Dimension(400, 400));
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
#Override
public void paint(Graphics g) {
super.paint(g);
// define the position
int locX = 200;
int locY = 200;
// draw a line (there is no drawPoint..)
g.drawLine(locX, locY, locX, locY);
}
public static void main(String[] args) {
Test test = new Test();
}
}
You could also use the update or paintComponents method which would be much nicer. But then you have to make sure, that it gets called. If you have problems and it does not get called you could use the following solution: Why is paint()/paintComponent() never called?
Best compromise between simplicity and usefulness would probably be to extend JPanel, and override paintComponent( Graphics ). Then place that panel in your JFrame (with an appropriate layout. There are some usage notes here: http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/JComponent.html#paintComponent%28java.awt.Graphics%29
see
void update(Graphics g)
method of JFrame class.
graphics API ( like draw point, draw line, draw arc, etc ) are in Graphics class.
EDIT: http://www.javadb.com/drawing-a-line-using-java-2d-graphics-api
Ask yourself if your really want to extend JFrame or JPanel. If you decide that you don't then you could create a basic JComponent. You may have varying success with this depending on what layout manager you use.
public class PixelComponent extends JComponent
{
private Color color;
public PixelComponent(Color color)
{
super();
this.color = color;
}
public PixelComponent()
{
this(Color.BLACK);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, 1, 1);
}
}
Send the Graphics Reference and axis x and y to make a pixel:
private void doPixel(Graphics g, int x, int y){
g.fillRect(x, y, 1, 1);
}

Categories

Resources