I would like to build a simple highlighter program. The idea is to set an image to change the cursor so that it will look like a highlighter. And then, when we move the cursor, it will trace a line along with our movement. The requirement here is to be able to draw the line on a transparent background (not fully transparent though, just about 55%).

My progress so far is being able to draw the line, with transparent background. However, the line is also transparent. Here's my code : left click to begin drawing, right click to stop, and press space to change color.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

public class FreehandExample extends JFrame implements MouseListener, MouseMotionListener, KeyListener {
     private int counter = 0;
     private int draw = 0;
     private int red[] = {58,71,231,243,255};
     private int green[] = {54,224,235,109,40};
     private int blue[] = {241,95,61,52,40};
     private Point start, end;
     private Graphics gd; 

     public FreehandExample()
     {
        setUndecorated(true);
        setBackground(new Color(255,0,0));
        setSize(new Dimension(300,200));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        addKeyListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);
        setOpacity(0.55f);
        setVisible(true);
     }

    public void mousePressed(MouseEvent e) {
        start = new Point(e.getX(), e.getY()); 
    }
    public void mouseClicked(MouseEvent e) {
        if(e.getButton() == MouseEvent.BUTTON1) draw = 1;
        if(e.getButton() == MouseEvent.BUTTON3) draw = 0;
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseDragged(MouseEvent e)  {}

    public void mouseMoved(MouseEvent e) {
       gd = this.getGraphics();

       if(draw==1){
          end = new Point(e.getX(), e.getY());
          gd.setColor(new Color( red[counter],green[counter],blue[counter]));
          gd.drawLine(start.x, start.y, end.x, end.y);
          start = end;
       }
    }

    public static void main(String []args){
         new FreehandExample();
    }

    public void keyPressed(KeyEvent e) {
         if(e.getKeyCode() == KeyEvent.VK_SPACE) {
            counter++;
            if(counter>4) counter=0;
         }
    }
    public void keyReleased(KeyEvent e) {}
    public void keyTyped(KeyEvent e) {}
}

I have tried the concept of per-pixel transparency... but the line drawing is not being drawn immediately... there is a delay before the line is drawn. However, it indeed produced the correct result e.g the line is not transparent while the frame is transparent. Could someone please help me modify this code to meet the requirement...? Thanks.

Recommended Answers

All 5 Replies

Here is the update on my progress... I've tried to apply per pixel translucency, and getting the desired result... The lines are not transparent, while the window is transparent. But there is a delay... I need to wait for a couple of minutes before the line is drawn. Even when I move the pointers, there is no line... but then they appear all at once after the delay. Could you please tell me what's wrong with my code...?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Paint;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class GradientTranslucentWindow extends JFrame implements KeyListener, MouseListener, MouseMotionListener {
	
    private int counter = 0;
    private int draw = 0;
    private int red[] = {58,71,231,243,255};
    private int green[] = {54,224,235,109,40};
    private int blue[] = {241,95,61,52,40};
    private Point start, end;
    private Graphics gd; 
    private JPanel panel;
	
    public GradientTranslucentWindow() {
   

        setBackground(new Color(0,0,0,0));
        setSize(new Dimension(500,500));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

         panel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                if (g instanceof Graphics2D) {
                    final int R = 240;
                    final int G = 240;
                    final int B = 200;

                    Paint p =
                        new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 50),
                            0.0f, getHeight(), new Color(R, G, B, 255), true);
                    Graphics2D g2d = (Graphics2D)g;
                    g2d.setPaint(p);
                    g2d.fillRect(0, 0, getWidth(), getHeight());
                   
                }
            }
        };
        setContentPane(panel);
        setLayout(new GridBagLayout());
        addKeyListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public static void main(String[] args) {
       JFrame.setDefaultLookAndFeelDecorated(true);
       GradientTranslucentWindow gtw = new GradientTranslucentWindow();
       
       gtw.setVisible(true);
       
    }
    
    public void mousePressed(MouseEvent e)   { start = new Point(e.getX(), e.getY()); }
    public void mouseClicked(MouseEvent e) {
    	if(e.getButton() == MouseEvent.BUTTON1) draw = 1;
    	if(e.getButton() == MouseEvent.BUTTON3) draw = 0;
    	
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseDragged(MouseEvent e)  {}
    
     public void mouseMoved(MouseEvent e) {
    	 gd = this.getGraphics();

    	 if(draw==1){
    		 end = new Point(e.getX(), e.getY());
    	
    		 gd.setColor(new Color( red[counter],green[counter],blue[counter]));
    		 gd.drawLine(start.x, start.y, end.x, end.y);
    		 start = end;
    		    		
    		 System.out.println(start.x + " - " + start.y);
    	 }
    	 
    }
    
    public void keyPressed(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_SPACE) {
			counter++;
			if(counter>4) counter=0;
		}
	}
	public void keyReleased(KeyEvent e) {}
	public void keyTyped(KeyEvent e) {}
}

Maybe your problem is that you get and update the Graphics in mouseMoved, but Swing doesn't know that you have done this. Swing is by default double-buffered, so the screen isn't getting updated with your new line until something else happens to cause a refresh of the screen.
If you want to do it that way you should call repaint() after drawing to the Graphics. However, in general, updating the component's Graphics outside paintComponent(..) isn't a great idea - it's hard to coordinate your drawing with Swing's event handing, eg on a window re-size.. It's normally better to update some data that describes the line in your mouse listener (or draw the line to your own off-screen graphics buffer), then call repaint(). Draw the latest version in paintComponent when that gets called by Swing.

