I am trying to build a java program that allows a user to play checkers. Right now I'm having trouble creating my 24 pieces & getting them to move from place to place. I want to be able to drag them from an orange square to another orange square. If the square isn't orange, I want it the program to reject the move. How can I go about doing this? Any & all help is appreciated!
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class Board extends JPanel{
public void paint(Graphics g){
g.setColor(new Color(234, 106,32));
g.fillRect(0, 0, 400, 400);
for(int i = 0; i <= 350; i+=100){
for(int j = 0; j <= 350; j+=100){
g.clearRect(i, j, 50, 50);
}
}
for(int i = 50; i <= 400; i+=100){
for(int j = 50; j <= 400; j+=100){
g.clearRect(i, j, 50, 50);
}
}
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(400,420);
frame.getContentPane().add(new Board());
frame.setTitle("Java Chip Checkers");
frame.setLocationRelativeTo(null);
/* frame.setBackground(new Color(234, 106, 32)); */
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
If it is not a training project to study JPanel, i recommend using a framework specifically designed for games. (libgdx eg) Otherwise, you have to write a lot of unnecessary interactions.
You need a binary matrix and translation of the mouse coordinates in the matrix. Then you will be easy to calculate the actions of the user.
But your question is not very suitable for stackoverflow.
Related
The following is an example using drawLine() to draw horizontal and vertical dashed lines on a JPanel.
As the JPanel is resized, so are the dashed lines.
Here is the main object.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ExampleForPosting implements Runnable{
public static void main(String args[]) {
SwingUtilities.invokeLater(
new ExampleForPosting ());
}
private LineDrawer panel;
#Override
public void run() {
JFrame frame = new JFrame("Line Sample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new LineDrawer();
panel.setPreferredSize(new Dimension(300, 200));
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public void setJPanelBackground(Color color) {
panel.setBackground(color);
panel.repaint();
}
}
This is the JPanel which does the drawing.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import javax.swing.JPanel;
public class LineDrawer extends JPanel
{
private Stroke dashedLineStroke = getDashedLineStroke(1);
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
g2.setStroke(dashedLineStroke);
for (int i = 1; i < (this.getWidth()-10) ; i++)
g.drawLine(10, (i*10), this.getWidth()-10, (i*10));
for (int i = 1; i < (this.getHeight()-10) ; i++)
g.drawLine((i*10), 10, (i*10), this.getHeight()-10);
}
public Stroke getDashedLineStroke(int width)
{
float[] dashPattern = {2, 2};
return new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 2, dashPattern, 0);
}
}
For the most part. It works.
As the panel increases in size so do the dashed lines.
The issue is depending upon where the panel is stopped when resizing, it can be incomplete as shown here by the highlights or there isn't an equal amount of space from the edge.
The objective would be to make this dynamic so that the dashed lines always complete and same spacing on all sides.
If need be the spacing could be modified, but it should be dynamic even if the properties of the dashed line are changed.
I suspect there is some other attribute required for the calculation but unable to find one that works.
for (int i = 1; i < (this.getWidth()-10) ; i++)
First of all your looping condition is wrong. If your width is 300, then you would loop 289 times. You need to divide the width by 10 to get the number of lines to draw.
so that the dashed lines always complete and same spacing on all sides.
Well that is not possible. If the width is 105 and each border is 10, then the width of the last line segment can only be 5.
The easiest way to solve the problem is to set the clip bounds of your painting. Then any drawing outside of the clipped area will be ignored.
This will allow a partial line to be drawn as the frame is resized:
Rectangle clip = new Rectangle(10, 10, getWidth() - 19, getHeight() - 19);
g.setClip( clip );
int linesX = getHeight() / 10;
int linesY = getWidth() / 10;
for (int i = 1; i < linesX ; i++)
g.drawLine(10, (i*10), this.getWidth(), (i*10));
for (int i = 1; i < linesY ; i++)
g.drawLine((i*10), 10, (i*10), this.getHeight()-10);
This question already has an answer here:
Circle not showing up in JPanel
(1 answer)
Closed 2 years ago.
For someone who is wanting to learn more about awt/swing and who has not worked a lot with awt/swing I'm not sure if I am doing this correctly or not. What I am trying to do is override paintComponent() with a method that creates 6 circles that are supposed to be added to the inner panel in certain spots (the x + 50 and y + 50 are just for testing purposes). I've looked through online resources including this site and the circles still don't appear to be showing up. I'm sure I am doing something wrong but I am not sure what. Tips and/or informative links would be greatly appreciated
This is the class I have with the goal of creating and adding the circles to the panel:
public class TimeUnit extends JPanel {
private static final long serialVersionUID = 1L;
private int x = -50;
private int y = -50;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
ArrayList<Graphics> list = new ArrayList<Graphics>(6);
for (int i = 0; i < 6; i++) {
list.add(g.create());
}
for (Graphics r : list) {
r.drawOval(x + 50, y + 50, 50, 50);
}
}
And this is where it is incorporated into my main program:
JPanel inner = new JPanel();
inner.setLayout(null);
inner.setSize(325, 570);
inner.setBackground(null);
inner.setLocation(500, 350);
inner.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.BLACK));
inner.setVisible(true);
inner.repaint();
//----Containers to Panel/Panel to Frame---------
Panel.add(inner);
Panel.add(labelOne);
Panel.add(labelTwo);
Panel.add(labelFour);
Panel.add(labelEight);
Panel.add(timeLabel);
frame.add(Panel, BorderLayout.CENTER);
You should use the passed in Graphics g to draw the ovals, not create new Graphics objects:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < 6; i++) {
g.drawOval(x + 50*i, y + 50*i, 50, 50);
}
}
I am trying to draw 8 red squares in a specific pattern in java.
And I am expecting an output like this:
Alteration.java
And this is what I have tried so far:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Alteration {
private int xGrid;
private int yGrid;
public static void main(String[] args) {
Alteration a = new Alteration();
a.display();
}
public void display() {
JFrame frame = new JFrame("Alteration");
Background bg = new Background();
frame.setSize(400, 200);
frame.getContentPane().add(bg);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
for (int i = 0; i < 2; i++) {
for (int s = 0; s < 4; s++) {
bg.repaint();
xGrid += 50;
yGrid += 50;
}
yGrid = 0;
}
}
class Background extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.RED);
g.fillRect(xGrid, yGrid, 50, 50);
}
}
}
However, when I compile the code and run it, I only see one red square at the position of (400, 0)
That was not what I expected to output and I dont know why. I've done plenty of research and I still cannot find the correct answer to my problem, can anyone help?
EDIT: I added a code in the paintComponent method.
public void paintComponent(Graphics g) {
g.setColor(Color.RED);
g.fillRect(xGrid, yGrid, 50, 50);
System.out.println(xGrid+" "+yGrid);
}
Output (in the command prompt): 400 0
The double for loop runs 8 loops in total.
so bg.repaint() is called 8 times.
However the command prompt prints only 1 line.
I'm confused by this, why does the command prompt only print 1 line despite the fact that the paintComponent method was called 8 times?
I have a graphic which consists of a horizontal line of circles of different sizes at regular intervals. Here is the picture:
I am trying to recreate this graphic using recursion as opposed to the if statements used in my code but after trying, am unsure about how to do this. Would love some help, here is my code:
package weekFour;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.*;
#SuppressWarnings("serial")
public class Circle extends JPanel {
private int circX = 10;
private static int windowW = 1700;
private static int windowH = 1000;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //smoothes out edges
Color c5 = new Color(50, 50, 50);
Color c4 = new Color(100, 100, 100);
Color c3 = new Color(150, 150, 150);
Color c2 = new Color(200, 200, 200);
Color c1= new Color(250, 250, 250);
for (int i = 0; i < 1; i++) {
g2.setColor(c1);
g2.fillOval(522 + 75*i, 138, 666, 666);
g2.setColor(c1);
g2.drawOval(522 + 75*i, 138, 666, 666);
}
for (int i = 0; i < 3; i++) {
g2.setColor(c2);
g2.fillOval(244 + 522*i, 365, 180, 180);
g2.setColor(c2);
g2.drawOval(244 + 522*i, 365, 180, 180);
}
for (int i = 0; i < 10; i++) {
g2.setColor(c3);
g2.fillOval(130 + 174*i, 428, 60, 60);
g2.setColor(c3);
g2.drawOval(130 + 174*i, 428, 60, 60);
}
for (int i = 0; i < 25; i++) {
g2.setColor(c4);
g2.fillOval(60 + 87*i, 444, 25, 25);
g2.setColor(c4);
g2.drawOval(60 + 87*i, 444, 25, 25);
}
for (int i = 0; i < 120; i++) {
g2.setColor(c5);
g2.fillOval(circX + 29*i, 450, 12, 12);
g2.setColor(c5);
g2.drawOval(circX + 29*i, 450, 12, 12);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("MyTaskToo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Circle());
frame.setSize(windowW, windowH);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Thanks for your time.
This is how I went about this problem, although we had to do it with green circles as opposed to grey circles but it's not that different.
N.B: Sorry for the appealing comments for sometimes trivial things but we get marks for commenting and it is better to be safe than sorry. Maybe they change you some insight into the thought process.
Here is the main method that starts the programme and sets out the window information.
public class Q2Main {
public static void main(String[] args) {
// here we are just setting out the window end putting the circles drawin in Q2Circles into this window.
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(1000, 500);
window.getContentPane().add(new Q2Circles(5));
window.setVisible(true);
}}
This is where the magic happens:
public class Q2Circles extends JPanel {
// this allows the user to specify how many loops of recursion they want the programme to complete before finishing
int recursionsToDo;
public Q2Circles(int recursionMax){
super();
recursionsToDo = recursionMax;
}
/*
this method is automatically called when we run the constructor as it inherits from the JFram superclass. here
we are setting out the size of the circle by getting the size of the window to make it proportional to the rest
of the screen and circles.
we then pass these values into the drawCircle method to draw the circle
*/
public void paintComponent(Graphics g){
Rectangle rectangle = this.getBounds();
int diameter = rectangle.width/3;
int centerPoint = rectangle.width/2;
drawCircle(g, 1, centerPoint, diameter);
}
/*
This method is where the magic of the programme really takes place. first of all we make sure we haven't completed
the necessary recursions. we the set the color by dividing it by the amount of times we have recursed, this will
have the affect of getting darker the more times the method recurses. we then sset the color. finaly we fill the
oval (draw the circle). because we want to move depending on the times it has recursed and size of the previous
we do it based on the size of the elements from the previous call to this method. Getting the right numbers
though was just alot of trial and error.
we then increment the recursion counter so that we know how many times we have recursed and that can then be
used at different points where needed. e.g for setting the color.
each recursive call used the dimension of the other recursive calls to make the whole picture. Although the
first recursive call creates the circles on the right of the screen. the second call draws the circle on the
left of the screen and the last one does the circles in the middle, they all use eachothers values to make it
complete. without one recursive step, more is missing than just what is created by that recursive call on its own.
in all honesty though, there is alot of duplication, like the large middlecircle.
*/
public void drawCircle(Graphics g, int amountOfRecursions, int center, int diameter){
if (amountOfRecursions <= recursionsToDo){
int recursionsCount = amountOfRecursions;
int greenColor = Math.round(225 / (amountOfRecursions));
g.setColor(new Color(0, greenColor, 0));
g.fillOval(center - (diameter/2), 200 - (diameter/2), diameter, diameter);
recursionsCount++;
drawCircle(g, recursionsCount, Math.round(center + diameter), diameter/3);
drawCircle(g, recursionsCount, Math.round(center - diameter), diameter/3);
drawCircle(g, recursionsCount, Math.round(center), diameter/3);
}
}}
I'm currently working on a program where certain numerical variables, which evolve over time, have their value displayed on each iteration. That works well enough, but now I want to plot a graph that shows their evolution over time.
So, I looked into an example of code for plotting graphs in Swing. My final code looks like this:
public class Populus3 extends JPanel
{
public static void main(String[] args) throws IOException {
final Populus3 pop = new Populus3();
JFrame f = new JFrame(); //where I want to plot the graph
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new GraphingData());
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
frame = new JFrame("Animation Frame"); //where I'm running animation for another element of the program
frame.add(pop, BorderLayout.CENTER);
frame.setSize(graphSize, graphSize);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//insert all sort of things
}
public void paint(Graphics g)
{
super.paint(g);
paintCell(g, 1);
Toolkit.getDefaultToolkit().sync(); // necessary for linux users to draw and animate image correctly
g.dispose();
}
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i = 0; i < particleType.length; i++)
paintCell(g, i); //a method that draws a small circle for the animation panel
}
public static class GraphingData extends JPanel {
int[] data = {
21, 14, 18, 03, 86, 88, 74, 87, 54, 77,
61, 55, 48, 60, 49, 36, 38, 27, 20, 18
};
final int PAD = 20;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = getWidth();
int h = getHeight();
// Draw ordinate.
g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));
// Draw abcissa.
g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
double xInc = (double)(w - 2*PAD)/(data.length-1);
double scale = (double)(h - 2*PAD)/getMax();
// Mark data points.
g2.setPaint(Color.red);
for(int i = 0; i < data.length; i++) {
double x = PAD + i*xInc;
double y = h - PAD - scale*data[i];
g2.fill(new Ellipse2D.Double(x-2, y-2, 4, 4));
}
}
private int getMax() {
int max = -Integer.MAX_VALUE;
for(int i = 0; i < data.length; i++) {
if(data[i] > max)
max = data[i];
}
return max;
}
}
}
Now, the animation panel works just fine. The graph panel, on the other hand...when I run the program, it displays a bunch of red dots, without lines to connect them. What am I doing wrong?
In addition to #Hovercraft's helpful suggestions, also consider these other approaches:
Accumulate the points in a GeneralPath that may be rendered as required, for example.
Connect the points using repeated calls to drawLine() using a suitable coordinate system, outlined here.
Look at JFreeChart.
Your code confuses me:
You override both paint and paintComponent for your Populus3 JPanel -- why? You should only override paintComponent unless you absolutely have to have your drawing affect a component's children and borders.
You dispose of the Graphics object passed into paint -- a very dangerous thing to do. You should never dispose of a Graphics object given to you by the JVM, only Graphics objects that you yourself create.
You repeatedly call a method not defined here for us, paintCell(...).
I've never heard of the need for Toolkit.getDefaultToolkit().sync(); for Swing applications. Do you have a reference for this need?
You mention "animation" but I see no animation code.
In your GraphingData class's paintComponent method you fill ellipses in your for loop, but you don't connect them with lines ever, so it shouldn't be surprising that you're only seeing dots in your graph and no lines.
Consider isolating your problem more and posting an sscce, a minimal test program that we can compile, run, modify and correct and that shows us your problem, but has no extra code not related to the problem or required for demonstration.
The following code demonstrates a real-time Java chart using XChart where the line is updated as the data evolves over time. Creating real-time charts is as simple as calling updateXYSeries for one or more series objects through the XYChart instance and triggering a redraw of the JPanel containing the chart. This works for all chart types including XYChart, CategoryChart, BubbleChart and PieChart, for which example source code can be found here: https://github.com/timmolter/XChart/tree/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/realtime. Examples demonstrate using the SwingWrapper with repaintChart() method as well as XChartPanel with revalidate() and repaint(). Disclaimer, I'm the main developer of the XChart library.
public class SimpleRealTime {
public static void main(String[] args) throws Exception {
double phase = 0;
double[][] initdata = getSineData(phase);
// Create Chart
final XYChart chart = QuickChart.getChart("Simple XChart Real-time Demo", "Radians", "Sine", "sine", initdata[0], initdata[1]);
// Show it
final SwingWrapper<XYChart> sw = new SwingWrapper<XYChart>(chart);
sw.displayChart();
while (true) {
phase += 2 * Math.PI * 2 / 20.0;
Thread.sleep(100);
final double[][] data = getSineData(phase);
chart.updateXYSeries("sine", data[0], data[1], null);
sw.repaintChart();
}
}
private static double[][] getSineData(double phase) {
double[] xData = new double[100];
double[] yData = new double[100];
for (int i = 0; i < xData.length; i++) {
double radians = phase + (2 * Math.PI / xData.length * i);
xData[i] = radians;
yData[i] = Math.sin(radians);
}
return new double[][] { xData, yData };
}
}
This results in the following Java Swing real-time chart app: