The following code is the code that I am using to rotate two rectangles is below
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setColor(Color.WHITE);
//r1
Rectangle2D r1 = new Rectangle2D.Double(0, 0, 50, 4);
g2d.rotate(Math.toRadians(45));
g2d.fill(r1);
//r3
Rectangle2D r3 = new Rectangle2D.Double(0, 25, 50, 4);
g2d.rotate(Math.toRadians(-90));
g2d.fill(r3);
This create something which looks like this
Whereas I am trying to create something which looks like this
This occurs since when the rectangles are rotated, they are both rotated around the point 0,0. To fix that I tried using rotate(double theta, double x, double y). However I am having trouble using that correctly. For example when I have tried
Rectangle2D r3 = new Rectangle2D.Double(0, 25, 50, 4);
g2d.rotate(Math.toRadians(-90), 25, 25);
or
Rectangle2D r3 = new Rectangle2D.Double(0, 25, 50, 4);
g2d.rotate(Math.toRadians(-90), 0, 25);
I get similar undesired results when both the rectangles were being rotated around the point 0,0. I would appreciate any help if fixing my problem.
If you are wondering why I have done it like this, it is because I am hoping to make a effect similar to when you click on the 3 parallel lines seen here by the time I finish coding the graphic
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.*;
public class Cross extends JPanel {
private Rectangle2D rectangle;
Cross() {
rectangle = new Rectangle2D.Double(0, 0, 50, 4);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setColor(Color.white);
AffineTransform at = g2.getTransform();
g2.translate(5, 5);
g2.rotate(Math.toRadians(45));
g2.fill(rectangle);
g2.setTransform(at);
g2.translate(5, 5 + Math.sqrt(2) * 25);
g2.rotate(Math.toRadians(-45));
g2.fill(rectangle);
g2.setTransform(at);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Cross");
frame.add(new Cross());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(128, 128);
frame.setVisible(true);
}
}
Although I think I might have done mistake somewhere with maths (it looks somewhat odd), this should give you an idea.
So it turns out that this can be done with some relatively simple maths. As the shape I am trying to make is a perfect X.
To work out the position for the rectangle we can use Pythagorean theorem.
The image above shows two steps.
Translation [2√2, 0] from the point [0, 0]
Rotate 45deg from the point [2√2, 0]
Next we need to work out the minimum point of this rectangle. Again we can use Pythagorean theorem.
This tells us where the top point of the second rectangle will be
Difference in height: 4 - 2√2
Bottom of line when straight: [0, 27√2 + (4 - 2√2)] = [0, 4 + 25√2]
Top of line when straight: [0, 25√2]
Finally we can put in the last rectangle starting at [0, 0]
Translation [0, 25√2] from the point [0, 0]
Rotate -45deg from the point [0, 25√2]
Now that the theory is out of the way, what does this look like in code? It looks similar to the code below
//Values
final static double[] r1Points = {2.828427125, 0}; //Equivilant 2√2
final static double[] r3Points = {0, 35.35533906}; //Equivilant 25√2
final static int[] widthNHeight = {50, 4}; //Width then height
final static double angle = 45.0; //Angle to rotate lines
//Declaring the rectangles
Rectangle2D r1 = new Rectangle2D.Double(r1Points[0], r1Points[1], widthNHeight[0], widthNHeight[1]);
Rectangle2D r3 = new Rectangle2D.Double(r3Points[0], r3Points[1], widthNHeight[0], widthNHeight[1]);
//r1
g2d.rotate(Math.toRadians(angle), r1Points[0], r1Points[1]); //Rotates graphic for first rectangle
g2d.fill(r1);
//r3
g2d.rotate(Math.toRadians(-angle), r1Points[0], r1Points[1]); //Rotates the graphic back to straight
g2d.rotate(Math.toRadians(-angle), r3Points[0], r3Points[1]); //Rotates graphic for second rectangle
g2d.fill(r3);
Related
I've already searched this topic everywhere on the Internet, but nothing.
I'm programming with JAVA and I'm painting in a JPanel some shapes like yellow stars with a sort of spaceship in the center of the screen. My purpose is to make the entire scene, apart from the spaceship which remains stationary at the center, rotate around the center (and of course around the spaceship) when I press a certain button.
Now, when I rotate the stars I make them rotate around the center point wich changes as the spaceship moves, but when I do a rotation, the coordinates system changes and the ship moves diagonally, while I want to rotate the scene keeping possible to move the spaceship vertically and horizontally.
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
// RIEMPIMENTO SFONDO
g2.setColor(new Color(10, 10, 10));
g2.fillRect(0, 0, 1366, 768);
// DEBUGGER
g2.setColor(Color.WHITE);
g2.drawString("|" + posx + "|" + posy + "| " + scale, 1250, 758);
// TRASFORMAZIONE NAVICELLA
AffineTransform at = new AffineTransform();
at.translate(683, 384);
at.scale(scale, scale);
g2.setTransform(at);
AffineTransform backup = g2.getTransform();
// DISEGNO NAVICELLA
g2.setColor(Color.LIGHT_GRAY);
int[] xp = {0, -25, -25, 0, 25, 25};
int[] yp = {-25, 0, 25, 0, 25, 0};
g2.drawPolygon(xp, yp, 6);
// TRASFORMAZIONE SPAZIO
at.translate(posx, posy);
at.rotate(Math.toRadians(rotation), -posx, -posy);
g2.setTransform(at);
// DISEGNO SPAZIO
STAR(g2, 300 + posx, 100 + posy, 200, 200, Color.YELLOW);
STAR(g2, -100 + posx, -200 + posy, 200, 200, Color.YELLOW);
g2.dispose();
}
Following the previously asked question I now face the task of creating this sophisticated illustration for the company's software:
This is a Dynamic diagram which contains varying data. Those 3 lines are not just an example and there can actually be any number between 1 line and 32 lines. The numeric data above them also may change constantly and dynamically as the application lingers on.
I have a graphic designer at my disposal, but I'm not sure how can I use her help with this task.
on the previous question that I linked above, I eventually used a grid of JPanels which I had graphics place over them as JLabels. But this task is dealing with rounded and unrectangular shapes.
I don't see how I can have the big circle over a JPanel and have those lines over different adjacent JPanels because of the rounded shape of the circle.
Any ideas how can I manipulate this kind of graphics? this entire structure should reside over a JFrame or a JPanel but that is not an issue.
I am willing to work hard and learn new skills in order to do this.
Thank you for any comment or insight.
Demo code for you check it out if it helps you to implement you for software design.
I used graphics2D which comes with java.
This is static JFrame. But you can program it dynamic implementation of this design.
As you can see if remove all colors form picture then it's same design. But you can use also gray-scale to provide all your color effect to this example.
I have added few random code so one you see dotted line are generated randomly.
So here is code that created,
package Stakeoverflow.swingFrame;
/**
*
* #author Naimish
*/
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ShapeTest extends JFrame {
private static final long serialVersionUID = 1L;
private int width = 300;
private int height = 300;
private int padding = 50;
private BufferedImage graphicsContext;
private JPanel contentPanel = new JPanel();
private JLabel contextRender;
private Stroke dashedStroke = new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 2f, new float[] {3f, 3f}, 0f);
private Stroke solidStroke = new BasicStroke(3.0f);
private RenderingHints antialiasing;
private Random random = new Random();
public static void main(String[] args) {
//you should always use the SwingUtilities.invodeLater() method
//to perform actions on swing elements to make certain everything
//is happening on the correct swing thread
Runnable swingStarter = new Runnable()
{
#Override
public void run(){
new ShapeTest();
}
};
SwingUtilities.invokeLater(swingStarter);
}
public ShapeTest(){
antialiasing = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphicsContext = new BufferedImage(width + (2 * padding), width + (2 * padding), BufferedImage.TYPE_INT_RGB);
contextRender = new JLabel(new ImageIcon(graphicsContext));
contentPanel.add(contextRender);
contentPanel.setSize(width + padding * 2, height + padding * 2);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setContentPane(contentPanel);
//take advantage of auto-sizing the window based on the size of its contents
this.pack();
this.setLocationRelativeTo(null);
this.paint();
setVisible(true);
}
public void paint() {
Graphics2D g2d = graphicsContext.createGraphics();
g2d.setRenderingHints(antialiasing);
//Set up the font to print on the circles
Font font = g2d.getFont();
font = font.deriveFont(Font.BOLD, 14f);
g2d.setFont(font);
//clear the background
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, graphicsContext.getWidth(), graphicsContext.getHeight());
//set up the large circle
Point2D largeCircleCenter = new Point2D.Double((double)width / 2 + padding, (double)height / 5 + padding);
double largeCircleRadius = (double)width / 5;
Ellipse2D largeCircle = getCircleByCenter(largeCircleCenter, largeCircleRadius);
//here we build the small circle
Point2D smallCircleCenter = new Point2D.Double();
double smallCircleRadius = 15;
//the resulting end point of the vector is a random distance from the center of the large circle
//in a random direction, and guaranteed to not place the small circle outside the large
smallCircleCenter.setLocation(largeCircleCenter);
Ellipse2D smallCircle = getCircleByCenter(smallCircleCenter, smallCircleRadius);
//before we draw any of the circles or lines, set the clip to the large circle
//to prevent drawing outside our boundaries
// -- g2d.setClip(largeCircle);
//chose a random angle for the line through the center of the small circle
double angle = random.nextDouble() * 360.0d;
//we create two lines that start at the center and go out at the angle in
//opposite directions. We use 2*largeCircleRadius to make certain they
//will be large enough to fill the circle, and the clip we set prevent stray
//marks outside the big circle
Line2D centerLine1 = getVector(smallCircleCenter, angle, largeCircleRadius * 2);
Line2D centerLine2 = getVector(smallCircleCenter, angle, -largeCircleRadius * 2);
Line2D centerLine90 = getVector(smallCircleCenter, 45, 200);
// set line width
g2d.setStroke(new BasicStroke(5));
g2d.setColor(Color.RED);
g2d.draw(centerLine90);
Ellipse2D lineEndCircle = getCircleByCenter(centerLine90.getP2(), smallCircleRadius + 10);
g2d.setStroke(new BasicStroke(2));
g2d.setColor(Color.BLUE);
g2d.draw(lineEndCircle);
// Level 3 Circales
Point2D endCir = centerLine90.getP2();
Line2D centerLine5 = getVector(endCir, 90, smallCircleRadius+30);
g2d.setColor(Color.black);
g2d.draw(centerLine5);
Ellipse2D lineEndCircle2 = getCircleByCenter(centerLine5.getP2(), smallCircleRadius - 5);
g2d.setStroke(new BasicStroke(2));
g2d.setColor(Color.BLUE);
g2d.draw(lineEndCircle2);
g2d.fill(lineEndCircle2);
Line2D centerLine6 = getVector(endCir,0, smallCircleRadius+30);
g2d.setColor(Color.black);
g2d.draw(centerLine6);
Ellipse2D lineEndCircle3 = getCircleByCenter(centerLine6.getP2(), smallCircleRadius - 5);
g2d.setStroke(new BasicStroke(2));
g2d.setColor(Color.BLUE);
g2d.draw(lineEndCircle3);
g2d.fill(lineEndCircle3);
//now we just add 20 and 120 to our angle for the center-line, start at the center
//and again, use largeCircleRadius*2 to make certain the lines are big enough
Line2D sightVector1 = getVector(smallCircleCenter, angle + 60, largeCircleRadius * 2);
Line2D sightVector2 = getVector(smallCircleCenter, angle + 120, largeCircleRadius * 2);
//fill the small circle with blue
g2d.setColor(Color.BLUE);
g2d.fill(smallCircle);
//draw the two center lines lines
g2d.setStroke(dashedStroke);
g2d.draw(centerLine1);
g2d.draw(centerLine2);
//create and draw the black offset vector
Line2D normalVector = getVector(smallCircleCenter, angle + 90, largeCircleRadius * 2);
g2d.setColor(Color.black);
g2d.draw(normalVector);
//draw the offset vectors
g2d.setColor(new Color(0, 200, 0));
g2d.draw(sightVector1);
g2d.draw(sightVector2);
//we save the big circle for last, to cover up any stray marks under the stroke
//of its perimeter. We also set the clip back to null to prevent the large circle
//itselft from accidentally getting clipped
g2d.setClip(null);
g2d.setStroke(solidStroke);
g2d.setColor(Color.BLACK);
g2d.draw(largeCircle);
g2d.dispose();
//force the container for the context to re-paint itself
contextRender.repaint();
}
private static Line2D getVector(Point2D start, double degrees, double length){
//we just multiply the unit vector in the direction we want by the length
//we want to get a vector of correct direction and magnitute
double endX = start.getX() + (length * Math.sin(Math.PI * degrees/ 180.0d));
double endY = start.getY() + (length * Math.cos(Math.PI * degrees/ 180.0d));
Point2D end = new Point2D.Double(endX, endY);
Line2D vector = new Line2D.Double(start, end);
return vector;
}
private static Ellipse2D getCircleByCenter(Point2D center, double radius)
{
Ellipse2D.Double myCircle = new Ellipse2D.Double(center.getX() - radius, center.getY() - radius, 2 * radius, 2 * radius);
return myCircle;
}
}
In principle a JPanel that does the drawing of a graph: items and connections between them. These graph elements can be own classes.
One idea is to consider SVG (Scalable Vector Graphics), an XML notation for such graphs, and JAXB with annotations to map XML to objects. The designer may help produce elements with a GUI editor which helps in the numerical details. Unfortunately SVG is rather concrete. Painting and things like rotation you will need to fill in. You might opt for more abstract coding, but an SVG definition of an element might help. There are at least two java SVG libraries.
I've been having some issues with a ConvolveOp that can be fixed by setting the imageType of the BufferedImage I'm working with to TYPE_INT_ARGB_PRE (see related SO answer here).
Unfortunately I don't fully understand all the implications of selecting this different imageType and I can't seem to find a good reference either, so let me try here:
Which drawing operations are affected by changing the imageType of a BufferedImage from TYPE_INT_ARGB to TYPE_INT_ARGB_PRE? Is it just BufferedImageOps? Or does it affect any of the draw commands on the image's Graphics object or the way the image is rendered if it is drawn onto a different Graphics object?
This basically depends on whether the painting algorithms take into account the information of whether the image is using premultiplied alpha or not.
As already pointed out in the comment: The results will in most cases be the same - at least for the basic drawing operations: Whether you are painting a "non-premultiplied" image into a premultiplied one, or vice versa, will not affect the result, because the differences are handled internally.
A special case are the BufferedImageOps. The JavaDoc comments explicitly say how the alpha channel is treated, and passing in the wrong kind of image can lead to the undesirable results described in the question that you linked to.
It's hard to pin down "the" reason why they decided to implement the BufferedImageOp this way. But a (somewhat vague) statement here is: When operating on (and combining) the pixels of a single source, and these pixels have different alpha values, the treatment of the alpha channel may become fiddly. It's simply not always perfectly obvious what should happen with the alpha channel.
For example, imagine a stack of thee pixels (here, in ARGB, with floating point values):
[1.00, 1.00, 0.00, 0.00] // 100% red, 100% alpha
[0.00, 0.00, 0.00, 0.00] // black, 0% alpha
[0.00, 0.00, 0.00, 0.00] // black, 0% alpha
Now, you want to do a convolution on these pixels (as in the question that you linked to). The kernel could then be
[0.33...]
[0.33...],
[0.33...]
which means that the center pixel of the result should just be the "average" of all pixels (ignoring the borders - roughly as with ConvolveOp#EDGE_ZERO_FILL).
The convolution would then treat all channels equally. For a non-premultiplied image, this would mean that the resulting pixel is a dark red with low opacity:
[0.33, 0.33, 0.00, 0.00]
For the premultiplied image, the components are assumed to be multipled with their alpha value. In this case, the resulting pixel would be fully red, with the same opacity:
[0.33, 1.00, 0.00, 0.00]
Doing the maths behind this is tedious. And in fact, too tedious for me to do it manually - so here is an example:
and the corresponding code
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.util.Locale;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class PremultipliedAlphaTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new PremultipliedAlphaTestPanel());
f.setSize(550,500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class PremultipliedAlphaTestPanel extends JPanel
{
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
BufferedImage imageS = createImage(BufferedImage.TYPE_INT_ARGB);
BufferedImage imageP = createImage(BufferedImage.TYPE_INT_ARGB_PRE);
Kernel kernel = new Kernel(1, 3,
new float[]{ 1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f });
ConvolveOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_ZERO_FILL, null);
BufferedImage resultS = op.filter(imageS, null);
BufferedImage resultP = op.filter(imageP, null);
g.setColor(Color.BLACK);
g.setFont(new Font("Monospaced", Font.PLAIN, 12));
g.drawString("Straight:", 10, 40);
print(g, 2, 1, imageS.getRGB(0, 0));
print(g, 2, 2, imageS.getRGB(0, 1));
print(g, 2, 3, imageS.getRGB(0, 2));
print(g, 7, 2, resultS.getRGB(0, 1));
g.drawString("Premultiplied:", 10, 240);
print(g, 2, 5, imageP.getRGB(0, 0));
print(g, 2, 6, imageP.getRGB(0, 1));
print(g, 2, 7, imageP.getRGB(0, 2));
print(g, 7, 6, resultP.getRGB(0, 1));
g.scale(50, 50);
g.drawImage(imageS, 1, 1, null);
g.drawImage(resultS, 6, 1, null);
g.drawImage(imageP, 1, 5, null);
g.drawImage(resultP, 6, 5, null);
}
private static void print(Graphics2D g, int px, int py, int argb)
{
g.drawString(stringFor(argb), px*50+5, py*50+25);
}
private static String stringFor(int argb)
{
int a = (argb >> 24) & 0xFF;
int r = (argb >> 16) & 0xFF;
int g = (argb >> 8) & 0xFF;
int b = (argb ) & 0xFF;
float fa = a / 255.0f;
float fr = r / 255.0f;
float fg = g / 255.0f;
float fb = b / 255.0f;
return String.format(Locale.ENGLISH,
"%4.2f %4.2f %4.2f %4.2f", fa, fr, fg, fb);
}
private static BufferedImage createImage(int type)
{
BufferedImage b = new BufferedImage(1,3, type);
Graphics2D g = b.createGraphics();
g.setColor(new Color(1.0f,0.0f,0.0f,1.0f));
g.fillRect(0, 0, 1, 1);
g.setColor(new Color(0.0f,0.0f,0.0f,0.0f));
g.fillRect(0, 1, 1, 1);
g.setColor(new Color(0.0f,0.0f,0.0f,0.0f));
g.fillRect(0, 2, 1, 1);
g.dispose();
return b;
}
}
I'm trying to make a Mastermind in Java. The code isn't really difficult, but I want to have a very good interface. I have a JPanel which take all my JFrame, and I paint this JPanel with surchargind repaint() method:
//method to draw elements on the map
public void paint(Graphics g) {
super.paintComponents(g);
Graphics gr;
gr = MasterMindPane.getGraphics();
img = MasterMindPane.getToolkit().getImage("images/plateau4-8.jpg");
gr.drawImage(img, 0, 0, 600, 720, this);
gr = bouleRougePane.getGraphics();
img = bouleRougePane.getToolkit().getImage("images/bouleRouge.png");
//gr.drawImage(img, 535, 303, 45, 45, this);
gr.drawImage(img, 0, 0, 45, 45, this);
gr = bouleOrangePane.getGraphics();
img = bouleOrangePane.getToolkit().getImage("images/bouleOrange.png");
//gr.drawImage(img, 535, 303, 45, 45, this);
gr.drawImage(img, 0, 0, 45, 45, this);
}
When I click on one image, which have a Panel, I draw a yellow circle like that :
private void bouleRougePaneMouseClicked(java.awt.event.MouseEvent evt) {
Graphics2D g2d = (Graphics2D) MasterMindPane.getGraphics();
for(int i = 0; i<4; i++)
{
g2d.setColor(Color.ORANGE);
g2d.setStroke(new BasicStroke(3));
g2d.drawOval(78+i*70, 106+etape*50, 35, 35);
}
}
And when I select a hole, I want to delete the circle, which only indicates where the gamer can play.
But I don't know how to delete the circle or repaint just a part of my Image because it costs a lot to repaint all.
A very simple way is to use paintImmediately(x,y,w,h);
This repaints only the specified area that starts at pixel (x,y) with width w and height h.
You can set clip Shape to the thick oval and fill it.
Create the big oval Shape via BasicStroke with thick line.
Using java awt, how to make the code draw a border for a circle. The henceforth code has performance issues, and maybe it would run faster if it just painted the outline.
g.fillOval(gameLogic.getParticleXCoor(i) - 3,
gameLogic.getParticleYCoor(i) - 3,
gameLogic.getParticleSize(i) + 6,
gameLogic.getParticleSize(i) + 6);
g.setColor(gameLogic.getParticleColor(i));
g.fillOval(gameLogic.getParticleXCoor(i),
gameLogic.getParticleYCoor(i),
gameLogic.getParticleSize(i),
gameLogic.getParticleSize(i));
You could try drawOval instead of fillOval.
If you want paint circle use Ellipse2D class:
Ellipse2D.Double circleBorder = new Ellipse2D.Double(x, y, 15, 15);
After just call draw() methid from Graphics2D
g2.draw(circleBorder);
Full code for draw circle icons as example is here:
#Override
public void paintIcon(#Nonnull Component c, #Nonnull Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g;
RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
BasicStroke dashed =new BasicStroke(3.0f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER,10.0f);
Ellipse2D.Double circle = new Ellipse2D.Double(x+1, y+1, 14, 14);
Ellipse2D.Double circleBorder = new Ellipse2D.Double(x, y, 15, 15);
g2.setColor(getColor());
g2.setRenderingHints(hints);
g2.fill(circle);
Composite oldComposite=g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0));
g2.setColor(new Color(1,1,1,1));
g2.setStroke(dashed);
g2.draw(circleBorder);
g2.setComposite(oldComposite);
}