I am drawing images in paintComponent(Graphics g) method in order to make them compatible with Retina displays
g.drawImage(image, 0, 0, imageWidth/2, imageHeight/2, null);
Everything works perfectly but the image's shadows stack on each other. It makes the picture ugly.
So I need to clear image before drawing new. Here comes the problem:
I had no problems clearing image, however the problem is to prevent the background of the parent element from being overlapped. Now it looks in such a way http://cl.ly/image/0K1u0q2M150W .
I used methods from other topics:
g2d.setBackground(new Color(255,255,255,0));
g2d.clearRect(0, 0, ICON_WIDTH, ICON_HEIGHT);
as well as
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g2d.setBackground(new Color(255,255,255,0));
g2d.clearRect(0, 0, ICON_WIDTH, ICON_HEIGHT);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
and several others.
this is how it should look like http://cl.ly/image/2V1R1v0X452N
and this is how it looks after invoking repaint() method several times. I need to call it to change the image from one to another.
my paintComponent method:
Image image;
if (flag) {
image = image1;
} else {
image = image2;
}
g2d.drawImage(image, 0, 0, IMAGE_SIZE, IMAGE_SIZE, null);
While writing this question I accidentally found the answer.
For me calling
super.paintComponent(g);
in the beginning of the paintComponnent() method was the solution. Because it clears the image somewhere inside.
The code from super.paintComponent(g) that clears image is the following:
g.setColor(c.getBackground());
g.fillRect(0, 0, c.getWidth(),c.getHeight());
if I put it instead of super.paintComponent - it also works. I just needed not to set my own color before filling the rectangle.
Related
So after looking at multiple ways to paint or draw things onto the canvas/screen, I tested out my own way that seems to work, no problem. I simply just g.clearRect(0, 0, width, height) on an update method that is put in my game loop so that the game can refresh every frame, and the BufferStrategy will only show after all the items are refreshed fully, so wouldn't this be an okay strategy?
Here is the idea of the method that I use that uses a canvas's BufferStrategy.
public void update() {
//Update all the entities that are on the screen, like their x and y, etc.
player.update();
g.clearRect(0, 0, width, height);
// Draw the things I want here, such as player, etc.
g.drawImage(image, player.getX(), player.getY(), null);
bs.show();
}
Is this method inefficient somehow? I struggled a lot to find a method of displaying objects and such on screen, but I stumbled across this way which seems very easy for me.
I need to draw strings on a painted image. The project I am working on also requires the string to move around the screen at least 22 times in a second. Hence, its position can be anywhere on the image. So, redrawing the image with the string on it won't be possible as I feel there are better ways of doing this and that would unnecessarily consume resources redrawing the whole image. I have also tried using panel.getGraphics and then painting on the image but then all the drawn text is all over the screen(the code is below). I was wondering if someone could guide me in the right direction on how I can draw text over a paintedImage but it also needs to reset its position when required. The code I have tried that doesn't reset its previous position is below.
Original Panel with the Image:
public class PanelForImages extends JPanel{
private BufferedImage image;
public PanelForImages(File image) throws IOException{
//this.image = image;
//URL resource = getClass().getResource("so2.jpg");
this.image = ImageIO.read(image);
}
#Override
public void paintComponent(Graphics g){
//super.paint(g);
//super.paintComponents(g);
super.paintComponent(g);
//g.drawImage(image, 3, 4, this);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
g.drawString("HELLOOOOOOOOOOOOOOOOOOOOOOOO", 400, 400);
//repaint();
}
}
Method with which I am trying to draw the string over the image.
public void drawFixationsOnFrame(GazeData gazeData){
Graphics g = this.panelForImages.getGraphics();
g.drawString("TEsting 123", (int)gazeData.smoothedCoordinates.x, (int)gazeData.smoothedCoordinates.y);
g.dispose();
jF.revalidate();
}
I have also tried making a new panel and then adding it to the current one but it doesn't seem to work. I am not sure how I can make it so it comes on top of the panelForImages without it hiding panelForImages.
The project I am working on also requires the string to move around the screen at least 22 times in a second. Hence, its position can be anywhere on the image. So, redrawing the image with the string on it won't be possible as I feel there are better ways of doing this and that would unnecessarily consume resources redrawing the whole image.
Then don't redraw the whole image. The JComponent repaint(...) method has an override, one that allows you to repaint only a select rectangle (check out the JComponent API for more on this). You will want to move the image in a Swing Timer, then repaint its old location (to get rid of the old String image) and repaint its new location. If you need the dimensions of the String, then use FontMetrics to help you get its bounding rectangle.
I note that your code has two other issues that are worrisome, some of it commented out:
Calling getGraphics() on a component to get its graphics component and draw with it -- you don't want to do this as this will result in a Graphics object that is short-lived risking broken images or a NPE
Calling repaint() from within the paintComponent. This is a bad and completely uncontrolled way of doing animation. Instead use a Swing Timer so you can have complete control of the animation and so you don't use paintComponent for something it was not intended to be used for.
I am playing around with graphics in Java using JFrames and am trying to completely understand when Graphics changes actually occur.
Let's say I have a timer running every second, and every second the graphics change. The tick method, for example, will run every second...
public void tick(Graphics g) {
g.fillRect(0,0,10,10);
//Do Some Computations
g.fillRect(0,0,someComputedWidth,someComputedHeight);
}
Are the graphics instantly updated on the computers display? When the first fillRect method is called, is that rectangle instantly created?
I want to be able to draw all my graphics, and then make them have their effect at the same exact time. I want the tick method to buffer all updates, and then execute them all at once. How do I accomplish this?
To buffer your updates you can use BufferedImage:
#Override
public void paintComponent(Graphics g){
BufferedImage image = new BufferedImage(this.size.width, this.size.height, BufferedImage.TYPE_INT_RGB);
Graphics bgr = image.getGraphics();
for(Tile t : this.tiles){
t.draw(bgr);
}
super(bgr);
g.drawImage(image, 0, 0, null);
bgr.dispose();
image = null;
}
I used this method in one of my school projects. It draws to an off-screen image and then draws the image to display.
With few drawable objects being drawn, and no, or little animation, updating directly to the display does not always have noticable effects, however with more complex tasks the image "flickers" and double buffering is a perfect cure for that.
I know Im not the first person to ask this type of question, but I think mines a little bit different.
I have a png image I drew on MS paint that is a player and I want the background of the image to be transparent when I use a graphics objects to draw the image. I tried some stuff with magic pink but It doesn't seem to be working the same in java. Im not new to java, but Im inexperienced so could you explain any packages or methods that you use thanks!
You will need to use AlphaComposite to have the transparency effect:
Assuming that you already know Graphics2D and Graphics uses BufferedImage
Creating temporary graphics object g.create() and then dispose the object for safely restore the state of graphics object changed after the object creation.
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.drawImage(tileImage, 0, 0, getWidth(), getHeight());
g2d.dispose();
// draw player image
}
With Java6, a PNG picture should be used for TrayIcon, but as mentioned in this SO question, check:
the background color chosen to represent the transparent pixels
the transparency options
the resolution of the icon
alternate format like SVG (provided you are using external library like Batik, and
conversion mechnism to java.awt.Image)
Hi I've been trying to get rid of my flickering on a JFrame app. Have searched around and seen that setDoubleBuffered(true) can be used for paintComponent of Jpanel, but not paint method of JFrame, nor applets.
Managed to diminish but not eliminate flickering by introducing the instructions this.createbufferstrategy(2) within paint method, and further reduced flickering with the instruction this.setignorerepaint(true) inside paint.
But I finally found an example of code that completely removes flickering and it works by drawing the static elements within the update function.
Tested fillRect within update in an applet and it works, but when copy pasted into a regular java application it does not work there within the jframe's update function.
Here's the code
Graphics graphics;
Image image;
public void update(Graphics g)
{
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
graphics = image.getGraphics(); }
graphics.setColor(Color.blue);
graphics.fillRect(0, 0, this.getWidth(), this.getHeight());
g.drawImage(image, 0, 0, this);//}
With an empty paint function this draws to the screen and fills it with blue in an applet, it also gets rid of flickering. But in a normal application of jframe it does nothing.
What needs to be done to allow either fillRect or drawImage to work from within update in a non applet regular application environment?
BTW, I'm a bit new to this if the graphics object is being modified itself by calling fillRect, how does that modify the image object? Because drawImage is necessary for the screen to turn blue.
PS I've tried not using both createbufferedstrategy and setignorerepaint, and nothing changes.
When using setIgnorePaint(true), its not allowing you to mess with the Graphics.
I'm guessing by the looks of your update(Graphics g) parameter, you call that within your paint method, using the paintMethod's graphic g to paint (inside paint method, you call update(g))
If you ignore paint, its not gonna allow you to use the paintComponent's Graphic parameter.
Post all code that includes graphics (Where you made your strategy, where you're calling this method, ect..)
The flickering is a pretty mainstream issue with the strategy, and I can't promise that I'll be able to fix it (my friend brought the problem up to me a while ago, but i didnt care enough to try and figure it out), but that should at least explain why your graphics aren't rendering