Thank you for your tips JamesCherrill.
Is this what you meant ?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GradientTranslucentWindow extends JFrame implements KeyListener, MouseListener, MouseMotionListener {
    private int counter = 0;
    private int draw = 0;
    private Point start, end;
    private JPanel panel;
    private static final int red[] = {58, 71, 231, 243, 255};
    private static final int green[] = {54, 224, 235, 109, 40};
    private static final int blue[] = {241, 95, 61, 52, 40};
    private static final int R = 240;
    private static final int G = 240;
    private static final int B = 200;

    public GradientTranslucentWindow() {
        setBackground(new Color(0, 0, 0, 0));
        setSize(new Dimension(500, 500));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        panel = new JPanel() {
            protected void paintComponent(Graphics g) {
                if (g instanceof Graphics2D) {
                    Paint p = new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 50),
                            0.0f, getHeight(), new Color(R, G, B, 255), true);
                    Graphics2D g2d = (Graphics2D) g;
                    g2d.setPaint(p);
                    g2d.fillRect(0, 0, getWidth(), getHeight());
                    if (draw == 1) {
                        g2d.setColor(new Color(red[counter], green[counter], blue[counter]));
                        g2d.drawLine(start.x, start.y, end.x, end.y);
                        start = end;
                    }
                }
            }
        };
        setContentPane(panel);
        addKeyListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        new GradientTranslucentWindow().setVisible(true);
    }

    public void mousePressed(MouseEvent e) {
        start = e.getPoint();
        if (e.getButton() == MouseEvent.BUTTON1) draw = 1;
        else if (e.getButton() == MouseEvent.BUTTON3) draw = 0;
    }

    public void mouseClicked(MouseEvent e) {}

    public void mouseEntered(MouseEvent e) {}

    public void mouseExited(MouseEvent e) {}

    public void mouseReleased(MouseEvent e) {}

    public void mouseDragged(MouseEvent e) {
        start = e.getPoint();
    }

    public void mouseMoved(MouseEvent e) {
        if (draw == 1) {
            end = e.getPoint();
            int x = (start.x < end.x) ? start.x : end.x;
            int y = (start.y < end.y) ? start.y : end.y;
            panel.repaint(x, y, Math.abs(start.x - end.x) + 1, Math.abs(start.y - end.y) + 1);
            System.out.println(start.x + " - " + start.y);
        }
    }

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            counter++;
            if (counter > 4) counter = 0;     
        }
    }

    public void keyReleased(KeyEvent e) {}

    public void keyTyped(KeyEvent e) {}
}

And here is my previous code, using the same method as above code, but the drawing activity is called outside paintComponent(). The result is the same... Could you please tell me what the worst effect of this code is?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Paint;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GradientTranslucentWindow extends JFrame implements KeyListener, MouseListener, MouseMotionListener {
	
    private int counter = 0;
    private int draw = -1;
    private int red[] = {58,71,231,243,255};
    private int green[] = {54,224,235,109,40};
    private int blue[] = {241,95,61,52,40};
    private int R = 240;
    private int G = 240;
    private int B = 200;
    private Point start, end;
    private Graphics gd; 
    private JPanel panel;
	
    public GradientTranslucentWindow() {
        setBackground(new Color(0,0,0,0));
        setSize(new Dimension(500,500));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        panel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                if (g instanceof Graphics2D) {
                    Paint p =  new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0), 0.0f, getHeight(), new Color(R, G, B, 150), true);
                    Graphics2D g2d = (Graphics2D)g;
                    g2d.setPaint(p);
                    if(draw==-1) g2d.fillRect(0, 0, getWidth(), getHeight());
                }
            }
        };
        setContentPane(panel);
        addKeyListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public static void main(String[] args) {
       JFrame.setDefaultLookAndFeelDecorated(true);
       new GradientTranslucentWindow().setVisible(true);
    }
    
    public void mousePressed(MouseEvent e) { start = new Point(e.getX(), e.getY()); }
    public void mouseClicked(MouseEvent e) {
    	if(e.getButton() == MouseEvent.BUTTON1) draw = 1;
    	if(e.getButton() == MouseEvent.BUTTON3) draw = 0;
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseDragged(MouseEvent e)  {}
    
     public void mouseMoved(MouseEvent e) {
    	 gd = this.getGraphics();

    	 if(draw==1){
    		 end = new Point(e.getX(), e.getY());
    		 gd.setColor(new Color( red[counter],green[counter],blue[counter]));
    		 gd.drawLine(start.x, start.y, end.x, end.y);
    		 start = end;
    		 panel.repaint();   		
    		 System.out.println(start.x + " - " + start.y);
    	 }
    }
    
    public void keyPressed(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_SPACE) {
			counter++;
			if ( counter > 4 ) counter = 0;
		}
	}
	public void keyReleased(KeyEvent e) {}
	public void keyTyped(KeyEvent e) {}
}

Confused by questions then thread solved. Are you OK now?

Confused by questions then thread solved. Are you OK now?

Yes, I'm fine now ^_^
The problem is already solved since I managed to get it working. Lines are drawn on a transparent window

Thank you JamesCherrill :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.