Java Swing drawImage sometimes slow in XORMode - java

I have extended ImageIcon to colorize my icons for different purposes as needed.
I've tried quite a lot now, but when resizing the window it needs > 3 sec. to repaint about 60 32x32 Icons.
First off, this only happens if I color them in XOR Mode. If I leave them as they are it's a matter of milliseconds.
I tried converting the images to a better format with GraphicsConfiguaration.createCompatibleImage but that didn't help.
Now a strange thing: if I draw onto the component.getGraphics instead to the Graphics provided in the paintIcon method, it does so lightning fast even in XOR Mode, but only shows it in a short flicker until it gets overdrawn.
I draw them by adding JButtons into a JPanel with a FlowLayout.
Anything else I can try?
Slow:
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
g.setXORMode(color);
g.drawImage(getImage(), x, y, null);
}
Fast but flickering:
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
gr = c.getGraphics();
gr.setXORMode(color);
gr.drawImage(getImage(), x, y, null);
}
Fast but without Xor
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
g.drawImage(getImage(), x, y, null);
}
Edit:
Found a solution now with a combination of a BufferedImage and AlphaComposite:
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
int w = getIconWidth();
int h = getIconHeight();
BufferedImage bimage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D bg2 = bimage.createGraphics();
bg2.setColor(co);
bg2.fillRect(0, 0, w, h);
bg2.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
bg2.drawImage(getImage(),0,0,null);
bg2.dispose();
g.drawImage(bimage,0,0,null);
return;
}
Leaving the question open for some hours to see if someone comes up with a better solution though.

Related

How is Java Graphics' fillRect(int, int, int, int) implemented [Low level graphics programming]?

I'm trying to write a fill rectangle function for my project. And I was wondering how the fillRect(int, int, int, int) method of Java's java.awt.Graphics class is implemented. I tried finding the source code by right clicking in a Java program and "Open Declaration" (in the eclipse IDE) but all I can find is the abstract declaration of the method.
Basically I want to know how a simple Java code like this:
protected void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
g.fillRect(10, 10, 620, 460);
}
can produce a green rectangle like the on in the window below:
I only know of two shape filling methods : the Flood-fill & Boundary-fill algorithms .
The issue with those is that they both needs existing boundaries (monochrome for Boundary-fill and mono- or polychrome for Flood-fill).
so that with the boundary-fill algorithm it would be something like :
void fillRect(int x, int y, int w, int h){
drawLine(x, y, x+w, y); // Draw top boundary
drawLine(x, y+h, x+w, y+h); // Draw bottom boundary
drawLine(x, y, x, y+h); // Draw left boundary
drawLine(x+w, y, x+w, y+h); // Draw right boundary
boundaryFill4D(x+1, y+1, GREEN, GREEN); // for simplicity I'm hardcoding color
}
void boundaryFill4D(int x, int y, int fill_color, int boundary_color)
{
if(getpixel(x, y) != boundary_color &&
getpixel(x, y) != fill_color)
{
putpixel(x, y, fill_color);
boundaryFill4D(x + 1, y, fill_color, boundary_color);
boundaryFill4D(x, y + 1, fill_color, boundary_color);
boundaryFill4D(x - 1, y, fill_color, boundary_color);
boundaryFill4D(x, y - 1, fill_color, boundary_color);
}
}
As you can see from this example I had to first draw the 4 sides before I could "bucket fill" the the outlined rectangle. I was wondering if there is a better way to do this.

Swift: Double Buffering like in Java

