g.fillPolygon not updating location (Integer arrays not updating...?) - java

I've come across a problem when trying to move a custom polygon around a JPanel with the mouse; the location for the polygon never updates, even on repaint:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.ArrayList;
import java.util.List;
public class Figure extends JPanel{
/**
*
*/
private static final long serialVersionUID = 1L;
public int nPoints = 17, x = 120, y = -60;
int MouseX, MouseY;
final static int SIZE = 400;
public int[] xPoints = {x + 100, x + 85, x + 70, x + 55, x + 40, x + 55, x + 55, x + 40, x + 25, x + 55, x + 55, x + 85, x + 85, x + 115, x + 100, x + 85, x + 85};
public int[] yPoints = {y + 375, y + 385, y + 340, y + 385, y + 375, y + 335, y + 200, y+ 240, y + 225, y + 185, y + 175, y + 175, y + 185, y + 220, y + 240, y + 200, y + 335, y + 375};
List<Integer> xList = new ArrayList<Integer>();
List<Integer> yList = new ArrayList<Integer>();
static final Figure m = new Figure();
public static void main(String[] args){
final JFrame frame = new JFrame();
frame.setTitle("Figure");
frame.getContentPane().add(m);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(SIZE, SIZE);
frame.setResizable(true);
frame.setVisible(true);
m.setBackground(Color.darkGray);
}
public void mouseMovement(){
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
if(((e.getX() >= xPoints[8] && e.getX() <= xPoints[13]) && (e.getY() >= yPoints[10] && e.getY() <= yPoints[1])) || ((e.getX() >= (x + 45) && e.getX() <= (x + 45 + SIZE / 8)) && (e.getY() >= (y + 102) && e.getY() <= (y + 102 + SIZE / (57 / 10))))){
x = e.getX() - 75;
y = e.getY() - 150;
repaint();
}else{
repaint();
}
}
});
}
public Figure(){
mouseMovement();
}
#Override
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.black);
g.fillPolygon(xPoints, yPoints, nPoints);
g.fillPolygon(xPoints, yPoints, nPoints);
g.setColor(Color.white);
g.fillOval(x + 45, y + 102, SIZE / 8, SIZE / (57 / 10));
}
}
My thoughts on this are that the integer array is not updating properly using my predefined variables, but then I come across the problem of not knowing how to properly update it. It seems like it should, considering the location for the oval i made to represent the figure's "head" does, but apparently I'm wrong on that, so I'd like to know why just using the array in fillPolygon doesn't work and how I'd get the location to update. Many thanks in advance.

Use the Polygon class to create a Polygon using your Array of points.
Then in the painting method you can cast the Graphics object to a Graphics2D object and use the Graphics2D.fill(Shape) method to paint the polygon.
When you need to move the Polygon you can use the translate(...) method of the Polygon class.
Also, you should NOT be overriding the paint() method. Custom painting is done by overriding the paintComponent() method.

Related

counter updating/repainting graphics

