paintComponent() leaving behind previously drawn images after repaint() - java

I have a JPanel which draws .png images. each image has 2 copies to signify whether or not it has been selected. One image is normal and one has a colored border to signify the selection has been made. (You can think of these images as simple shapes for the sake of argument)
Which version of the image is drawn is determined via MouseListeners. If the user selects image1, then image1 will display its highlighted version.
In general this is working, however upon repaint() the highlighted version of the image is left behind. Since the highlighted version is slightly larger than the normal version, you can see it sticking out behind the newly drawn normal image (overlapping).
I thought repaint() was supposed to completely dispose of the current drawings and start from scratch, this doesn't seem to be the case here. Below is the general idea, blackClicked is toggled inside a MouseListener.
So my question is how do I make repaint() get rid of its currently drawn images and start from scratch.
Also, if there is a simpler way to achieve all of this please let me know, making 2 copies of images is tedious work.
#Override
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
if(blackClicked)
g2.drawImage(blackSelected,0, 0, null);
else
g2.drawImage(black,0, 0, null);
g2.drawImage(green,0, 0, null);
}

how do I make repaint() get rid of its currently drawn images and start from scratch.
You mean, how to make repaint fill the component with it's background color before painting? How about adding
g2.setColor(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
in top of paintComponent()?

Related

Drawing images to 4 different points

I have a quadrilateral drawn in Path2D, and I would like for there to be an image on it. More specifically, I am trying to draw an image of my choice to 4 different points on a quadrilateral. In my case, it is a parallelogram. I do not want the image to go over the paralellogram. A better way to see what I am trying to say is to see the screenshot below.
I would like the image to be transformed to fit the green area. Not clipped.
I want the image to be pinned over the green paralellogram. However. I do not want the image to go over into the blue paralellogram, or the white space foe that matter.
So far I have tried
Researching for a way to place images directly onto Path2D.Double() objects. No answer
Rotating the image to fit the paralellogram. Didnt work.
Using AffineTransform in java. Dont get it ;-;
Thanks. I am new to java so do try to be lenient?
One way is to:
create a separate BufferedImage.
Apply a transform to the new image.
Draw your image to that new image.
Use the Shape object for the green area as a clip on the main drawing area
Draw the transformed image onto the main drawing area.
It's been a while since I have done transformations. You may have to set the transformation first and then draw the image after. Transformation has to come first.
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.transform(AffineTransform.getShearInstance(1.0, 0));
g2.drawImage(image, 0, 0, this);
}
Here is a simple example of how transforms work. You will have to spend some time on figuring out what values you need to make it work or if you might need to manually create a transformation matrix yourself.

How do I control individual pixels outside of a frame in Java?

I need a way to control individual pixels on a monitor that are not inside a frame. Is there any way I can directly change a pixel at a certain x,y to a certain colour?
Try using Java's "Full-Screen Exclusive Mode" API:
http://docs.oracle.com/javase/tutorial/extra/fullscreen/exclusivemode.html
In this example:
http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/extra/fullscreen/examples/CapabilitiesTest.java
You see a Java application acquiring the "ContentPane" container from the graphics device, then it creates a JPanel and adds it to content pane. Once you do that, you're free to override the paintComponent of the JPanel with something like this:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(50, 50, 50, 50);
}
You can of course set whatever you draw to any color, and you can draw something other than a rectangle too.
The drawback is, you don't get transparency, in case you're looking to draw ONLY that pixel and leave the rest of the screen preserved. This StackOverflow question investigates this issue further: java fullscreen window with transparency

Drawing images onto AWT and initialising Graphics

