Painted Content Invisible While Resizing in Java

Painted content invisible while resizing in Java

Okay, I finally fixed it.

Instead of redrawing it every time in the paint(Graphics g)-method, you need to buffer the output and only redraw that image (I kinda hoped Java would be already doing that, just like Obj-C).

public BufferedImage buffer;

public void redraw() {
buffer = new BufferedImage(
200, // height
300, // width
BufferedImage.TYPE_4BYTE_ABGR); // ABGR = RGBA, 4-byte (r, g, b, a) per pixel
Graphics g = buffer.getGraphics();
// do your drawing here
if (this.getGraphics()) {
// 'this' is already shown, so it needs a redraw
this.paint(this.getGraphics()); // little hack
}
}

public void update(Graphics g) {
this.paint(g);
}

public void paint(Graphics g) {
g.drawImage(buffer, 0, 0, this);
}

Now, when you minimize the window and maximize it again, the paintings remain. Only, the window's flickering now for .1-second or so, but I don't really care about that.

no repaint while resizing when using .setPaint(gradient)

I put together a test and found that the GradientPaint has woeful performance. Taking an average render time from 1.2 seconds (at 400x400 pixles) out to 20+ seconds.

I changed the GradientPaint for a LinearGradientPaint and found that the render time was around 1.3 seconds instead.

LinearGradientPaint lgp = new LinearGradientPaint(
new Point2D.Float(0, minY),
new Point2D.Float(0, maxY),
new float[] {0f, 0.5f, 1f},
new Color[] {Color.BLUE, Color.RED, Color.BLUE}
);
g2d.setPaint(lgp);
// Render all your samples, don't reapply or change you paint...

Sorry, my sample isn't very exciting...

Sample Image

You may find it better to render to a backing buffer in a background thread instead and paint the whole image to the screen once it's complete. This will stop the screen from becoming "paused"

Panel visible only after resizing [Java]

public void classAttitudes() {
variables.classesTitleLabel.setVisible(false);
variables.classesTitlePanel.setVisible(false);
variables.continueClassPanel.setVisible(false);

variables.titleAttitudePanel = new JPanel();

variables.titleAttitudePanel.setBounds(50, 50, 100, 100);
variables.con.add(variables.titleAttitudePanel);

// ADD MANUAL REPAINT TO THE FRAME !!!
variables.window.repaint();
}

P.S. When you resize you manin window (i.e. JFrame) an action is thrown and at the end of this action repaint() is invoke to repaint this frame with all content from UI thread (I do not remember it's name)

Keeping a circle centered when the frame is resized

This example centers the circle and adjusts the size to the smaller dimension, but you can make d constant. The essential step is to render relative to the panel's current size. Resize the enclosing frame to see the effect. Adding RenderingHints, seen here, makes the drawing smother.

    @Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Dimension size = this.getSize();
int d = 200;
int x = (size.width - d) / 2;
int y = (size.height - d) / 2;
g.fillOval(x, y, d, d);
g.setColor(Color.blue);
g.drawOval(x, y, d, d);
}

image

Changes to the example:

$ diff OldSwingPaint.java SwingPaint.java 
38a39,41
> Graphics2D g2d = (Graphics2D) g;
> g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
> RenderingHints.VALUE_ANTIALIAS_ON);
40c43
< int d = Math.min(size.width, size.height) - 10;
---
> int d = 200;

AWT paints only last-added Canvas

You neglect to pack() the enclosing Window. Note the characteristic symptom in your original code: resizing the frame, which generates an update, causes elypse2 to appear.

Addendum: You can see both Elypse instances by using a layout such as GridLayout.

testFrame.setLayout(new GridLayout(0, 1));

image

As tested:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Point;

public class Test {

public static void main(String[] args) {
Frame testFrame = new Frame("Grafx-Test");
testFrame.setAlwaysOnTop(true);
Elypse elypse = new Elypse(new Point(70, 80), 30, 30, Color.BLUE, false);
testFrame.add(elypse);
Elypse elypse2 = new Elypse(new Point(70, 50), 50, 30, Color.BLUE, true);
testFrame.add(elypse2);
testFrame.pack();
testFrame.setVisible(true);
}

private static class Elypse extends Canvas {

private Point start;
private int width;
private int height;
private Color c;
private boolean filled;

public Elypse(Point start, int width, int height, Color c, boolean filled) {
this.start = start;
this.width = width;
this.height = height;
this.c = c;
this.filled = filled;
}

@Override
public void paint(Graphics g) {
g.setColor(c);
if (filled) {
g.fillOval(start.x, start.y, width, height);
} else {
g.drawOval(start.x, start.y, width, height);
}
}

@Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
}
}

JComponents only appear after resizing

By default the size of all components is (0, 0), so there is nothing to paint.

Components need to be added to the frame BEFORE the setVisible() method. Then when the frame is made visible the layout manager is invoked and components are given a size/location.



Related Topics



Leave a reply



Submit