I'm creating a Hangman game where a player enters a word and the other player tries to guess that word. There are 26 JButtons on the screen (with each letter of the alphabet).
Each time a correct letter is chosen a counter variable increments. The number of the counter variable dictates how much of the hangman is drawn (7 is when the hangman is fully drawn). I can get counter to increment when the correct letter is chosen but I cannot get parts of the hangman to be drawn when it does increment.
Here is my Hangman class that draws the Hangman and includes the incrementCounter method:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class HangMan extends JPanel implements ActionListener {
private int xS = 8;
private int yS = 30;
public int counter;
private Color hatColor = Color.BLACK;
private int dx = 0;
private int dy = 0;
public HangMan(int initalX, int initalY) {
// starting location
xS = initalX;
yS = initalY;
counter = 0;
Dimension dim = new Dimension(250, 475);
this.setPreferredSize(dim);
setFocusable(true);
requestFocusInWindow();
this.setVisible(true);
}
public void drawHangMan(Graphics g) {
g.setColor(Color.BLACK);
if (counter == 0) {
repaint();
}
if (counter == 1) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
repaint();
}
if (counter == 2) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
repaint();
}
if (counter == 3) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
repaint();
}
if (counter == 4) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
drawLeftLeg(xS - 20, yS + 225, xS + 25, yS + 175, g); //left leg
repaint();
}
if (counter == 5) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
drawLeftLeg(xS - 20, yS + 225, xS + 25, yS + 175, g); //left leg
drawRightLeg(xS + 25, yS + 175, xS + 65, yS + 225, g); //right leg
repaint();
}
if (counter == 6) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
drawLeftLeg(xS - 20, yS + 225, xS + 25, yS + 175, g); //left leg
drawRightLeg(xS + 25, yS + 175, xS + 65, yS + 225, g); //right leg
drawLeftArm(xS - 20, yS + 90, xS + 25, yS + 120, g); //left arm
repaint();
}
if (counter == 7) {
drawHat(xS + 15, yS - 1, 20, 25, g); // hat
drawBrim(xS + 10, yS + 25, 30, 6, g); // brim
drawHead(xS, yS + 30, 50, 50, g); // head
drawBody(xS + 25, yS + 80, xS + 25, yS + 175, g); // body
drawLeftLeg(xS - 20, yS + 225, xS + 25, yS + 175, g); //left leg
drawRightLeg(xS + 25, yS + 175, xS + 65, yS + 225, g); //right leg
drawLeftArm(xS - 20, yS + 90, xS + 25, yS + 120, g); //left arm
drawRightArm(xS + 25, yS + 120, xS + 70, yS + 90, g); //right arm
repaint();
}
}
public void drawLeftArm(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawRightArm(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawLeftLeg(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawRightLeg(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawBody(int a, int b, int x, int y, Graphics g) {
g.drawLine(a, b, x, y); //left arm
repaint();
}
public void drawHead(int a, int b, int x, int y, Graphics g) {
g.drawOval(a, b, x, y); //left arm
repaint();
}
public void drawHat(int a, int b, int x, int y, Graphics g) {
g.drawRect(a, b, x, y); //left arm
repaint();
}
public void drawBrim(int a, int b, int x, int y, Graphics g) {
g.drawRect(a, b, x, y); //left arm
repaint();
}
public void drawHanger(Graphics g) {
g.fillRect(xS - 125, yS + 300, 80, 20);
g.drawLine(xS - 85, yS + 300, xS - 85, yS + 80);
g.drawLine(xS - 85, yS + 80, xS + 22, yS + 80);
}
public void incrementCounter() {
counter++;
System.out.println("counter = " + counter);
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawHangMan(g);
drawHanger(g);
repaint();
g.setFont(new Font("Sherif", Font.BOLD, 40));
}
public void actionPerformed(ActionEvent e) {
repaint();
}
}
Now here is my Button Class that draws the 26 JButtons and includes the ActionListener that will call the update method every time a button is clicked
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Button extends JPanel {
JButton[] grid = new JButton[26];
Dashes dash;
public Button(String str, Dashes dash) {
this.dash = dash;
final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Dimension dim = new Dimension(360, 360);
this.setPreferredSize(dim);
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
System.out.println(action);
dash.update(action);
dash.repaint();
/*
add(new JLabel(action + ""));
setVisible(true);
*/
}
};
for (int i = 0; i < grid.length; i++) {
grid[i] = (JButton) this.add(new JButton(alphabet.charAt(i) + ""));
grid[i].addActionListener(listener);
this.setVisible(true);
}
}
}
and here is my Dashes class that contains the update method
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Dashes extends JPanel {
JLabel label;
String word;
String guess = "";
HangMan hang;
public Dashes(String word) {
this.word = word;
hang = new HangMan(150, 150);
for (int i = 0; i < word.length(); i++) {
guess += " ";
}
word = word.toUpperCase();
Dimension dim = new Dimension(1500, 300);
this.setPreferredSize(dim);
this.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
drawDashes(g2d);
}
private void drawDashes(Graphics2D g2d) {
for (int i = 0; i < word.length() * 50; i += 50) {
g2d.draw(new Line2D.Double(100.0 + i, 200.0, 125.0 + i, 200.0));
for (int j = 0; j < guess.length(); j++) {
g2d.drawString(guess.charAt(j) + "", 108 + j * 50, 198);
}
// g2d.drawString("m", 108 + i, 198);
}
}
public void update(String str) {
for (int i = 0; i < word.length(); i++) {
if (str.equals(word.charAt(i) + "")) {
guess = guess.substring(0, i) + str + guess.substring(i + 1);
hang.incrementCounter();
hang.repaint();
}
}
}
}
I'm sorry for making such a small problem so long. I would like to mention that if I initially set counter to be 2, for example, it would correctly draw the hat, brim and head. Some background: I was assigned a Java graphics project without ever actually having been taught graphics!
1 - Remove repaint() from the paint logic (as said in comment)
2 - in Dashes.update() use String.equalsIgnoreCase() instead of String.equals() (probably you have lowercase word and are comparing with uppercase charactere from the Button class).
3 - in Dashes.update() increment counter and repaint HangMan only if you miss:
public void update(String str) {
boolean found = false;
for (int i = 0; i < word.length(); i++) {
if (str.equalsIgnoreCase(word.charAt(i) + "")) {
guess = guess.substring(0, i) + str + guess.substring(i + 1);
found = true;
}
}
if(!found) {
hang.incrementCounter();
hang.repaint();
}
}

How do I stop my paint method form repeating twice?

Here is the code for a dice game that I am working on that outputs the results to a window. The paint method repeats twice, which is not good for me because I want the dice to roll once and then move on to the next frame. Please someone help me with this problem. Thank you in advance.
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class Dice extends JApplet {
public static int pause(int n)
{
try {
Thread.sleep(n);
} catch(InterruptedException e) {
}
return n;
}
public void Dice() {
JApplet app = new Dice();
JFrame frame = new JFrame("Dice Game");
frame.setBounds(30, 50, 1300, 650);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(app);
}
public void paint(Graphics g) {
int width = getWidth();
int height = getHeight();
int num = 0;
for (int i = 0; i < 7; i++) {
Random generator= new Random();
int number = generator.nextInt(6)+1;
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
g.setColor(Color.BLACK);
g.drawRoundRect(550, 150, 200, 200, 50, 50);
System.out.println("Test");
if (number == 1) { //Roll one
num = 1;
g.setColor(new Color (0, 0, 0));
g.fillOval(640, 240, 20, 20);
pause(100);
} if (number == 2) { //Roll two
num = 2;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 290, 20, 20);
g.fillOval(690, 190, 20, 20);
pause(100);
} if (number == 3) { //Roll three
num = 3;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 290, 20, 20);
g.fillOval(640, 240, 20, 20);
g.fillOval(690, 190, 20, 20);
pause(100);
} if (number == 4) { //Roll four
num = 4;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 290, 20, 20);
g.fillOval(590, 190, 20, 20);
g.fillOval(690, 290, 20, 20);
g.fillOval(690, 190, 20, 20);
pause(100);
} if (number == 5) { //Roll five
num = 5;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 290, 20, 20);
g.fillOval(590, 190, 20, 20);
g.fillOval(640, 240, 20, 20);
g.fillOval(690, 290, 20, 20);
g.fillOval(690, 190, 20, 20);
pause(100);
} if (number == 6) { //Roll six
num = 6;
g.setColor(new Color (0, 0, 0));
g.fillOval(590, 190, 20, 20);
g.fillOval(590, 240, 20, 20);
g.fillOval(590, 290, 20, 20);
g.fillOval(690, 190, 20, 20);
g.fillOval(690, 240, 20, 20);
g.fillOval(690, 290, 20, 20);
pause(100);
}
}
g.setFont(new Font("TimesRoman", Font.PLAIN, 20));
g.drawString("You rolled a " + num, 590, 100);
pause(1000);
}
}
The short answer is - you can't. You don't control when painting occurs that is the domain of the RepaintManager.
You should also NEVER call Thread.sleep within the context of the Event Dispatching Thread and especially not within any paint method
You should avoid overriding paint and instead use paintComponent
You should avoid extending from JFrame and instead use something like JPanel, which actually has a paintComponent method.
Animation of this nature is best achieved by using a Swing Timer, which will allow to employee a pause which is maintained outside of the EDT, but is triggered again within in the EDT making it safer to perform painting and updates
Take a look at
Concurrency in Swing
How to Use Swing Timers
Performing Custom Painting
Painting in AWT and Swing
For more details about how painting works in Swing and how to achieve what you are trying to do
Updated with working example
Cause I'm lazy, I've utilised the Graphics 2D API to draw the dots. I did this because many of the dots appear in the same locations for many of the numbers...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DiceRoller {
public static void main(String[] args) {
new DiceRoller();
}
public DiceRoller() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Die());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Die extends JPanel {
private int number = 1;
public Die() {
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
number = (int) (Math.round((Math.random() * 5) + 1));
repaint();
}
});
timer.setRepeats(true);
timer.setInitialDelay(0);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(220, 220);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
g2d.setColor(Color.BLACK);
g2d.drawRoundRect(10, 10, width - 20, height - 20, 50, 50);
List<Shape> dots = new ArrayList<>(6);
if (number == 1 || number == 3 || number == 5) {
int x = (width - 20) / 2;
int y = (height - 20) / 2;
dots.add(new Ellipse2D.Float(x, y, 20, 20));
}
if (number == 2 || number == 3 || number == 4 || number == 5 || number == 6) {
int x = ((width / 2) - 20) / 2;
int y = ((height / 2) - 20) / 2;
dots.add(new Ellipse2D.Float(x, y, 20, 20));
dots.add(new Ellipse2D.Float(x + (width / 2), y + (height / 2), 20, 20));
}
if (number == 4 || number == 5 || number == 6) {
int x = (width / 2) + (((width / 2) - 20) / 2);
int y = ((height / 2) - 20) / 2;
dots.add(new Ellipse2D.Float(x, y, 20, 20));
dots.add(new Ellipse2D.Float(x - (width / 2), y + (height / 2), 20, 20));
}
if (number == 6) {
int x = (((width / 2) - 20) / 2);
int y = (height - 20) / 2;
dots.add(new Ellipse2D.Float(x, y, 20, 20));
dots.add(new Ellipse2D.Float(x + (width / 2), y, 20, 20));
}
for (Shape dot : dots) {
g2d.fill(dot);
}
g2d.dispose();
}
}
}