I'll start off by telling you what Im trying to do if thats OK, as Im not certain the route Im struggling with is even the best way of achieving my ends.
I have a JFrame containing two JPanels. One contains a number of buttons (buttonPanel), the other is, initially, blank (displayPane). When buttons are pressed the stuff shown in displayPanel changes. The way this is working is each press of a button creates a new object that extends JPanel and then adds that to displayPane
So all the above is working fine and dandy (although I freely admit it may not be the best way of doing it) except for one particular case.
In this particular case I need to create a JLayeredPanel and then draw a clipped image on it. JLayeredPanel because I want to draw some stuff on top of it, clipped because I only want to show part of the area (which exact part is passed to the constructor).
Now, the problem Im having is this. The only way I know to draw a clipped image is through g=thingie.getGraphics(), g.setClip(Shape shape), g.drawImage(various). However, all of that relies on being able to get graphics. But because I am assembling the object first there is no graphics object associated with the JLayeredPane (because its not displayed) so getGraphics is returning null and g.setClip() is throwing a Null Pointer Exception.
Obviously I am doing this wrong somehow and somewhere. Any help would be appreciated, sorry if the question is confusing. I tried to include as much detail as possible and now I am a little concerned I've muddied the issue. I'll keep an eye on this and clarify if required.
Warning!: Wrong answer, see below the line
Why don't you just create a new Graphics object, paint on it and then use it with the update() method?
Graphics g = new Graphics();
g.drawStuff();
thingie.update(g);
This showd be correct
As stated on the comments the previous solution was wrong but it can be done with an Double buffer, create a buffered image and draw on it, then override the paint method of the jLayeredPane pane to draw the image.
private void addStuff() {
BufferedImage bi =
new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);
Graphics bufferedGraphics = bi.getGraphics();
//Paint stuff
bufferedGraphics.drawLine(0, 0, 50, 50);
javax.swing.JLayeredPane layered;
layered = new JLayeredPane() {
#Override
public void paint(Graphics g) {
g.drawImage(bi, 0, 0, null);
}
};
this.add(layered);
this.validate();
this.repaint();
}

Fading a portion of Graphics in Java Swing

I am trying to implement the fade in/fade out animation in swing.
I am using a JPanel which does not have any components in it. It is completely drawn by paintComponent() method.
Now in one of the portion of this JPanel, I want to implement the fade in/fade-out animation. When I tried using AlphaComposite, the animation is being triggered for whole JPanel.
Can I limit this animation in a small clipped region in that panel?
Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(AlphaComposite.getInstance(
AlphaComposite.XOR, alpha));
Have you tried using an Graphics object (like rectangle, circle etc..) for your fade in/out? That way it won't be triggered for the complete panel.
Good luck!
Perhaps, but that may be more difficult to achieve than what it's worth. Create a JComponent of the size you want to animate (or fade), add it to your JPanel, and have repaint() called on your smaller component during animation instead of the larger JPanel.
You can use setClip() before painting to restrict the fading area.
Suppose you want a small fading rectangle. Using Area class create 2 Shapes. Intersection of original clip and fading rect and subtraction (subtract the fading rectangle from the original clip).
Call super.paintComponent() twice with 2 different clips. For the second paint you can set your alpha filter.

Add image over another image?

Im trying to make a turn-based game, progressing OK so far, however now I came to the part where I want to be able to move units around. I use images to determine different types of terrain, and another image to display a unit, but I can't get the unit to come out OVER the terrain, it only pops up under the terrain. Seems like I'm the first one ever to bump into this problem, so am I going at it the wrong way?
The tile with a terrain-image:
protected void paintComponent(Graphics paintIt) //paints this sexy-hex
{
super.paintComponent(paintIt); //not sure if we need this? lol
paintIt.setColor(is); //sets the color (later not even used, we need pics and shit)
//paintIt.fillPolygon(hex); //fills the hexagon with the desired color, will not be used later on either
if(isExplored)
paintIt.drawImage(image, 0, 0, null);
else
paintIt.fillPolygon(hex); // I want to paint it black
if (hoover) //are we pointing at this cell?
{
paintIt.setColor(Color.WHITE); //we want the nice line around the cell to be white
Graphics2D g2 = (Graphics2D) paintIt;
g2.setStroke(new BasicStroke(3)); //and 3 pixels wide (we are allowed to change it, supposedly in proportion to "rad"
g2.drawPolygon(hex); //draws the line around the hexagon
}
}
The unit:
protected void paintComponent(Graphics paintIt)
{
if(!selected)
{
paintIt.drawImage(image, 0, 0, null);
paintIt.drawImage(image2,0,0,null);
/*
super.paintComponent(paintIt);
paintIt.setColor(Color.BLACK);
paintIt.drawPolygon(shape); */
}
else
{
super.paintComponent(paintIt);
paintIt.setColor(Color.RED);
paintIt.drawPolygon(shape);
}
}
Sorry for the comments, and sorry for some code that's not even used, just think it's best to have it until the project's finished if we need to get back to somewhere.
The unit image is smaller than the terrain, so it fits. I've tested without painting out the terrain so I know the unit is painted under it.
If there's still code you would need to get an idea what I'm doing, tell me, just thought this was the relevant parts.
EDIT #2
The tile is a class created from another class which extends JFrame. The unit-class is created from that JFrame class but is beeing stored in the tile. Both tile and unit are JComponents.
Fix'd, I had to draw the units image within the terrain-class to make it come out on top. Since I already stored the unit in the class I don't know why I didn't do it this way from the beginning.
Thanks anyhoo <3

Categories