I am creating a blank transparent JPanel and then drawing lines to form boxes on it. I want to increase the size of the box but when I do I end up leaving a trail behind where the lines used to be.
I've done much searching online but can't seem to find a solution that works for me.
Any help would be much appreciated!
public class AVTBox extends JPanel {
private int boxSize = 100;
private boolean started = false, stopped = true, track = false;
private final int center = 150;
private final int maxBoxSize = 300, minBoxSize = 25;
private final int lockBoxSize = 30;
public AVTBox()
{
this.setOpaque(false);
this.repaint();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g.create();
g2.setStroke(new BasicStroke(3.0f));
g2.setColor(Color.BLACK);
g2.draw(new Line2D.Double(center - (boxSize/2), center - (boxSize/2) + (boxSize*0.3),
center - (boxSize/2), center + (boxSize/2) - (boxSize*0.3))
);
g2.draw(new Line2D.Double(center + (boxSize/2), center - (boxSize/2) + (boxSize*0.3),
center + (boxSize/2), center + (boxSize/2) - (boxSize*0.3))
);
g2.draw(new Line2D.Double(center - (boxSize/2) + (boxSize*0.3), center - (boxSize/2),
center + (boxSize/2) - (boxSize*0.3), center - (boxSize/2))
);
g2.draw(new Line2D.Double(center - (boxSize/2) + (boxSize*0.3), center + (boxSize/2),
center + (boxSize/2) - (boxSize*0.3), center + (boxSize/2))
);
g2.dispose();
}
public void setBoxSize(String change)
{
switch (change) {
case "add":
if(boxSize < maxBoxSize)
{
boxSize++;
} break;
case "sub":
if(boxSize > minBoxSize)
{
boxSize--;
} break;
}
this.revalidate();
this.repaint();
}
}
EDIT: Everything works as it should when the panel has a full non-transparent background but moving these lines on a transparent background leaves painted parts behind. I need to find a way of getting this 'animation' working on a transparent background.
This image shows what should happen when the user increases the box size (green arrow) and what happens at the moment (red arrow).
Sorry for the terrible MSpaint image!
So I figured it out; I was adding this JPanel to another JPanel instead of a JFrame. Not completely sure why but everything worked perfectly after being added directly to the JFrame.
Related
Please help me how to make this eye move or to make it blink using repaint, thread and implements runnable. I don't know where to place the right codes to make it work. Please help me guys! Thank you!
Here is the code:
import java.awt.*;
import java.applet.*;
public class Pucca extends Applet {
public Pucca(){
setSize(700, 700); }
//paint method
public void paint(Graphics g){
Color white = new Color(255,255,255);
g.setColor(white);
g.fillOval(600, 100, 125, 125); //left white fill eye
g.setColor(Color.BLACK);
g.drawOval(600, 100, 125, 125); // left big black line eye
g.setColor(white);
g.fillOval(700, 100, 125, 125); //right white fill eye
g.setColor(Color.BLACK);
g.drawOval(700, 100, 125, 125); //right big black line eye
Color blue = new Color(0, 160, 198);
g.setColor(blue);
g.fillOval(635, 130, 51, 51); // left blue fill eye
g.setColor(Color.BLACK);
g.drawOval(635, 130, 50, 50); // left black small line eye
g.setColor(blue);
g.fillOval(735, 130, 51, 51); // right blue fill eye
g.setColor(Color.BLACK);
g.drawOval(735, 130, 50, 50); // right black small line eye
g.setColor(Color.BLACK);
g.fillOval(650, 145, 20, 20); // left black iris
g.setColor(Color.BLACK);
g.fillOval(750, 145, 20, 20); // right black iris
}
}
When it comes to animation, everything becomes variable. You also have a lot of repeated code (seriously, if you can paint one eye, you can paint lots).
The first thing you need to is make all the values of the eye as variable as possible.
The follow makes the eye size and position variable and the iris and pupil a scaled value of the eye size, which makes the whole process simpler to animate.
Next, you need an updated loop, which can update the state of the values you want to change. To keep it simple, I've set it up so that the pupil has a variable offset, which is changed over time.
import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
public class Pucca extends Applet {
public Pucca() {
setSize(700, 700);
Thread t = new Thread(new Runnable() {
private int xDelta = -1;
private int yDelta = 0;
private int blinkCount = 0;
#Override
public void run() {
while (true) {
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
}
xOffset += xDelta;
double irisSize = eyeSize.width * irisScale;
double range = ((eyeSize.width - irisSize) / 2);
if (xOffset <= -range) {
xOffset = -(int) range;
xDelta *= -1;
} else if (xOffset >= range) {
xOffset = (int) range;
xDelta *= -1;
}
blinkCount++;
if (blink && blinkCount > 10) {
blink = false;
blinkCount = 0;
} else if (blinkCount > 25) {
blink = true;
blinkCount = 0;
}
repaint();
}
}
});
t.setDaemon(true);
t.start();
}
private boolean blink = false;
private int xOffset, yOffset = 0;
private Dimension eyeSize = new Dimension(125, 125);
private Point left = new Point(20, 20);
private Point right = new Point(left.x + 100, left.y);
private double irisScale = 0.4;
private double pupilScale = 0.16;
//paint method
#Override
public void paint(Graphics g) {
super.paint(g);
paintEye(g, new Rectangle(left, eyeSize));
paintEye(g, new Rectangle(right, eyeSize));
}
protected void paintEye(Graphics g, Rectangle bounds) {
Color white = new Color(255, 255, 255);
if (blink) {
g.setColor(Color.YELLOW);
} else {
g.setColor(white);
}
g.fillOval(bounds.x, bounds.y, bounds.width, bounds.height); //left white fill eye
g.setColor(Color.BLACK);
g.drawOval(bounds.x, bounds.y, bounds.width, bounds.height); // left big black line eye
if (!blink) {
Color blue = new Color(0, 160, 198);
paintEyePartAt(g, bounds, irisScale, blue);
paintEyePartAt(g, bounds, pupilScale, Color.BLACK);
}
}
private void paintEyePartAt(Graphics g, Rectangle bounds, double delta, Color color) {
int width = (int) (bounds.width * delta);
int height = (int) (bounds.height * delta);
g.setColor(color);
g.fillOval(
xOffset + bounds.x + ((bounds.width - width) / 2),
yOffset + bounds.y + ((bounds.height - height) / 2),
width, height); // left blue fill eye
g.setColor(Color.BLACK);
g.drawOval(
xOffset + bounds.x + ((bounds.width - width) / 2),
yOffset + bounds.y + ((bounds.height - height) / 2),
width,
height); // left blue fill eye
}
}
This complicates things, as painting can occur for any number of reasons, many of which you don't have control over or will be notified about, so you should be very careful about where and when you change values.
You should also have a look at Java Plugin support deprecated and Moving to a Plugin-Free Web and Why CS teachers should stop teaching Java applets.
Applets are simply a dead technology and given the inherent complexities involved in using them, you should instead focus you should probably attention towards window based programs.
Personally, I'd start with having a look at Painting in AWT and Swing and Performing Custom Painting
Since I'm pretty new in Libgdx development, I would like to ask if it is possible to make image borders (to mark it up as selected) using it? I've read that one solution is to make 2 separate images: one with border and one without. However pretty all of my images are the same size and there are many of them so don't know if it's the best idea. Are there any other options?
EDIT
So i have chosen 2nd idea ( 1x1 image ) but there is some problem with it. First of all i can't make that borderImage to be under clicked element. Another problem is size of borderImage ( it's not same ). When i click in the center of button its smaller ( about couple pixels ) than when i click on the edge. Do u know what can cause these problems and how to fix them?
Code :
public void create(){
stage = new Stage();
Gdx.input.setInputProcessor(stage);
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
Texture borderTexture = new Texture(Gdx.files.internal("data/select.png") );
final Image borderImage = new Image( borderTexture );
TextButton exitButton = new TextButton("Exit",skin);
exitButton.addListener(new ClickListener(){
public void clicked(InputEvent event, float x, float y)
{
borderImage.setSize( event.getTarget().getWidth() + 1 * 2, event.getTarget().getHeight() + 1 * 2);
Vector2 loc = new Vector2(0, 0);
Vector2 stageLoc = event.getTarget().localToStageCoordinates(loc);
borderImage.setPosition( stageLoc.x, stageLoc.y);
System.out.println("" + event.getTarget().getWidth() + " " +event.getTarget().getHeight() + " " + event.getTarget().getX() +
" " + event.getTarget().getY() + " " + stageLoc.x + " " + stageLoc.y);
stage.addActor(borderImage);
}
}
);
Table table = new Table();
table.add(exitButton).colspan(3);
table.setFillParent(true);
stage.addActor(table);
}
And the output i have :
29.0 25.0 4.0 1.0 466.0 257.0 // clicked in the center of button
37.0 27.0 462.0 256.0 462.0 256.0 // clicked on the edge of button
If you are using Scene2D and its Image class the simpliest idea is to keep a small texture of color you want the border to has. The texture can be like 1px x 1px size. It should has Nearest filtering due to avoid blending borders effect.
When click on image you can create an Image of size of the image plus border width and place it where the image is achieving border effect. On touch up you need to remove the border-actor
Texture borderTexture = new Texture( Gdx.files.internal("border.png") );
Image borderImage = new Image( borderTexture );
...
//in the clickListener
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
borderImage.setSize( event.getTarget().getWidth() + BORDER_WIDTH * 2, event.getTarget().getHeight() + BORDER_WIDTH * 2);
borderImage.setPosition( event.getTarget().getX() - BORDER_WIDTH, event.getTarget.getY() - BORDER_WIDTH);
stage.addActor( borderImage );
event.getTarget().toFront(); //to move the original image over the border
return true;
}
public void touchUp(InputEvent event, float x, float y, int pointer, int button)
{
borderImage.remove();
}
If not using the Scene2D you can achieve same effect by rendering Sprite of size of the image + border width and manage a flag saying if render the border or not
Sprite image, border;
...
//in the input processor
public boolean touchDown (int x, int y, int pointer, int button)
{
border.setSize( image.getWidth() + BORDER_WIDTH * 2 , image.getHeight() + BORDER_WIDTH * 2 );
border.setPosition( image.getX() - BORDER_WIDTH, image.getY() - BORDER_WIDTH);
renderBorder = true;
return true;
}
public boolean touchUp (int x, int y, int pointer, int button)
{
renderBorder = false;
return false;
}
//in the render method
if(renderBorder)
{
border.draw(batch);
}
image.draw(batch);
here what i'll do if it was for me :
i will use one border image for all my images (instead of image border for each one of my images)
let assume that on the left is your image and on right is the border image
when a Click event occured on the image you draw the border on the image (your image border is transparent inside you can easly do it with editor like gimp) on top of the image and you will have something like this
if the size is different you can change it and fix the same size before drawing the image at same position
Hope this will help !
I'm moving a circle across the window by dragging it with the mouse. I'm supposed to make it always inside the window.
So by the default, when you drag the circle in a way that your mouse exits the frame, half of the circle will disappear (because it exits the frame), and half of it won't. I need to make it visible whole all the time, even if your cursor exits the frame. Here's the code:
if(draggingcircle)
{
g.drawString("Dragging circle = " + draggingcircle, 50, 110);
circle.setCenterX( gc.getInput().getMouseX() );
circle.setCenterY( gc.getInput().getMouseY() );
}
whatever the circle is contained in, lets call id , you can keep it in the container with simple math if you know the radius or the diameter (i forget which)
so
if(draggingcircle)
{
g.drawString("Dragging circle = " + draggingcircle, 50, 110);
circle.setCenterX( gc.getInput().getMouseX() );
circle.setCenterY( gc.getInput().getMouseY() );
}
becomes
var width = $('#container').width();
var height = $('#container').height();
var radius = 2;
if(draggingcircle)
{
g.drawString("Dragging circle = " + draggingcircle, 50, 110);
if (gc.getInput().getMouseX() > radius && gc.getInput().getMouseX() < width - radius)
{
circle.setCenterX( gc.getInput().getMouseX() );
}
if (gc.getInput().getMouseY() > radius && gc.getInput().getMouseY() < height - radius)
{
circle.setCenterY( gc.getInput().getMouseY() );
}
}
Sorry for my poor syntax, I am not familiar with Slick2d, but something along these lines should work.
Hey Guys I have succesfully made a GUI in java that will scale polygons and circles using a slider. Everything works but I was wondering if there is a way to change the Origin point(Where it scales from). Right now it scales from the corner and I would like it to scale from the middle so I can start it in the middle and it scales out evenly. Also, If anyone could tell me an easy way to replace the Rectangle I have with an Image of some kind so you can scale the Picture up and down would be great! Thank you! Here is my code:
import javax.swing.*;
public class Fred
{
public static void main(String[] args)
{
TheWindow w = new TheWindow();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //X wont close the window with out this line
w.setSize(375,375);
w.setVisible(true);
}
}
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class TheWindow extends JFrame
{
private JSlider slider; //declare slider
private drawRect myPanel; //declare/ create panel
public TheWindow()
{
super("Slider Example"); //make title
myPanel = new drawRect();
myPanel.setBackground(Color.green); //change background color
slider = new JSlider(SwingConstants.VERTICAL, 0, 315, 10);// restrains the slider from scaling square to 0-300 pixels
slider.setMajorTickSpacing(20); //will set tick marks every 10 pixels
slider.setPaintTicks(true); //this actually paints the ticks on the screen
slider.addChangeListener
(
new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
myPanel.setD(slider.getValue()); //Wherever you set the slider, it will pass that value and that will paint on the screen
}
}
);
add(slider, BorderLayout.WEST); //similar to init method, adds slider and panel to GUI
add(myPanel, BorderLayout.CENTER);
}
}
import java.awt.*;
import javax.swing.*;
public class drawRect extends JPanel
{
private int d = 25; //this determines the beginning length of the rect.
public void paintComponent(Graphics g)//paints circle on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
g.fillRect(15,15, d, d); //paints rectangle on screen
//x , y, width, height
}
public void setD(int newD)
{
d = (newD >= 0 ? newD : 10); //if number is less than zero it will use 10 for diameter(compressed if statement)
repaint();
}
public Dimension getPrefferedSize()
{
return new Dimension(200, 200);
}
public Dimension getMinimumSize()
{
return getPrefferedSize();
}
}
Changing the "origin point" so it becomes the center of the "zoom" is basically just the process of subtract half of d from the center point.
So, assuming the the center point is 28 ((25 / 2) + 15), you would simply then subtract d / 2 (25 / 2) from this point, 28 - (25 / 2) = 15 or near enough...
I modified the paintComponent method for testing, so the rectangle is always at the center of the panel, but you can supply arbitrary values in place of the originX and originY
#Override
public void paintComponent(Graphics g)//paints circle on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
int originX = getWidth() / 2;
int originY = getHeight() / 2;
int x = originX - (d / 2);
int y = originY - (d / 2);
System.out.println(x + "x" + y);
g.fillRect(x, y, d, d); //paints rectangle on screen
//x , y, width, height
}
As for scaling an image, you should look at Graphics#drawImage(Image img, int x, int y, int width, int height, ImageObserver observer), beware though, this will scaling the image to the absolute size, it won't keep the image ratio.
A better solution might be to use a double value of between 0 and 1 and multiple the various elements by this value to get the absolute values you want
In my java applet I have an image following the cursor around the content pane. I also set a background image. When I move the cursor I am able to see the cursor image but the background flickers rather badly however when I stop moving the cursor the background images stops flickering and the cursor image dissapears behind it. How can I always have the cursor image on top of the background without the background image flickering.
Here is my code:
public class ShootingGallery extends JApplet implements MouseListener, MouseMotionListener {
//VARIABLES
int mouseXPos;
int mouseYPos;
Image myImage;
Image gameBackground;
#Override
public void init() {
//SET UP PAGE
setSize(800, 600);
gameBackground = Toolkit.getDefaultToolkit().getImage("bikiniBottom.JPG");
//ADD ACTION LISTENERS
addMouseMotionListener(this);
addMouseListener(this);
this.add(new PaintContainer());
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(gameBackground, 0, 0, this);
}
#Override
public void update(Graphics g) {
paint(g);
}
#Override
public void mouseMoved(MouseEvent e) {
moveMouse(e);
}
public void moveMouse(MouseEvent e) {
Graphics g = getGraphics();
//SET UP CURSOR IMAGE
myImage = getImage(getDocumentBase(), "spongebob.gif");
mouseXPos = e.getX() - (myImage.getWidth(null) / 2);
mouseYPos = e.getY() - (myImage.getHeight(null) / 2);
System.out.println(mouseXPos + " ," + mouseYPos);
repaint();
}
public class PaintContainer extends JPanel {
#Override
protected void paintComponent(Graphics g) {
g.drawImage(myImage, mouseXPos, mouseYPos, this);
}
}
}
Thanks in advance
You should use Double Buffering to avoid the flickering.
class DoubleBufferedCanvas extends Canvas {
public void update(Graphics g) {
Graphics offgc;
Image offscreen = null;
Dimension d = size();
// create the offscreen buffer and associated Graphics
offscreen = createImage(d.width, d.height);
offgc = offscreen.getGraphics();
// clear the exposed area
offgc.setColor(getBackground());
offgc.fillRect(0, 0, d.width, d.height);
offgc.setColor(getForeground());
// do normal redraw
paint(offgc);
// transfer offscreen to window
g.drawImage(offscreen, 0, 0, this);
}
}
Tried using paintComponent instead of paint? (replace paint with paintComponent). Also, read about double buffering and why you need it: http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html
Don't override paint() and don't override update(). That is the old way to do custom painting when using AWT. This is Swing and that is NOT the way to do this.
Custom painting is done by overriding the paintComponent() method of a JPanel (or JComponent). Then you add the panel to the applet. Read the Swing tutorial o Custom Painting for an example and explanation.
Here is a paint application where u can draw image through color brushes
It is on white background
/* Arpana */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* A simple applet where the user can sketch curves in a variety of
* colors. A color palette is shown along the right edge of the applet.
* The user can select a drawing color by clicking on a color in the
* palette. Under the colors is a "Clear button" that the user
* can press to clear the sketch. The user draws by clicking and
* dragging in a large white area that occupies most of the applet.
* The user's drawing is not persistent. It is lost whenever
* the applet is repainted for any reason.
* <p>The drawing that is done in this example violates the rule
* that all drawing should be done in the paintComponent() method.
* Although it works, it is NOT good style.
* <p>This class also contains a main program, and it can be run as
* a stand-alone application that has exactly the same functionality
* as the applet.
*/
public class SimplePaint extends JApplet {
/**
* The main routine opens a window that displays a drawing area
* and color palette. This main routine allows this class to
* be run as a stand-alone application as well as as an applet.
* The main routine has nothing to do with the function of this
* class as an applet.
*/
public static void main(String[] args) {
JFrame window = new JFrame("Simple Paint");
SimplePaintPanel content = new SimplePaintPanel();
window.setContentPane(content);
window.setSize(600,480);
window.setLocation(100,100);
window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
window.setVisible(true);
}
/**
* The init method of the applet simply creates a SimplePaintPanel and
* uses it as the content pane of the applet. All the work is done
* by the SimplePaintPanel.
*/
public void init() {
setContentPane( new SimplePaintPanel() );
}
/**
* A simple paint panel contains a large white drawing surface where
* the user can draw curves and a color palette that the user can click
* to select the color to be used for drawing. When this class is used
* as an applet, the content pane of the applet is a SimplePaintPanel.
* When this class is run as a standalone application, the content pane
* is a SimplePaintPanel. All the real work is done in the
* SimplePaintPanel class.
*/
public static class SimplePaintPanel extends JPanel
implements MouseListener, MouseMotionListener {
/**
* Some constants to represent the color selected by the user.
*/
private final static int BLACK = 0,
RED = 1,
GREEN = 2,
BLUE = 3,
CYAN = 4,
MAGENTA = 5,
YELLOW = 6;
private int currentColor = BLACK; // The currently selected drawing color,
// coded as one of the above constants.
/* The following variables are used when the user is sketching a
curve while dragging a mouse. */
private int prevX, prevY; // The previous location of the mouse.
private boolean dragging; // This is set to true while the user is drawing.
private Graphics graphicsForDrawing; // A graphics context for the panel
// that is used to draw the user's curve.
/**
* Constructor for SimplePaintPanel class sets the background color to be
* white and sets it to listen for mouse events on itself.
*/
SimplePaintPanel() {
setBackground(Color.WHITE);
addMouseListener(this);
addMouseMotionListener(this);
}
/**
* Draw the contents of the panel. Since no information is
* saved about what the user has drawn, the user's drawing
* is erased whenever this routine is called.
*/
public void paintComponent(Graphics g) {
super.paintComponent(g); // Fill with background color (white).
int width = getWidth(); // Width of the panel.
int height = getHeight(); // Height of the panel.
int colorSpacing = (height - 56) / 7;
// Distance between the top of one colored rectangle in the palette
// and the top of the rectangle below it. The height of the
// rectangle will be colorSpacing - 3. There are 7 colored rectangles,
// so the available space is divided by 7. The available space allows
// for the gray border and the 50-by-50 CLEAR button.
/* Draw a 3-pixel border around the applet in gray. This has to be
done by drawing three rectangles of different sizes. */
g.setColor(Color.GRAY);
g.drawRect(0, 0, width-1, height-1);
g.drawRect(1, 1, width-3, height-3);
g.drawRect(2, 2, width-5, height-5);
/* Draw a 56-pixel wide gray rectangle along the right edge of the applet.
The color palette and Clear button will be drawn on top of this.
(This covers some of the same area as the border I just drew. */
g.fillRect(width - 56, 0, 56, height);
/* Draw the "Clear button" as a 50-by-50 white rectangle in the lower right
corner of the applet, allowing for a 3-pixel border. */
g.setColor(Color.WHITE);
g.fillRect(width-53, height-53, 50, 50);
g.setColor(Color.BLACK);
g.drawRect(width-53, height-53, 49, 49);
g.drawString("CLEAR", width-48, height-23);
/* Draw the seven color rectangles. */
g.setColor(Color.BLACK);
g.fillRect(width-53, 3 + 0*colorSpacing, 50, colorSpacing-3);
g.setColor(Color.RED);
g.fillRect(width-53, 3 + 1*colorSpacing, 50, colorSpacing-3);
g.setColor(Color.GREEN);
g.fillRect(width-53, 3 + 2*colorSpacing, 50, colorSpacing-3);
g.setColor(Color.BLUE);
g.fillRect(width-53, 3 + 3*colorSpacing, 50, colorSpacing-3);
g.setColor(Color.CYAN);
g.fillRect(width-53, 3 + 4*colorSpacing, 50, colorSpacing-3);
g.setColor(Color.MAGENTA);
g.fillRect(width-53, 3 + 5*colorSpacing, 50, colorSpacing-3);
g.setColor(Color.YELLOW);
g.fillRect(width-53, 3 + 6*colorSpacing, 50, colorSpacing-3);
/* Draw a 2-pixel white border around the color rectangle
of the current drawing color. */
g.setColor(Color.WHITE);
g.drawRect(width-55, 1 + currentColor*colorSpacing, 53, colorSpacing);
g.drawRect(width-54, 2 + currentColor*colorSpacing, 51, colorSpacing-2);
} // end paintComponent()
/**
* Change the drawing color after the user has clicked the
* mouse on the color palette at a point with y-coordinate y.
* (Note that I can't just call repaint and redraw the whole
* panel, since that would erase the user's drawing!)
*/
private void changeColor(int y) {
int width = getWidth(); // Width of applet.
int height = getHeight(); // Height of applet.
int colorSpacing = (height - 56) / 7; // Space for one color rectangle.
int newColor = y / colorSpacing; // Which color number was clicked?
if (newColor < 0 || newColor > 6) // Make sure the color number is valid.
return;
/* Remove the hilite from the current color, by drawing over it in gray.
Then change the current drawing color and draw a hilite around the
new drawing color. */
Graphics g = getGraphics();
g.setColor(Color.GRAY);
g.drawRect(width-55, 1 + currentColor*colorSpacing, 53, colorSpacing);
g.drawRect(width-54, 2 + currentColor*colorSpacing, 51, colorSpacing-2);
currentColor = newColor;
g.setColor(Color.WHITE);
g.drawRect(width-55, 1 + currentColor*colorSpacing, 53, colorSpacing);
g.drawRect(width-54, 2 + currentColor*colorSpacing, 51, colorSpacing-2);
g.dispose();
} // end changeColor()
/**
* This routine is called in mousePressed when the user clicks on the drawing area.
* It sets up the graphics context, graphicsForDrawing, to be used to draw the user's
* sketch in the current color.
*/
private void setUpDrawingGraphics() {
graphicsForDrawing = getGraphics();
switch (currentColor) {
case BLACK:
graphicsForDrawing.setColor(Color.BLACK);
break;
case RED:
graphicsForDrawing.setColor(Color.RED);
break;
case GREEN:
graphicsForDrawing.setColor(Color.GREEN);
break;
case BLUE:
graphicsForDrawing.setColor(Color.BLUE);
break;
case CYAN:
graphicsForDrawing.setColor(Color.CYAN);
break;
case MAGENTA:
graphicsForDrawing.setColor(Color.MAGENTA);
break;
case YELLOW:
graphicsForDrawing.setColor(Color.YELLOW);
break;
}
} // end setUpDrawingGraphics()
/**
* This is called when the user presses the mouse anywhere in the applet.
* There are three possible responses, depending on where the user clicked:
* Change the current color, clear the drawing, or start drawing a curve.
* (Or do nothing if user clicks on the border.)
*/
public void mousePressed(MouseEvent evt) {
int x = evt.getX(); // x-coordinate where the user clicked.
int y = evt.getY(); // y-coordinate where the user clicked.
int width = getWidth(); // Width of the panel.
int height = getHeight(); // Height of the panel.
if (dragging == true) // Ignore mouse presses that occur
return; // when user is already drawing a curve.
// (This can happen if the user presses
// two mouse buttons at the same time.)
if (x > width - 53) {
// User clicked to the right of the drawing area.
// This click is either on the clear button or
// on the color palette.
if (y > height - 53)
repaint(); // Clicked on "CLEAR button".
else
changeColor(y); // Clicked on the color palette.
}
else if (x > 3 && x < width - 56 && y > 3 && y < height - 3) {
// The user has clicked on the white drawing area.
// Start drawing a curve from the point (x,y).
prevX = x;
prevY = y;
dragging = true;
setUpDrawingGraphics();
}
} // end mousePressed()
/**
* Called whenever the user releases the mouse button. If the user was drawing
* a curve, the curve is done, so we should set drawing to false and get rid of
* the graphics context that we created to use during the drawing.
*/
public void mouseReleased(MouseEvent evt) {
if (dragging == false)
return; // Nothing to do because the user isn't drawing.
dragging = false;
graphicsForDrawing.dispose();
graphicsForDrawing = null;
}
/**
* Called whenever the user moves the mouse while a mouse button is held down.
* If the user is drawing, draw a line segment from the previous mouse location
* to the current mouse location, and set up prevX and prevY for the next call.
* Note that in case the user drags outside of the drawing area, the values of
* x and y are "clamped" to lie within this area. This avoids drawing on the color
* palette or clear button.
*/
public void mouseDragged(MouseEvent evt) {
if (dragging == false)
return; // Nothing to do because the user isn't drawing.
int x = evt.getX(); // x-coordinate of mouse.
int y = evt.getY(); // y-coordinate of mouse.
if (x < 3) // Adjust the value of x,
x = 3; // to make sure it's in
if (x > getWidth() - 57) // the drawing area.
x = getWidth() - 57;
if (y < 3) // Adjust the value of y,
y = 3; // to make sure it's in
if (y > getHeight() - 4) // the drawing area.
y = getHeight() - 4;
graphicsForDrawing.drawLine(prevX, prevY, x, y); // Draw the line.
prevX = x; // Get ready for the next line segment in the curve.
prevY = y;
} // end mouseDragged()
public void mouseEntered(MouseEvent evt) { } // Some empty routines.
public void mouseExited(MouseEvent evt) { } // (Required by the MouseListener
public void mouseClicked(MouseEvent evt) { } // and MouseMotionListener
public void mouseMoved(MouseEvent evt) { } // interfaces).
} // End class SimplePaintPanel
} // end class SimplePaint