Determining a winner in java race car program

I am trying to find a way to determine a winner and I am not having much luck. The program is suppose to run three laps and which ever car finish all the laps first is the winner. I can get 3 "laps" in but it is not a very good way of doing it. I am hoping someone can show me a better way and also how I can can "count" those laps for the specific winning car. The number of cars is random from 2 - 4 and the "speed" is also random. Can someone help me please. Some code would be nice.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class RacingCar extends JFrame {
public RacingCar() {
int x = (int)(Math.random() * 3) + 2;
setLayout(new GridLayout(x, 1, 5,5));
for (int i = 0; i < x; i++){
add(new CarImage());
}
}
public static void main(String[] args) {
JFrame frame = new RacingCar();
frame.setTitle("Racing Car");
frame.setSize(1200, 350);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
class CarImage extends JPanel {
protected int x = 0;
protected int y = 350;
protected int z = 1200;
protected int c = 0;
public CarImage() {
int j = (int)(Math.random() * 500) + 2;
Timer timer1 = new Timer(j, new ActionListener(){
public void actionPerformed(ActionEvent e) {
x += 10;
c ++;
repaint();
}
});
timer1.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//x = 0;
y = getHeight();
z = getWidth();
g.setColor(Color.WHITE);
g.fillRect(0, 0, z, y);
Polygon polygon = new Polygon();
polygon.addPoint(x + 10, y - 21);
polygon.addPoint(x + 20, y - 31);
polygon.addPoint(x + 30, y - 31);
polygon.addPoint(x + 40, y - 21);
if (x < z - 50) {
g.setColor(Color.BLACK);
g.fillOval(x + 10, y - 11, 10, 10);
g.fillOval(x + 30, y - 11, 10, 10);
g.setColor(Color.BLUE);
g.fillRect(x, y - 21, 50, 10);
g.setColor(Color.GRAY);
g.fillPolygon(polygon);
g.setColor(Color.RED);
}
else {
x = 0;
/*if (c < z - 86) {
g.drawString("Clint's Car", c, y - 51);
}
else {
c = 0;
}*/
}
}
}
}
What I did for the laps loop is this:
if (k < 341){
repaint();
k++;
{
this loop was inserted at the end of:
public void paintComponent(Graphics g) {
I really am stuck here. Thanks for all the help.
Give this code a try
New RacingCar.java
By the way I made your timer be faster in order to not wait 3 laps on really slow races! :P

Is it possible to create my own Graphics2D and combine with another in a Applet?

Normally an applet will call different methods that will have a Graphics2D-object that ends on the screen.
In the process the methods will manipulate and draw things on this object.
But my problem is, that I have some very static images that needs to be calculated and drawn for each frame.
How can I build an Graphics-object that I can cache, and re-apply the moving objects? For an example I have this static background drawer, the Graphics2D-object is the one from the Applet.
private Graphics2D drawbackground(Graphics2D g2d) {
// Debug grid layer
int x = 0;
int y = 0;
for (int i = 0; i < 9; i++) {
if (x == 0 && y == 0 || y % 82 == 0) {
x = 0;
for (int t = 0; t <= 5; t++) {
g2d.setColor(Color.WHITE);
g2d.drawLine(x, y + 41, x + 41, y);
g2d.drawLine(x + 41, y, x + 82, y + 41);
g2d.drawLine(x, y + 41, x + 41, y + 82);
g2d.drawLine(x + 82, y + 41, x + 41, y + 82);
x += 82;
}
y += 41;
} else if (y % 41 == 0) {
x = 41;
for (int t = 0; t <= 5; t++) {
g2d.setColor(Color.WHITE);
g2d.drawLine(x, y + 41, x + 41, y);
g2d.drawLine(x + 41, y, x + 82, y + 41);
g2d.drawLine(x, y + 41, x + 41, y + 82);
g2d.drawLine(x + 82, y + 41, x + 41, y + 82);
x += 82;
}
y += 41;
}
}
}
Is it possible to generate these drawings, and re-use them in a cached copy, so my Applet doesn't need to use time to run through these drawLines for each draw?
I agree with Raveline, BufferedImage is where I would go for this solution. However Double buffering is the concept that you need to get your head around before you go too deep into this.
http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html

Transparent circular dialog in Java

I'm building a Poker Odds Calc app in Java. I want to select a new card by clicking the card's placeholder which is basically an extended JPanel that I "draw" the card's face and has a mouseListener.
What I have imagined to do is that when I clicked the card, I would like a round menu to pop up around the mouse cursor having a circle in the middle cut in four with each suite in a quarter and a ring around it cut in thirteen for the value of the card. Then I will select suit and value and it would disappear. Do you know any way I could do this? I researched a bit and I think it can be done with JavaFX by making a transparent JDialog but I'm not sure.
Is there a way to draw a totally custom shaped JComponent like a JButton shaped for each quarter of the circle etc.? I have some experience in Java but not GUI building.
Thanks in advance for your time.
edit: Used your comment and have answered my question about the circular dialog (don't know if it's the best way to do it but works for now). Now, is there anyway I know in which area the click belongs (if the click was on a useful area) without hardcoding the coordinates?
I would suggest doing custom graphics rather than trying to customize JButton and so on. When you click on the JPanel you can draw the circle and so on using the java.awt.Shape interfaces and its various implementations such as java.awt.geom.Ellipse2D.
These shapes come with contains() method that can tell you if a point is in the Shape or not. This way, when the user next clicks on the JPanel, you can determine which shape the user clicked on by going through all the shapes and checking.
The code to create the graphics is this in case anyone needs it:
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D.Double;
import javax.swing.JDialog;
/**
*
* #author Dimitris Klimis <dnklimis at gmail.com>
*/
public class CardChooser extends JDialog implements MouseListener {
int sizeX = 140;
int sizeY = sizeX; //in case I don't want it to be circle
int x, y;
Point point;
public CardChooser(Point point) {
x = point.x;
y = point.y;
this.point = point;
this.initComponents();
}
public static int[] getCard(Point point) {
int[] output = {0, 0};
CardChooser chooser = new CardChooser(point);
return output;
}
#Override
public void paint(Graphics g) {
if (g instanceof Graphics2D) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
//Drawing the transparent dialog
g2.setPaint(new Color(0.0f, 0.0f, 0.0f, 0.0f));
g2.fillRect(0, 0, getWidth(), getHeight());
//Drawing the circles
g2.setColor(Color.BLACK);
drawCircle(g2, 100, new GradientPaint(0.0f, 0.0f, Color.darkGray, (float) getWidth(), (float) getHeight(), Color.lightGray, false));
drawLines(g2, 13, 100);
int smallCircle = 38;
drawCircle(g2, smallCircle + 3, Color.GRAY);
drawCircle(g2, smallCircle, new GradientPaint((float) (getWidth() * 0.25), (float) (getHeight() * 0.25), Color.lightGray, (float) (getWidth() * 0.75), (float) (getHeight() * 0.75), Color.darkGray, false));
drawLines(g2, 4, smallCircle);
drawCircle(g2, 10, Color.LIGHT_GRAY);
drawSuiteLetters(g2);
drawCardValues(g2);
drawClosingX(g2);
} else {
super.paint(g);
}
}
private void drawCircle(Graphics2D g2, int percentage, Paint fill) {
double perc = (double) percentage / 100.0;
Ellipse2D ellipse = new Ellipse2D.Double(((1 - perc) / 2) * sizeX, ((1 - perc) / 2) * sizeY, perc * sizeX, perc * sizeY);
g2.setPaint(fill);
g2.fill(ellipse);
g2.setColor(Color.BLACK);
g2.draw(ellipse);
}
private void drawLines(Graphics2D g2, int outOf, int percentage) {
double rads = Math.toRadians(360.0 / outOf);
double perc = (double) percentage / 100.0;
Double zeroAxis = new Point.Double(sizeX / 2.0, sizeY / 2.0);
for (int i = 0; i < outOf; i++) {
g2.draw(new Line2D.Double(zeroAxis.x, zeroAxis.y, zeroAxis.x + (zeroAxis.x * perc * Math.sin(rads * i)), zeroAxis.y + (zeroAxis.y * perc * Math.cos(rads * i))));
}
}
private void drawSuiteLetters(Graphics2D g2) {
Double zeroAxis = new Point.Double(sizeX / 2.0, sizeY / 2.0);
g2.setFont(new Font("Courier New", Font.BOLD, 25));
g2.drawString("\u2660", (float) zeroAxis.x - 18, (float) zeroAxis.y - 5);//spades
g2.drawString("\u2663", (float) zeroAxis.x + 3, (float) zeroAxis.y + 20);//clubs
g2.setColor(Color.RED);
g2.drawString("\u2665", (float) zeroAxis.x + 3, (float) zeroAxis.y - 3);//hearts
g2.drawString("\u2666", (float) zeroAxis.x - 18, (float) zeroAxis.y + 19);//diamonds
g2.setColor(Color.BLACK);
}
private void drawCardValues(Graphics2D g2) {
Double zeroAxis = new Point.Double((sizeX / 2.0) - 8, 21);
float xx = (float) zeroAxis.x;
float yy = (float) zeroAxis.y;
g2.setFont(new Font("Arial", Font.BOLD, 24));
String[] letters = {"A", "K", "Q", "J", "T", "9", "8", "7", "6", "5", "4", "3", "2"};
float[] xPosition = {0, 25, 46, 63, 58, 42, 15, -10, -37, -53, -58, -46, -25};
float[] yPosition = {0, 7, 23, 50, 80, 102, 115, 115, 102, 80, 50, 23, 7};
for (int i = 0; i < 13; i++) {
g2.drawString(letters[i], xx + xPosition[i], yy + yPosition[i]);
}
}
private void drawClosingX(Graphics2D g2) {
Double zeroAxis = new Point.Double(sizeX / 2.0, sizeY / 2.0);
g2.draw(new Line2D.Double(zeroAxis.x - 5, zeroAxis.y - 5, zeroAxis.x + 5, zeroAxis.y + 5));
g2.draw(new Line2D.Double(zeroAxis.x - 5, zeroAxis.y + 5, zeroAxis.x + 5, zeroAxis.y - 5));
}
private void initComponents() {
this.addMouseListener(this);
this.setBounds(x - (sizeX / 2), y - (sizeY / 2), sizeX + 1, sizeX + 1);
this.setUndecorated(true);
this.setModal(true);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setVisible(true);
}
public void mouseClicked(MouseEvent e) {
this.dispose();
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
PS. I extended JDialog cause I couldn't get JPanel to show up...

Categories