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?
Related
So I am trying to update a JPanel using a byte array with a specified byte/color
This is a very simple version.
When I start the program it's white for half a second, then becomes the right color, and then after 1 second it's going back to being white, I tried to print out the current color, and sometimes it's changing to '0'.
What am I doing wrong?
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static Random ran = new Random();
public static byte[] buffer;
public static int num = 0;
public static JFrame frame = new JFrame();
public static JPanel panel = new JPanel() {
private static final long serialVersionUID = 1L;
#Override
public void paint(Graphics g) {
num = 0;
byte[] current_buffer = buffer.clone();
for (int y = 0; y < panel.getHeight(); y++) {
for (int x = 0; x < panel.getWidth(); x++) {
g.setColor(new Color(current_buffer[num], current_buffer[num], current_buffer[num]));
g.fillRect(x, y, 1, 1);
num++;
}
}
}
};
public static void main(String[] args) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1200, 800);
frame.setLocationRelativeTo(null);
frame.setContentPane(panel);
frame.setResizable(false);
frame.setVisible(true);
engine.run();
}
public static boolean running = true;
public static Thread engine = new Thread() {
#Override
public void run() {
buffer = new byte[panel.getWidth() * panel.getHeight()];
for (int i = 0; i < buffer.length; i++) {
buffer[i] = (byte) 34;
}
while (running) {
panel.repaint(10L);
}
}
};
}
Not really understanding your logic:
for (int i = 0; i < buffer.length; i++) {
buffer[i] = (byte) 34;
}
You assign the same value to the buffer.
Then you create a Color object using the same value.
g.setColor(new Color(current_buffer[num], current_buffer[num], current_buffer[num]));
So every pixel will be the same Color.
And since the buffer is always built with the same values, the color won't change.
Also, why would you use
byte[] current_buffer = buffer.clone();
You are just using the values in the buffer, not updating the values in the buffer so I see no reason for the clone.
Don't use a Thread with a while loop. For animation you should be using a Swing Timer. When the Timer fires you update the values in the buffer and then invoke repaint().
When I start the program it's white for half a second, then becomes the right color, and then after 1 second it's going back to being white,
I don't see that behaviour.
it blinks a light color
it stays painted at a darker color
The above makes sense because:
Your paintCompnent() method does not invoke super.paintComponent(...) to make sure the background is cleared
The array is not initialized to any values when it is created so the default value will be 0.
After the Thread takes over the array will alway contain the same value so the same color will be painted.
What do you expect it to do?
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);
}
}
package getcm;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class test {
public static void main( String[] args ) {
tpanel panel = new tpanel();
JFrame app = new JFrame();
app.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
app.add(panel);
app.setSize(250, 250);
app.setVisible(true);
}
}
class tpanel extends JPanel {
int st = 0;
public void paintComponent(Graphics g) {
for (int h = 0; h < 2; h++) {
System.out.println(st);
st += 1;
}
}
}
I think this result should be 0, 1 but in Eclipse, the data that printed is 0, 1 ,2 ,3.
I have a reason that variable st can not produce inside the fuction paintComponent, and I have to get result 0, 1. (getting paintComponent only one time)
Please help me to get result 0, 1.
I have no idea about why this code print 0, 1 ,2 ,3 not 0, 1.
It is happening only on frame resize.
When resizing the frame, your paintComponent is called again with the old value of variable "st".
It is because, for the class "tpanel", "st" is a global variable and until your JPanel remains open, control will not exit from the "tpanel" class.
So simply it is only printing the value of global variable which is called between different function calls of paintComponent.
Hope this will help. :-)
Because
paintComponent
get called multiple times, everytime the panel get painted
it'll print a couple of number 0,1 for the frist paint and 2,3 for the second
If you edit the code like this it will print
class tpanel extends JPanel {
int st = 0;
public void paintComponent(Graphics g) {
for (int h = 0; h < 2; h++) {
System.out.println(st);
st += 1;
}
Systen.out.println("paintComponent completed");
}
}
Output:
0
1
paintComponent completed
2
3
paintComponent completed
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 wrote a program to play Maxwell's Demon. It should have a window with 2 sides and a few
dots running around bouncing off the walls. There's a wall in the middle. When you click a
button, a gap opens up in the wall (until you unclick). This should allow a person to try
to get more balls on one side than the other. You can display the count on each side.
This is the main class, I have two other classes one is Dot ( where I make my dots move, and
tell how fast), and the other one is BLueDot(where i create the blue dots).
So what I want is that to display the counts of the balls on each sides? Or How many we
got (balls) on each side of the walls?
Main Program
package dotChaser;
//DotChaser.java
//This program does some simple animation where a dot move around
//the blue dots.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DotChaser extends JFrame implements ActionListener, KeyListener
{
javax.swing.Timer time; // generates ticks that drive the animation
protected double deltaT = 0.020; // how much time for each tick
BlueDot[] blues; // holds the blue dots
int blueCounter = 0; // number of blue dots
//Label howMany = new Label();
JTextField tf;// The text field for the key listener
boolean open; // open= true part. pass through, open = false part. dont pass through
public static void main(String[] args)
{
DotChaser d = new DotChaser();
}
// constructor
public DotChaser()
{
Dot.theDotChaser = this;
//time managment
time = new javax.swing.Timer((int)(1000*deltaT), this);
time.start();
blues= new BlueDot[200] ;
tf = new JTextField("---------------");
add(tf);
tf.addKeyListener(this);
for(int i = 0; i<20; i++)
{blues[blueCounter++] = new BlueDot();
//count++;
//howMany.setText(ballReport());
setLayout( new FlowLayout());
setTitle("Dot Chaser!");
setSize(new Dimension(600,600));
setVisible(true);}
}
// the work its doing
public void actionPerformed(ActionEvent e)
{
if (e.getSource()==time){doTime();}
repaint();
}
// key listener mouse motion
public void keyTyped( KeyEvent k ) { }
public void keyPressed( KeyEvent k )
{
System.out.println("you pressed key="+k.getKeyChar());
open=true;
}
public void keyReleased( KeyEvent k )
{
System.out.println("you released key="+k.getKeyChar());
open=false;
}
// the clock ticked, so tell all the dots to move a little
public void doTime()
{
for (int i= 0; i<blueCounter; i++)
{
blues[i].move(deltaT);
}
}
// make another blue dot (and add it to the blues array)
public void doMoreDots()
{blues[blueCounter++] = new BlueDot();}
// paint all the dots
public void paint(Graphics g)
{
super.paint(g);
for (int i= 0; i<blueCounter; i++)
{
blues[i].drawMe(g);
}
{
// draw the wall
g.setColor( Color.pink );
g.fillRect( 250, 40, 90, 200 );
g.fillRect( 250, 400, 90, 300 );
}
// close wall when false
if ( open == false)
{
g.fillRect(250, 200, 90, 200);
g.fillRect(250, 400, 90, 300);
}
}
}
As I am getting you need to count the total number of dots each side.
The total number of dots you can get from the Array where you are keeping.Add a counter in the below method which will keep the number of dots total.
static int count=0;
public void doMoreDots()
{
blues[blueCounter++] = new BlueDot();
count++;
}
Now ,you need to find out the count for each side,here I will suggest that use another 2 separate counter in that class where you can track moving dots.
Hope it will help you.