Related
Is there a way to display an item in the middle of the chart?
Using the chart to output values from the database.
I'd like to place the next item in the center of each pie.
Is there a way? Below is the code.
public class DrawingPiePanel extends JPanel {
public DrawingPiePanel() {
}
private static final long serialVersionUID = 1L;
Admin ad = Login.ad;
String month = ad.year1 + "-01";
kiosk_dao dao = new kiosk_dao();
int Kor = dao.SelectSaleMonthRestaurant(month, "한식");
int Ch = dao.SelectSaleMonthRestaurant(month, "중식");
int Jp = dao.SelectSaleMonthRestaurant(month, "일식");
int We = dao.SelectSaleMonthRestaurant(month, "양식");
public void paint(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
int Total = Kor + Ch + Jp + We;
if (Total != 0) {
int arc1 = (int) 360.0 * Kor / Total;
int arc2 = (int) 360.0 * Ch / Total;
int arc3 = (int) 360.0 * Jp / Total;
int arc4 = 360 - (arc1 + arc2 + arc3);
double KorPer = (double) Kor / (double) Total * 100;
double ChPer = (double) Ch / (double) Total * 100;
double JpPer = (double) Jp / (double) Total * 100;
double WePer = (double) We / (double) Total * 100;
g.setColor(Color.YELLOW);
g.fillArc(50, 20, 200, 200, 0, arc1);
g.setColor(Color.RED);
g.fillArc(50, 20, 200, 200, arc1, arc2);
g.setColor(Color.BLUE);
g.fillArc(50, 20, 200, 200, arc1 + arc2, arc3);
g.setColor(Color.GREEN);
g.fillArc(50, 20, 200, 200, arc1 + arc2 + arc3, arc4);
g.setColor(Color.BLACK);
g.setFont(new Font("굴림체", Font.PLAIN, 12));
g.drawString(" 한식: 노랑" + String.format("%.2f", KorPer) + "%", 300, 150);
g.drawString(" 중식: 빨강" + String.format("%.2f", ChPer) + "%", 300, 170);
g.drawString(" 일식: 파랑" + String.format("%.2f", JpPer) + "%", 300, 190);
g.drawString(" 양식: 초록" + String.format("%.2f", WePer) + "%", 300, 210);
g.drawString(" 총매출액: " + Total + " 원", 300, 230);
}
}
}
I tried to use a Shape to draw the arcs and an Area to calculate the center of the filled arc.
It does a reasonable job, but not perfect:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.geom.*;
public class DrawPie extends JPanel
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawArc(g2d, Color.YELLOW, 0, 70, "Y");
drawArc(g2d, Color.RED, 70, 80, "R");
drawArc(g2d, Color.BLUE, 150, 90, "B");
drawArc(g2d, Color.GREEN, 240, 120, "G");
g2d.dispose();
}
private void drawArc(Graphics2D g2d, Color color, int start, int extent, String text)
{
g2d.setColor( color );
Shape shape = new Arc2D.Double(50, 50, 200, 200, start, extent, Arc2D.PIE);
g2d.fill( shape );
Rectangle bounds = new Area(shape).getBounds();
System.out.println(bounds);
int centerX = bounds.x + (bounds.width / 2) - 5;
int centerY = bounds.y + (bounds.height / 2) + 7;
g2d.setColor( Color.BLACK );
g2d.drawString(text, centerX, centerY);
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(300, 300);
}
public static void main(String[] args)
{
EventQueue.invokeLater(() ->
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(new DrawPie()));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
The adjustments to the centerX/Y values was a shortcut for using the real FontMetrics of the Graphics class. The X value should be half the width of the text you draw and the Y value should be the height test you draw. You can try playing with the real FontMetrics to see if it makes a difference.
Note, this is an example of an "minimal, reproducible example". Only the code directly related to the question is included in the example. Anybody can copy/paste/compile and text. In the future all questions should include an MRE to demonstrate the problem.
Edit:
My second attempt which attempts to use Andrew's suggestion to determine a point on a line that is half the arc angle and half the radius.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.geom.*;
public class DrawPie extends JPanel
{
private int inset = 25;
private int radius = 100;
private int diameter = radius * 2;
private int translation = inset + radius;
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawArc(g2d, Color.YELLOW, 0, 70, "Y");
drawArc(g2d, Color.RED, 70, 90, "R");
drawArc(g2d, Color.CYAN, 160, 80, "B");
drawArc(g2d, Color.GREEN, 240, 120, "G");
g2d.dispose();
}
private void drawArc(Graphics2D g2d, Color color, int start, int extent, String text)
{
g2d.setColor( color );
Shape shape = new Arc2D.Double(inset, inset, diameter, diameter, start, extent, Arc2D.PIE);
g2d.fill( shape );
double radians = Math.toRadians(90 + start + (extent / 2));
int centerX = (int)(Math.sin(radians) * radius / 2);
int centerY = (int)(Math.cos(radians) * radius / 2);
g2d.setColor( Color.BLACK );
g2d.drawString(text, centerX + translation, centerY + translation);
}
#Override
public Dimension getPreferredSize()
{
int size = (inset * 2) + diameter;
return new Dimension(300, 300);
}
public static void main(String[] args)
{
EventQueue.invokeLater(() ->
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(new DrawPie()));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
Don't know why I needed to add "90" when converting the angle to radians?
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();
}
}
I'm getting this error: The nested type cannot hide an enclosing type. I have looked it up, and other people seem to be declaring their class twice, which I am not.
What's weird is if I copy and paste the code into a new processing document, it works with no error. But as I'm converting it to js i need it to work with no errors after saving and opening again.
MotorBike Bike1, Bike2, Bike3, Bike4, Bike5, Bike6, Bike7, Bike8, Bike9;
int Score_Bike1 = 0;
int Score_Bike2 = 0;
int Score_Bike3 = 0;
int Score_Bike4 = 0;
int Score_Bike5 = 0;
int Score_Bike6 = 0;
int Score_Bike7 = 0;
int Score_Bike8 = 0;
int Score_Bike9 = 0;
String Score_Spacing = " ";
int GameState = 0;
class MotorBike {
float Pos_X;
int Pos_Y;
float Speed;
int Size = 30;
float WheelSize = Size / 3;
color Color;
MotorBike(int Declare_X, int Declare_Y, int Declare_Speed, color Declare_Color)
{
this.Pos_X = Declare_X;
this.Pos_Y = Declare_Y;
Speed = Declare_Speed;
Color = Declare_Color;
}
void move()
{
if (GameState == 1) {
Speed = (random(0, 50) / 10);
Pos_X = Pos_X + Speed;
}
}
void render()
{
fill(Color);
triangle(Pos_X, Pos_Y, Pos_X + Size, Pos_Y, Pos_X + Size / 2, Pos_Y -Size / 2);
fill(255);
strokeWeight(1.5);
ellipse(Pos_X, Pos_Y, WheelSize, WheelSize);
ellipse(Pos_X + Size, Pos_Y, WheelSize, WheelSize);
}
}
void setup()
{
size(700, 600);
background(200);
SpawnBikes();
}
void draw()
{
background(200);
strokeWeight(3);
line(50, 10, 50, 590);
line(650, 10, 650, 590);
strokeWeight(1);
MoveBikes();
DetectWinner();
DisplayScore();
}
void MoveBikes()
{
Bike1.render();
Bike1.move();
Bike2.render();
Bike2.move();
Bike3.render();
Bike3.move();
Bike4.render();
Bike4.move();
Bike5.render();
Bike5.move();
Bike6.render();
Bike6.move();
Bike7.render();
Bike7.move();
Bike8.render();
Bike8.move();
Bike9.render();
Bike9.move();
}
void DetectWinner()
{
textSize(15);
fill(0);
if (Bike1.Pos_X >= 620) {
noLoop();
text("Bike 1 Wins", 310, 10, 350, 50);
Score_Bike1 += 1;
GameState = 2;
}
if (Bike2.Pos_X >= 620) {
noLoop();
text("Bike 2 Wins", 310, 10, 350, 50);
Score_Bike2 += 1;
GameState = 2;
}
if (Bike3.Pos_X >= 620) {
noLoop();
text("Bike 3 Wins", 310, 10, 350, 50);
Score_Bike3 += 1;
GameState = 2;
}
if (Bike4.Pos_X >= 620) {
noLoop();
text("Bike 4 Wins", 310, 10, 350, 50);
Score_Bike4 += 1;
GameState = 2;
}
if (Bike5.Pos_X >= 620) {
noLoop();
text("Bike 5 Wins", 310, 10, 350, 50);
Score_Bike5 += 1;
GameState = 2;
}
if (Bike6.Pos_X >= 620) {
noLoop();
text("Bike 6 Wins", 310, 10, 350, 50);
Score_Bike6 += 1;
GameState = 2;
}
if (Bike7.Pos_X >= 620) {
noLoop();
text("Bike 7 Wins", 310, 10, 350, 50);
Score_Bike7 += 1;
GameState = 2;
}
if (Bike8.Pos_X >= 620) {
noLoop();
text("Bike 8 Wins", 310, 10, 350, 50);
Score_Bike8 += 1;
GameState = 2;
}
if (Bike9.Pos_X >= 620) {
noLoop();
text("Bike 9 Wins", 310, 10, 350, 50);
Score_Bike9 += 1;
GameState = 2;
}
}
void DisplayScore()
{
textSize(15);
fill(0);
text("Bike 1: " + Score_Bike1 + Score_Spacing + "Bike 2: " + Score_Bike2 + Score_Spacing + "Bike 3: " +
Score_Bike3 + Score_Spacing + "Bike 4: " + Score_Bike4 + Score_Spacing + "Bike 5: " + Score_Bike5 + Score_Spacing +
"Bike 6: " + Score_Bike6 + Score_Spacing + "Bike 7: " + Score_Bike7 + Score_Spacing + "Bike 8: " + Score_Bike8 +
Score_Spacing + "Bike 9: " + Score_Bike9, 65, 530, 635, 700);
}
void keyPressed()
{
if (keyPressed) {
if (key == ' ')
{
if (GameState == 0) {
GameState = 1;
}
if (GameState == 2) {
loop();
background(200);
SpawnBikes();
GameState = 0;
}
}
}
}
void SpawnBikes()
{
Bike1 = new MotorBike(50, 100, 2, color(255, 0, 0));
Bike2 = new MotorBike(50, 150, 2, color(0, 255, 0));
Bike3 = new MotorBike(50, 200, 2, color(0, 0, 255));
Bike4 = new MotorBike(50, 250, 2, color(255, 255, 0));
Bike5 = new MotorBike(50, 300, 2, color(0, 255, 255));
Bike6 = new MotorBike(50, 350, 2, color(255, 0, 255));
Bike7 = new MotorBike(50, 400, 2, color(100, 255, 0));
Bike8 = new MotorBike(50, 450, 2, color(0, 100, 255));
Bike9 = new MotorBike(50, 500, 2, color(255, 0, 100));
}
Your problem is caused by the fact that you're naming your sketch the same thing as a class you're using inside your sketch. Your sketch can't be named MotorBike if you have a MotorBike class inside that sketch.
Either rename your sketch, or rename your class.
Behind the scenes, this is because Processing exports your sketch as a Java class, and any classes in your sketch become inner classes of that Java class. So your sketch becomes something like this:
class MotorBike{
void draw(){
//whatever
}
class MotorBike{
int x;
//whatever
}
}
This is illegal Java, which is what's causing your error. You can't have an inner class with the same name as a parent class. In other words, a nested type cannot hide an enclosing type.
This is also why it works okay when you copy it into a new sketch- Processing gives your sketch a random default name, so you don't have this name collision until you save your sketch as something else.
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();
}
}
}
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.