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();
}
}
}
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?
This is my first time trying to build a GUI and I've reached an impasse which I can't seem to find the solution to. Currently I have parts of my GUI set up but I want to insert a graph I've created on another class, however, I'm not sure how to link it with my current JFrame. I can get it to work as a separate entity, but not together.
MainDisplay Class:
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MainDisplay.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MainDisplay.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MainDisplay.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MainDisplay.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainDisplay().setVisible(true);
}
});
float LvBTC;
float LvLTC;
float LvETH;
float[] HBTC;
float[] HLTC;
float[] HETH;
float CurETH;
float CurBTC;
float CurLTC;
WebScraper WS1 = new WebScraper();
LvBTC = WS1.LvScrapeBTC();
LvLTC = WS1.LvScrapeLTC();
LvETH = WS1.LvScrapeETH();
HBTC = WS1.HScrapeBTC();
HLTC = WS1.HScrapeLTC();
HETH = WS1.HScrapeETH();
System.out.println("Bitcoin's Current Price is: $"+LvBTC);
System.out.println("Litecoin's Current Price is: $"+LvLTC);
System.out.println("Ethereum's Current Price is: $"+LvETH);
Graph G1 = new Graph();
G1.CurrentValues(HBTC);
for (int i = 0; 5 > i;) {
System.out.println("Day " + (i + 1) + ": $" + G1.CurValues[i]);
i++;
}
System.out.println("Index of largest value: " + G1.IndexLarge(G1.CurValues));
System.out.println("Index of smallest value: " + G1.IndexSmall(G1.CurValues));
Graph Graphing = new Graph();
}
Graph Class:
package comsci_ia;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JFrame;
public class Graph extends JFrame {
int IndexL;
int IndexS;
int DistanceDay1;
int DistanceDay2;
int DistanceDay3;
int DistanceDay4;
int DistanceDay5;
float[] CurValues = new float[5];
ArrayList<Point> points = new ArrayList<>();
public float[] CurrentValues(float[] array) {
DatabaseBrowser DB1 = new DatabaseBrowser();
WebScraper WS1 = new WebScraper();
float[] HBTC = WS1.HScrapeBTC();
float[] HETH = WS1.HScrapeETH();
float[] HLTC = WS1.HScrapeLTC();
float CurHold = 0;
boolean BTCCheck = false;
BTCCheck = Arrays.equals(HBTC, array);
boolean LTCCheck = false;
LTCCheck = Arrays.equals(HLTC, array);
boolean ETHCheck = false;
ETHCheck = Arrays.equals(HETH, array);
if (BTCCheck == true) {
CurHold = DB1.RetriveBTC();
}
if (LTCCheck == true) {
CurHold = DB1.RetriveLTC();
}
if (ETHCheck == true) {
CurHold = DB1.RetriveETH();
}
float pick;
for (int i = 0; 5 > i;) {
for (int z = 0; z < array.length; z++) {
pick = array[z];
pick = pick * CurHold;
CurValues[i] = pick;
i++;
}
}
return CurValues;
}
public int IndexLarge(float[] array) {
float temp = 0;
for (int i = 0; 5 > i;) { //Cycles through ArrayList and replaces temp with the Largest value
if (array[i] > temp) {
temp = array[i];
}
i++;
}
int IndexCheck = 0; //Searches and records the index of "temp" value (Largest value in array)
for (IndexCheck = 0; 5 > IndexCheck;) {
if (array[IndexCheck] == temp) {
break;
}
IndexCheck++;
}
IndexL = IndexCheck;
return IndexL;
}
public int IndexSmall(float[] array) {
float temp = 1000000;
for (int i = 0; 5 > i;) { //Cycles through ArrayList and replaces temp with the smallest value
if (array[i] < temp) {
temp = array[i];
}
i++;
}
int IndexCheck = 0; //Searches and records the index of "temp" value (smallest value in array)
for (IndexCheck = 0; 5 > IndexCheck;) {
if (array[IndexCheck] == temp) {
break;
}
IndexCheck++;
}
IndexS = IndexCheck;
return IndexS;
}
public void Plotter(float[] array) {
/* int DayRefL = IndexL + 1;
int DayRefS = IndexS + 1; */
float ValRange;
float ValPx;
points = null;
ValRange = array[IndexL] - array[IndexS];
ValPx = (300f/ ValRange); //Number is the pixel distance between highest and lowest values
DistanceDay1 = (int) ((int) 50 + ((array[IndexL] - array[0]) * ValPx));
DistanceDay2 = (int) ((int) 50 + ((array[IndexL] - array[1]) * ValPx));
DistanceDay3 = (int) ((int) 50 + ((array[IndexL] - array[2]) * ValPx));
DistanceDay4 = (int) ((int) 50 + ((array[IndexL] - array[3]) * ValPx));
DistanceDay5 = (int) ((int) 50 + ((array[IndexL] - array[4]) * ValPx));
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int DotSize = 10;
int width = g2.getFontMetrics().stringWidth("Today");
int middle = width / 2;
g2.setColor(Color.BLACK);
/* g2.drawLine(10, 10, 10, 410); //Frame Boundaries
g2.drawLine(410, 10, 10, 10); //Frame Boundaries
g2.drawLine(410, 10, 410, 410); //Frame Boundaries
g2.drawLine(410, 410, 10, 410); //Frame Boundaries */
//Axis
g2.drawLine(30, 30, 30, 370);
g2.drawLine(370, 370, 30, 370);
//Points & Connections
PlotPoints(g2, 98, DistanceDay1, DotSize);
g2.drawLine(98, DistanceDay1, 166, DistanceDay2);
PlotPoints(g2, 166, DistanceDay2, DotSize);
g2.drawLine(166, DistanceDay2, 234, DistanceDay3);
PlotPoints(g2, 234, DistanceDay3, DotSize);
g2.drawLine(234, DistanceDay3, 302, DistanceDay4);
PlotPoints(g2, 302, DistanceDay4, DotSize);
g2.drawLine(302, DistanceDay4, 370, DistanceDay5);
PlotPoints(g2, 370, DistanceDay5, DotSize);
//Labels
g2.drawString("Today", 370 - middle, 390);
/* g2.drawString("Test", 98 - middle, 40);
g2.drawString("Test", 146, 25); */
}
private void PlotPoints(Graphics2D g, int x, int y, int r) {
x = x - (r / 2);
y = y - (r / 2);
g.fillOval(x, y, r, r);
}
}
If I run the Graph class as a separate entity it'll result in this: Graph pop-up
Here's a separate version of the Graph code in which a frame will pop up displaying the graph:
package graphing;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Graphing extends JPanel {
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int DotSize = 10;
int width = g2.getFontMetrics().stringWidth("Test");
int middle = width / 2;
g2.setColor(Color.BLACK);
g2.drawLine(10, 10, 10, 390); //Frame Boundaries
g2.drawLine(390, 10, 10, 10); //Frame Boundaries
g2.drawLine(390, 10, 390, 390); //Frame Boundaries
g2.drawLine(390, 390, 10, 390); //Frame Boundaries
//Axis
g2.drawLine(30, 30, 30, 370);
g2.drawLine(370, 370, 30, 370);
//Points & Connections
PlotPoints(g2, 98, 55, DotSize);
g2.drawLine(98, 55, 166, 40);
PlotPoints(g2, 166, 40, DotSize);
g2.drawLine(166, 40, 234, 100);
PlotPoints(g2, 234, 100, DotSize);
g2.drawLine(234, 100, 302, 332);
PlotPoints(g2, 302, 332, DotSize);
g2.drawLine(302, 332, 370, 40);
PlotPoints(g2, 370, 40, DotSize);
//Labels
g2.drawString("Test", 98 - middle, 40);
g2.drawString("Test", 146, 25);
}
private void PlotPoints(Graphics2D g, int x, int y, int r) {
x = x - (r / 2);
y = y - (r / 2);
g.fillOval(x, y, r, r);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(420, 420);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Graphing app = new Graphing();
frame.setContentPane(app);
frame.setVisible(true);
frame.invalidate();
}
}
So, my immediate issue is, you're extending from JFrame, which isn't a good, as this locks the UI into in a single use case (it's not easily re-usable)
My second issue is, you've created a method called paintComponent in JFrame, but since JFrame doesn't use this style of painting, it is never called
So, the first thing I would do is change Graph so it extends from JPanel instead...
public class Graph extends JPanel {
//...
I would then update your paintComponent so it supports the painting process properly...
#Overrride
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
//...
Now, the next problem is, you're going to need to provide some sizing hints so that the layout manager of the container you add it to has some idea about how best to layout the component...
#Override
public Dimension getPreferredSize() {
// I've not been through your code in detail
// so I've not calculated what the actual
// preferred size might be and this is just an
// example you'll have to update
return new Dimension(200, 200);
}
Now, you can create an instance of Graph and add it to what ever container you want
First of all, I wanted to say that I'm not very experienced Java programmer but was forced to learn things very quickly by school assignment. The assignment is to create a grid inside which we have a simple image. When a cell inside an image is clicked, then it's flood filled. The program needs to allow for different type of neighbourhood (4, 6 or 8). I managed to create a program that allows the user to paint the inside the image with different neighbourhoods, however now I'm trying to adjust the program so it would allow the flood fill. My question is - how can I set the boundaries for flood fill? I know that I can set the boundaries based on the color - that's why my image is painted in red, while I was planning to do the filling in black. However, I have no idea how can I put a condition using the color value. I checked different isssues on the net but couldn't quite apply anything to my program.
Here's the code I'm using (just the class for paining):
class MyCanvas extends JPanel implements MouseListener {
private int x,y;
ArrayList<Point> points = new ArrayList<Point>();
ArrayList<Point> points2 = new ArrayList<Point>();
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
int xSiatki = x/20;
int ySiatki = y/20; //gets the rectangle coordinate of grid
System.out.println("Siatka x: " + xSiatki + " " + "y: " + ySiatki );
if(clickEight){
points.add(new Point(xSiatki,ySiatki));
}
if(clickSix){
points2.add(new Point(xSiatki,ySiatki));
}
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Krata(g2d);
Rysunek(g2d);
if (clickStart){
Krata(g2d);
Rysunek (g2d);
repaint();
points.clear();
points2.clear();}
if (clickEight){
Krata(g2d);
Rysunek (g2d);
for(Point p: points) {
int x,y;
x = (int)p.getX();
y = (int)p.getY();
drawEightFlood(g2d, x, y);}
}
if (clickSix){
Krata(g2d);
Rysunek (g2d);
for(Point p: points2) {
int x,y;
x = (int)p.getX();
y = (int)p.getY();
drawSixFlood(g2d, x, y);}
}
}
private void drawEightFlood (Graphics2D g2d, int x, int y){
g2d.setColor(Color.BLACK);
g2d.fillRect (20*x, 20*y, 20, 20);
g2d.fillRect (20*x, 20*(y+1), 20, 20);
g2d.fillRect (20*(x+1), 20*y, 20, 20);
g2d.fillRect (20*(x-1), 20*y, 20, 20);
g2d.fillRect (20*x, 20*(y-1), 20, 20);
g2d.fillRect (20*(x-1), 20*(y+1), 20, 20);
g2d.fillRect (20*(x+1), 20*(y-1), 20, 20);
g2d.fillRect (20*(x-1), 20*(y-1), 20, 20);
g2d.fillRect (20*(x+1), 20*(y+1), 20, 20);
drawEightFlood (g2d, 20*x, 20*(y+1));
drawEightFlood (g2d, 20*(x+1), 20*y);
drawEightFlood (g2d, 20*(x+1), 20*(y+1));
drawEightFlood (g2d, 20*(x-1), 20*(y+1));
drawEightFlood (g2d, 20*x, 20*(y-1));
drawEightFlood (g2d, 20*(x-1), 20*(y-1));
drawEightFlood (g2d, 20*(x-1), 20*(y-1));
drawEightFlood (g2d, 20*(x-1), 20*y);
}
private void drawSixFlood (Graphics2D g2d, int x, int y){
g2d.setColor(Color.BLACK);
g2d.fillRect (20*x, 20*y, 20, 20);
g2d.fillRect (20*x, 20*(y-1), 20, 20);
g2d.fillRect(20*x, 20*(y+1), 20, 20);
g2d.fillRect(20*(x+1), 20*(y-1), 20, 20);
g2d.fillRect(20*(x+1), 20*y, 20, 20);
g2d.fillRect(20*(x-1), 20*y, 20, 20);
g2d.fillRect(20*(x-1), 20*(y+1), 20, 20);
drawSixFlood (g2d, 20*x, 20*(y+1));
drawSixFlood (g2d, 20*(x+1), 20*y);
drawSixFlood (g2d, 20*(x-1), 20*(y+1));
drawSixFlood (g2d, 20*x, 20*(y-1));
drawSixFlood (g2d, 20*(x-1), 20*(y-1));
drawSixFlood (g2d, 20*(x-1), 20*y);
}
public void Krata (Graphics2D g2d) { //code for grid
for(int i=0; i<54; i++) {
for(int j=0; j<34; j++) {
g2d.setColor(Color.BLACK);
g2d.drawRect (20*i, 20*j, 20, 20);
}
}
}
public void Rysunek (Graphics2D g2d){ //code for the image
for (int i=0; i<54;i++){
for (int j=0; j<34; j++){
if ((i == 0 || i == 53) && (j>12 && j<21 )){
g2d.setColor(Color.RED);
g2d.fillRect(20*i, 20*j, 20, 20);
}
if (((i>0 && i<11) || (i>42 && i<53)) &&(j == 13 || j == 20)){
g2d.setColor(Color.RED);
g2d.fillRect(20*i, 20*j, 20, 20);
}
if ((i > 16 && i < 37) && (j == 7 || j == 20)){
g2d.setColor(Color.RED);
g2d.fillRect(20*i, 20*j, 20, 20);
}
if ((i > 10 && i < 17) && (j == (23-i))){
g2d.setColor(Color.RED);
g2d.fillRect(20*i, 20*j, 20, 20);
}
if ((i > 36 && i < 43) && (j == (i-30))){
g2d.setColor(Color.RED);
g2d.fillRect(20*i, 20*j, 20, 20);
}
if (((i > 10 && i < 17) || (i>36 && i<43)) && (j==23 || j==18)){
g2d.setColor(Color.RED);
g2d.fillRect(20*i, 20*j, 20, 20);
}
if ((i == 11 || i == 16 || i == 37 || i == 42) && (j>18 && j<23)){
g2d.setColor(Color.RED);
g2d.fillRect(20*i, 20*j, 20, 20);
}
}
}
}
}
The code you present is pretty incomprehensible (no comments, method-names in foreign language - i guess polish or sth like that, overall bad code style, etc.).I'd recommend painting to a BufferedImage instead of directly painting to the screen. This way you can easily check the color of single pixels or modify it or paint to the image and keep changes consistent:
int type = BufferedImage.TYPE_4BYTE_ABGR;
BufferedImage image = new BufferedImage(width , height , type);
Graphics g = image.getGraphics();
//draw stuff with g, just like in paintComponent(Graphics)
g.dispose();
//get color of pixel at (px , py)
Color c = new Color(image.getRGB(px , py));
//set color at pixel (px , py) to red
image.setRGB(px , py , Color.red.getRGB());
Ive created a game of Craps which is a dice based game. Ive created my game logic but am trying to implement a GUI. Ive created my Dice and Dice Component for both dice. If i add my Dice to the frame one at a time they both work, but as soon as i try and add both to the frame at the same time and run my Craps game, the frame is empty.
CrapsGame code:
package crapsgame;
import java.awt.FlowLayout;
import javax.swing.*;
public class CrapsGameTester
{
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
JFrame frame = new JFrame("Craps-Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
final int FRAME_WIDTH = 400;
final int FRAME_HEIGHT = 600;
frame.setSize(FRAME_HEIGHT, FRAME_WIDTH);
CrapsGame game = new CrapsGame();
JPanel panel = new JPanel(new FlowLayout());
frame.add(panel);
Dice1Component dice1 = new Dice1Component(6);
Dice2Component dice2 = new Dice2Component(6);
panel.add(dice1);
panel.add(dice2);
String message = game.doFirstRoll();
System.out.println(message);
while(!game.isOver())
{
message = game.rollAgain();
System.out.println(message);
}
if(game.isWon())
System.out.println("You win, big man!");
else
System.out.println("Loser ...");
frame.setVisible(true);
}
}
Dice1 code:
package crapsgame;
import java.awt.*;
public class Dice1
{
int sides;
int xCoord = 150;
int yCoord = 130;
public Dice1(int s)
{
sides = s;
}
/**
*
* #param g2 Graphics2D object used by draw method
*/
public void draw(Graphics2D g2)
{
g2.setColor(Color.BLACK);
g2.fillRect(xCoord, yCoord, 100, 100);
g2.setColor(Color.WHITE);
switch (sides)
{
case 1:
g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
break;
case 2:
g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
break;
case 3:
g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
break;
case 4:
g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 15, yCoord + 65, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
break;
case 5:
g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 15, yCoord + 65, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 15, 20, 20);
g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
break;
case 6:
g2.fillOval(xCoord + 20, yCoord + 20, 20, 20);
g2.fillOval(xCoord + 20, yCoord + 45, 20, 20);
g2.fillOval(xCoord + 20, yCoord + 70, 20, 20);
g2.fillOval(xCoord + 60, yCoord + 20, 20, 20);
g2.fillOval(xCoord + 60, yCoord + 45, 20, 20);
g2.fillOval(xCoord + 60, yCoord + 70, 20, 20);
break;
}
}
}
Dice1Component code:
package crapsgame;
import java.awt.*;
import javax.swing.*;
public class Dice1Component extends JComponent
{
private int sides;
public Dice1Component(int s)
{
sides = s;
}
public void setSide(int s)
{
sides = s;
}
#Override
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Dice1 dice1 = new Dice1(sides);
dice1.draw(g2);
}
}
I read that to add more than one component to a frame you must use a JPanel but this doesn't seem to work for me either.
There are a couple of issues (in addition to those mentioned in comments), but these should make the code work:
You should override the preferred size in Dice1Component so that the layout manager can
reserve it the correct space
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
remove xCoord and yCoord from Dice1. The coordinates used are relative to the component, so a large offset will try to draw outside the component area
Take a look at the tutorial how you should create and access components only in the event dispatch thread.
I need to have the for loop at the bottom do everything in the body every 5 seconds but it's not working for some reason! Sorry if this sounds very dumb, I am very new to java! If you could help, that'd be great! Thanks! :)
package rBP;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Main extends Applet implements MouseListener {
public void init() {
super.init();
addMouseListener(this);
}
public long numClicks = 0; // 16385
public int autoFingerNum = 0;
public int faultyButtonNum = 0;
public int slickButtonNum = 0;
public int coolButtonNum = 0;
public int heatSinkNum = 0;
public int superButtonNum = 0;
public int aFCost = 30;
public int aFValue = 1;
public int fBCost = 75;
public int fBValue = 3;
public int slBCost = 300;
public int slBValue = 10;
public int cBCost = 1000;
public int cBValue = 25;
public int hSCost = 5000;
public int hSValue = 80;
public int suBCost = 10000;
public int suBValue = 200;
#Override
public void paint(Graphics g) {
this.setSize(1010, 360);
g.setColor(Color.cyan);
g.fillRect(0, 0, 1010, 360); // background
g.setColor(Color.black);
g.fillOval(47, 47, 205, 205); // button outline
g.setColor(Color.red);
g.fillOval(50, 50, 200, 200); // button
g.setColor(Color.yellow);
g.fillRect(2, 5, 290, 30); // yellow boxes
g.fillRect(300, 25, 100, 250);
g.fillRect(410, 25, 100, 250);
g.fillRect(520, 25, 100, 250);
g.fillRect(630, 25, 100, 250);
g.fillRect(740, 25, 100, 250);
g.fillRect(850, 25, 100, 250);
g.setColor(Color.black);
g.drawLine(300, 100, 400, 100); // lines on yellow boxes
g.drawLine(410, 100, 510, 100);
g.drawLine(520, 100, 620, 100);
g.drawLine(630, 100, 730, 100);
g.drawLine(740, 100, 840, 100);
g.drawLine(850, 100, 950, 100);
g.drawLine(300, 190, 400, 190);
g.drawLine(410, 190, 510, 190);
g.drawLine(520, 190, 620, 190);
g.drawLine(630, 190, 730, 190);
g.drawLine(740, 190, 840, 190);
g.drawLine(850, 190, 950, 190);
g.fillRect(307, 197, 86, 71); // boxes around "buy" buttons
g.fillRect(417, 197, 86, 71);
g.fillRect(527, 197, 86, 71);
g.fillRect(637, 197, 86, 71);
g.fillRect(747, 197, 86, 71);
g.fillRect(857, 197, 86, 71);
g.setColor(Color.red);
g.fillRect(310, 200, 80, 65); // red "buy" buttons
g.fillRect(420, 200, 80, 65);
g.fillRect(530, 200, 80, 65);
g.fillRect(640, 200, 80, 65);
g.fillRect(750, 200, 80, 65);
g.fillRect(860, 200, 80, 65);
g.setColor(Color.black);
g.setFont(new Font("default", Font.BOLD, 12));
g.drawString("Number of Points: " + numClicks, 5, 25); // num of points
g.setFont(new Font("default", Font.BOLD, 20));
g.drawString("DO", 135, 120);
g.drawString("NOT", 127, 150);
g.drawString("PRESS", 115, 180);
g.setFont(new Font("default", Font.BOLD, 16));
g.drawString("AutoFinger", 310, 50);
g.drawString("FaultyButton", 411, 50);
g.drawString("SlickButton", 524, 50);
g.drawString("CoolButton", 635, 50);
g.drawString("HeatSink", 754, 50);
g.drawString("SuperButton", 851, 50);
g.drawString("+1p/5s", 310, 75);
g.drawString("+3p/5s", 434, 75);
g.drawString("+10p/5s", 540, 75);
g.drawString("+40p/5s", 648, 75);
g.drawString("+100p/5s", 756, 75);
g.drawString("+500p/5s", 866, 75);
g.drawString("Buy: 30P", 315, 240);
g.drawString("Buy: 75P", 425, 240);
g.drawString("Buy: 300P", 530, 240);
g.setFont(new Font("default", Font.BOLD, 15));
g.drawString("Buy: 1000P", 642, 240);
g.drawString("Buy: 5000P", 752, 240);
g.setFont(new Font("default", Font.BOLD, 13));
g.drawString("Buy: 10000P", 862, 240);
g.setFont(new Font("default", Font.BOLD, 12));
g.drawString("aFNumber: " + autoFingerNum, 305, 150);
g.drawString("fBNumber: " + faultyButtonNum, 415, 150);
g.drawString("sBNumber: " + slickButtonNum, 525, 150);
g.drawString("cBNumber: " + coolButtonNum, 635, 150);
g.drawString("hSNumber: " + heatSinkNum, 745, 150);
g.drawString("sBNumber: " + superButtonNum, 855, 150);
}
#Override
public void mouseClicked(MouseEvent e) {
if ((e.getX() > 50 && e.getX() < 250)
&& (e.getY() > 50 && e.getY() < 250)) {
numClicks++;
repaint();
}
if ((e.getX() > 310 && e.getX() < 390)
&& (e.getY() > 200 && e.getY() < 265)
&& numClicks > (aFCost - 1)) {
autoFingerNum++;
numClicks -= aFCost;
repaint();
}
if ((e.getX() > 420 && e.getX() < 500)
&& (e.getY() > 200 && e.getY() < 265)
&& numClicks > (fBCost - 1)) {
faultyButtonNum++;
numClicks -= fBCost;
repaint();
}
if ((e.getX() > 530 && e.getX() < 610)
&& (e.getY() > 200 && e.getY() < 265)
&& numClicks > (slBCost - 1)) {
slickButtonNum++;
numClicks -= slBCost;
repaint();
}
if ((e.getX() > 640 && e.getX() < 720)
&& (e.getY() > 200 && e.getY() < 265)
&& numClicks > (cBCost - 1)) {
coolButtonNum++;
numClicks -= cBCost;
repaint();
}
if ((e.getX() > 750 && e.getX() < 830)
&& (e.getY() > 200 && e.getY() < 265)
&& numClicks > (hSCost - 1)) {
heatSinkNum++;
numClicks -= hSCost;
repaint();
}
if ((e.getX() > 860 && e.getX() < 940)
&& (e.getY() > 200 && e.getY() < 265)
&& numClicks > (suBCost - 1)) {
superButtonNum++;
numClicks -= suBCost;
repaint();
}
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
public void output() {
for (int i = 0; i >= 50; i++) { //<- I just set it at 50 for testing purposes
i = 0;
numClicks += autoFingerNum * aFValue;
numClicks += faultyButtonNum * fBValue;
numClicks += slickButtonNum * slBValue;
numClicks += coolButtonNum * cBValue;
numClicks += heatSinkNum * hSValue;
numClicks += superButtonNum * suBValue;
}
}
}
Timer + TimerTask might suit your needs. Here is a code sample:
TimerTask task = new MyTask();
Timer timer = new Timer();
timer.scheduleAtFixedRate(task, startTime, interval);
Where MyTask is:
public class MyTask extends TimerTask {
#Override
public void run() {
// do work here
}
}
Thread.sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system. The sleep method can also be used for pacing, as shown below
boolean continueExec = true; //you can use this to exit the loop
public void output() {
while(this.continueExec ){
Thread.sleep(5000); //wait 5 seconds
numClicks += autoFingerNum * aFValue;
numClicks += faultyButtonNum * fBValue;
numClicks += slickButtonNum * slBValue;
numClicks += coolButtonNum * cBValue;
numClicks += heatSinkNum * hSValue;
numClicks += superButtonNum * suBValue;
}
}
Use javax.swing.Timer. You can schedule it to run your event handling code at any given time interval, or after any scheduled time, and this code will run in a Swing thread from where you can safely manipulate buttons, labels, etc.
If you just want drawing to change periodically, the timer could set some variable that have effect on your painting and then call repaint().
It is more complex to do with your own separate thread as it cannot touch any GUI components, unless SwingUtils.invokeLater or something similar is used.
Use a Thread to execute the statements of output()
Thread timer = new Thread(){
public void run(){
try{
while(true ){
numClicks += autoFingerNum * aFValue;
numClicks += faultyButtonNum * fBValue;
numClicks += slickButtonNum * slBValue;
numClicks += coolButtonNum * cBValue;
numClicks += heatSinkNum * hSValue;
numClicks += superButtonNum * suBValue;
repaint();
sleep(5000);
}
}catch(InterruptedException e){
e.printStackTrace();
}finally{
}
}
};
timer.start();