In Java, I can write pixel data to an image that is then printed to the screen by overridden methods (paint and paintComponent). I can refresh the screen easily by updating the image and calling refresh(), which calls the paint/paintComponent cycle.
I'm wanting to do this in swift (3) with a UIImage. I can update the image, but I can't figure out how to repeatedly project the image onto the screen, print the screen, and repeat as I need to refresh the screen.
Firstly, what type of swift project (Single view app., Game, etc.) is best for repeatedly refreshing the screen?
And secondly how do I go about creating a (regulated) loop in Swift that refreshes the screen every so often?
In java this would look like (in a class that extends Frame):
static int width = 1440;
static int height = 900;
private BufferedImage canvas;
static Color[][] RGBMap = new Color[width][height];
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setBackground(Color.WHITE);
g2.clearRect(0, 0, width, height);
g2.drawImage(this.canvas, null, null);
paint();
}
public void paint() {
int i = 0;
while (i < width) {
int t = 0;
while (t < height) {
this.canvas.setRGB(i, t, RGBMap[i][t].getRGB());
t++;
}
i++;
}
//Refreshes RGBMap
iterate();
repaint();
}

how to make ellipse in java swing JPanel TitledBorder?

how to draw this in java swing TitledBorder or any other panel ?
i tried the following code and didn't work, kept drawing half ellipse and the other half was cut.
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.BLUE);
FontMetrics m = c.getFontMetrics(getTitleFont());
Ellipse2D shape = new java.awt.geom.Ellipse2D.Float(2, -20,m.stringWidth(title)+10, m.getHeight()+40);
g2.fill(shape);
g2.draw(shape);
super.paintBorder(c, g, x, y, width, height);
}

How to write text inside a rectangle

Hi I am creating a java desktop application where I am drawing rectangle. I want to write some text inside rectangle.
How can I achieve this?
Here is my code:
class DrawPanel extends JPanel {
private void doDrawing(Graphics g) {
int a=90;
int b=60;
int c=10;
int d=15;
ArrayList<Graphics2D> g1 = new ArrayList<Graphics2D>();
for(int i=0;i<=9;i++){
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(212, 212, 212));
g2d.drawRect(c, d, a, b);
d+=65;
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
Use your Graphics2D object and call drawString(String str, int x, int y). Something like
g2d.drawRect(c, d, a, b);
g2d.drawString("Hi", (a+c)/2, (b+d)/2);
Note that the Javadoc specifies
Draws the text given by the specified string, using this graphics context's current font and color. The baseline of the leftmost character is at position (x, y) in this graphics context's coordinate system.
so you would need to take into account the space the font takes on screen. Use FontMetrics for that.

int cannot be dereferenced

I am beginning in java (I'm learning in microedition) and I got this error: "int cannot be dereferenced" in the following class:
class DCanvas extends Canvas{
public DCanvas(){
}
public void drawString(String str, int x, int y, int r, int g, int b){
g.setColor(r, g, b); //The error is here
g.drawString(str, x, y, 0); //and here
}
public void paint(Graphics g){
g.setColor(100, 100, 220);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
What am I doing wrong here?
Well I came from PHP and ECMAScripts where I was able to pass my function arguments this way so I really don't understand this error.
The g in drawString is the color value you've passed in, not your Graphics reference. So the error is when you're trying to call a method on an int, which you can't do.
// Passing an integer 'g' into the function here |
// V
public void drawString(String str, int x, int y, int r, int g, int b){
// | This 'g' is the integer you passed in
// V
g.setColor(r, g, b);
g.drawString(str, x, y, 0);
}
You are calling the setColor and fillRect methods on g, which is a parameter of type int.
Since int is not a reference type, you cannot call methods on it.
You probably want to add a Graphics parameter to the function.
While g is in the paint-method an object of the class Graphics (that contains methods named setColor, fillRect and also drawString) in the method drawString is g defined as an Integer that conatins the value for the color green. Especially in the line g.setColor(r, g, b); you use g to set a color on it and also as the argument for setting the color. int has no method setColor (that also doesn't make sense), so you get an error. You probably want to get an Graphics-object also in this method. As you extend canvas, you can get a graphics-object by calling getGraphics(), so your example could look like this:
public void drawString(String str, int x, int y, int r, int g, int b){
getGraphics().setColor(r, g, b);
getGraphics().drawString(str, x, y, 0);
}

Categories

Resources