I'm working on java gui with socket programming.I want to create jpanel on the jframe with the parameters I send from the server and create random shapes in jpanel.
I used this resource to draw shapes:
https://github.com/AugustBrenner/Random-Draw-Shape/blob/master/DrawPanel.java
my code in jframe is;
public void starteGame(String received) {
gamers.setText(received);
String[] mParsed = received.split(" ");
boolean filled = true;
int width = Integer.parseInt(mParsed[2]);
int height = Integer.parseInt(mParsed[1]);
int x1 = Integer.parseInt(mParsed[3]);
int y1 = Integer.parseInt(mParsed[4]);
int x2 = Integer.parseInt(mParsed[5]);
int y2 = Integer.parseInt(mParsed[6]);
int randomShape = Integer.parseInt(mParsed[7]);
Color firstColor = new Color(Integer.parseInt(mParsed[8]), true);
Color secondColor = new Color(Integer.parseInt(mParsed[9]), true);
boolean cyclic = Boolean.parseBoolean(mParsed[10]);
switch (randomShape) {
case 1:
// add the line to the list of lines to be displayed
shape = new MyPolygon(x1, y1, x2, y2, firstColor, filled);
break;
case 2:
shape = new MyRectangle(x1, y1, x2, y2, firstColor, filled);
break;
case 3:
shape = new MyOval(x1, y1, x2, y2, firstColor, filled);
break;
}
jPanel2=new PanelDraw(width,height,x1,y1,x2,y2,firstColor,secondColor,
randomShape,shape,cyclic);
}
And my PanelDraw is;
public class PanelDraw extends JPanel implements MouseMotionListener {
private Random randomNumbers;
private MyShape shape;
int x1;
int y1;
int x2;
int y2;
Color firstColor;
Color secondColor;
int width;
int height;
// generate random shape
int randomShape;
boolean cyclic ;
// constructor, creates a panel with random shapes
public PanelDraw(int width, int height, int x1, int y1, int x2, int y2,
Color first, Color second, int randomS,MyShape shape ,boolean cyclic) {
this.width = width;
this.height = height;
// generate random coordinates
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
// generate a random color
this.firstColor = first;
this.secondColor = second;
// generate random shape
randomShape = randomS;
this.shape=shape;
this.cyclic=cyclic;
//setBackground( Color.BLACK );
} // end DrawPanel constructor
public void mouseMoved(MouseEvent event) {
}// end mouseMoved
public void mouseDragged(MouseEvent event) {
} // end method
// for each shape array, draw the individual shapes
#Override
public void paintComponent(Graphics g) {
//initialize filled boolean to true;
boolean filled = true;
// initialize random cyclic boolean
// draw the shape
Graphics2D g2d = (Graphics2D) g; // cast g to Graphics2D
g2d.setPaint(new GradientPaint(x1, y1, firstColor, x2, y2,
secondColor, cyclic));
shape.draw(g2d);
g2d.dispose();
// shapeCount++;
try {
Thread.sleep(700);
} catch (Exception e) {
}
repaint();
} // end method paintComponent
} // end class DrawPanel
the panel does not appear when my function is running and random shapes do not appear.
Can you help me?
Problem #1...
try {
Thread.sleep(700);
} catch (Exception e) {
}
inside your paintComponent method :/
Swing is single threaded (and not thread safe), doing this in your paintComponent will prevent EVERYTHING from been painted until AFTER sleep returns, it will also stop all user interaction from occurring.
See Concurrency in Swing for more details
Problem #1.1...
Graphics2D g2d = (Graphics2D) g; // cast g to Graphics2D
//...
g2d.dispose();
The Graphics context passed to you is created by the system and is shared between all components been painted during the paint pass. Disposing of it like this can cause other components from been painted
Problem #1.2...
repaint();
inside your paintComponent method.
Don't change the state, directly or indirectly, of any component from within a paint pass. Painting should paint state and nothing else. Doing this will cause the repaint manager to run wild and consume all the CPU cycles
Problem #2....
jPanel2=new PanelDraw(width,height,x1,y1,x2,y2,firstColor,secondColor, randomShape,shape,cyclic);
Yes, but you're not adding the component to anything, so how is it suppose to be painted?
Thread.sleep(700);
Don't ever use a Thread.sleep() in a painting method.
This will cause the Event Dispatch Thread to sleep which means the GUI can't repaint itself or respond to events.
Also:
Never invoke reapint() in a painting method. If you need animation use a Swing Timer.
The first statement in the paintCoponent() method should be super.paintComponent(g) to make sure the background of the panel is cleared before you do your custom painting.
Related
I have an arraylist of images, I am trying to have each image, slide through the screen repeatedly..
public class GraphicsT extends JPanel implements ActionListener {
Timer timer = new Timer(1, this);
Image image;
Image image2;
int x1;
int x2;
int y1;
int y2;
int num;
List<String> imageList1 = new ArrayList<String>();
GraphicsT() {
imageList1.add("image/java.jpeg");
imageList1.add("image/slide.jpg");
imageList1.add("image/giphy.gif");
x1 = 100;
y1 = 100;
x2 = 200;
y2 = 200;
num = 0;
}
public void paint(Graphics g) {
ImageIcon i2 = new ImageIcon("image/street.jpg");
image2 = i2.getImage();
g.drawImage(image2, 0, 0, null);
for (int i = 1; i < imageList1.size(); i++) {
ImageIcon im = new ImageIcon(imageList1.get(i));
image = im.getImage();
g.drawImage(image, x1, y1, x2, y2, 100, 120, 120, 240, null);
System.out.println(imageList1.get(i));
}
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
num++;
if (num % 100 == 0) {
x1 = x1 + 10;
x2 = x2 + 10;
}
if (x2 >= 570) {
// end reached
x1 = 0;
x2 = 100;
}
repaint();
}
}
public class GraphicsApp extends JFrame {
GraphicsT gt = new GraphicsT();
public GraphicsApp() {
this.setTitle("Multiple Slide");
this.setSize(450, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.add(gt);
}
public static void main(String[] args) {
new GraphicsApp();
}
}
my current code can only pick one image, but i want a situation whereby after the first images goes out of the screen, the second image can follow, then the third, and so on...
Please help will be much appreciated.
Several issues:
you should be overriding paintComponent() not paint() and you invoke super.paintComponent(...) to make sure the background is painted first.
a painting method is for painting only. You should NOT be doing I/O to read the images. The images should be read in the constructor of your class
You should NOT start the Timer in the painting method. The Timer is started in the constructor.
Your basic painting code is wrong. You should have a couple of instance variables, a) the "currentImage", b) "imageNumber". Then in the painting method you simply paint the currentImage at the x/y location.
In the ActionListener, when the image is off the screen you increment the "imageNumber" and copy the image from the ArrayList to the "currentImage". Then you reset the x/y location so the image is painted starting from the right.
When the "imageNumber" reaches the end of the ArrayList you reset it back to 0.
I am new in Java. I want to make simple agario game for my project. But I have a problem. I want to make random stopping circles on Panel but my circles don't stop and changing.
The Problem is I think Timer.
class TestPanel extends JPanel implements ActionListener{
TestPanel(){
Timer t = new Timer(50,this);
t.start();
}
Random rnd = new Random();
int r = rnd.nextInt(256);
int b = rnd.nextInt(256);
int gr = rnd.nextInt(256);
Color randomColor = new Color(r,b,gr);
Ellipse2D.Double ball = new Ellipse2D.Double(0, 0, 40, 40);
double v = 10;
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 =(Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.fill(ball);
int NumOfCircles = 70;
int diameter;
int x, y;
Graphics2D g3 =(Graphics2D)g;
for(int count = 0; count < NumOfCircles; count++){
diameter = rnd.nextInt(10);
x = rnd.nextInt(600);
y = rnd.nextInt(620);
g3.setColor(randomColor);
g3.fillOval(x, y, diameter, diameter);
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
Point p = getMousePosition();
if(p==null) return;
double dx = p.x - ball.x - 20;
double dy = p.y - ball.y - 20;
if(dx*dx+dy*dy >12){
double a=Math.atan2(dy, dx);
ball.x += v * Math.cos(a);
ball.y += v * Math.sin(a);}
repaint();
}
}
The problem is in your painting code. You can't control when Swing invokes the painting logic. So the painting code should only paint the object based on the properties of the panel and should not modify the properties.
This means:
Don't generate random values is a painting method.
In the constructor of your class you generate the Circles and assign a default size/location to each Circle. This information is then stored in in an ArrayList. Then in the paintComponent() method you simply iterate through the List and paint each circle.
In the ActionListener of the Timer you then itereate through the ArrayList and update the location of each Circle. Then you invoke repaint() on the panel so all the Circles get repainted.
For example check out: How to move two circles together in a JFrame from two different classes
nothing is showing up at all..
I have tried moving Random rand = new Random() to outside of the loop, but it still doesnt work at all.
Nor does the frame exit on close.
public class myMain {
public static void main(String args[]) {
Frame frame = new Frame();
}
}
public class Frame extends JFrame {
public Frame(){
super("Fancy Triangle");
setSize(1024, 768);
myPanel panel = new myPanel();
add(panel);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
}
public class myPanel extends JPanel {
int x1 = 512;
int y1 = 109;
int x2 = 146;
int y2 = 654;
int x3 = 876;
int y3 = 654;
int x = 512;
int y = 382;
int dx, dy;
Random rand;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < 50000; i++) {
g.drawLine(x, y, x, y);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
rand = new Random();
int random = 1 + rand.nextInt(3);
if (random == 1) {
dx = x - x1;
dy = y - y1;
} else if (random == 2) {
dx = x - x2;
dy = y - y2;
} else {
dx = x - x3;
dy = y - y3;
}
x = x - (dx / 2);
y = y - (dy / 2);
}
}
}
This:
Thread.sleep(300);
is not doing what you intend it to do. I think that you're trying to draw with a delay, but that's not what this does. Instead you're calling sleep on the Swing event thread puts the whole application to sleep, since the thread cannot do what it needs to do, including drawing the application and interacting with the user. Even worse, you're doing this within a painting method, a method that is required to be extremely fast since often the perceived responsiveness of a Swing application is determined by painting speed.
Instead use a Swing Timer (Swing Timer tutorial) to change the state of fields of the class, and then call repaint. Have your paintComponent use those changed fields to decide what to draw and where. Since a Sierpinski triangle is composed of dots, consider creating an ArrayList<Point>, getting rid of the for loop inside your painting method, and using the Swing Timer to replace this for loop. Within the Timer's ActionListener, place the semi-random points into the ArrayList and call repaint. Then within paintComponent, iterate through the ArrayList, drawing each point that it contains.
Alternatively, you could draw the points onto a BufferedImage in your Swing Timer and then simply have your paintComponent display the BufferedImage via g.drawImage(...) method call. This would likely be more efficient.
JPanel Not Updating as Expected
Every time the image on my application is clicked I want the panel to the (bottom) right of the interface to refresh with the RGB value for that specific locaton.
I know it is getting the values as as you can see in the console it has printed the values and locations of both pixel 1 and 2.
When the mouse is clicked it does this:
image_Display.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
x1 = x2;
y1 = y2;
colour1 = colour2;
x2 = e.getX();
y2 = e.getY();
colour2 = originalpixelValue(x2, y2);
//RGBValue pixelValue = originalpixelValue(x2, y2);
System.out.println(colour2.toString());
String pixel1 = x2 + ", " + y2;
//String pixel2 = previousX + ", " + previousY;
System.out.println("Pixel 1: " + pixel1);
System.out.println("\n");
Toolbar.repaint();
repaint();
}
}
Paint method:
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(3));
Random r = new Random();
g2.setColor(new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256)));
g2.drawOval(x1, y1, 10, 10);
g2.drawOval(x2, y2, 10, 10);
}
Outcome Expected: Everything is working as it should, I am just struggling to print the RGB values to the user interface. I have tried using Repaint() and Revalidate().
Any help would be greatly appreciated
Whatever class your imageDisplay is will have to keep track of all selected points and the colors you want to use for them (perhaps in a Map of some kind). Then in your paintComponent() method you first call super.paintComponent() and then call drawOval() for each of clicked points.
I tried to create implementation DDA line drawing algorithm at Java. I created JFrame form and dda.java classes. There is just one Button action at JFrame for this moment. And I am not sure about implementation DDA at JFrame class. I think, that it might be problem with drawPixel method but I am not sure about implementation at JFrame at all. I appreciate your comments.
this is draw line method at dda.java
void drawLineDDA(Graphics2D g) {
dx=(double)(x2-x1);
dy=(double)(y2-y1);
double m=Math.abs(dy/dx);
double absx=Math.abs(dx);
double absy=Math.abs(dy);
double px = absx/p;
double py = absy/p;
int p=0;
float slope = 1;
if(y1==y2){
if(x1==x2) return; //it is not a line, nothing happened
slope = 0;
absx = 1;
absy = 0;
p=(int) (dx/absx); //p means number of steps
}
else if(x1==x2){
slope = 2;
absx = 0;
absy = 1;
p = (int) (dy/absy);
}
else{
slope = (float) (dy/dx);
absx=1;
absy=slope*absx;
p= (int) ((dy/absy > dx/absx) ? dy/absy : dx/absx);
}
for(int i = 0; i <=p;i++){
drawPixel(x1,y1,Color.BLACK);
x1 += absx;
y1 += absy;
}}
method draw Pixel at dda.java
private void drawPixel(int x1, int y1, Color BLACK) {
g.drawOval(x1, y1, x1+5, y1+5); //can be mistake right here?
}
part of JFrame class
public class NewJFrame extends javax.swing.JFrame {
int x1,x2,y1,y2;
Graphics2D g;
dda d;
public NewJFrame() {
this.d = new dda(20,30,20,50); //maybe this is not good?
initComponents();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
g = (Graphics2D) jPanel1.getGraphics();
d.drawLineDDA(g); // and I am definielly not sure about this
}
You should not use getGraphics() for custom painting, as it is a temporary buffer which is recycled on next repaint. Do you painting in paintComponent(). Override paintComponent() method of a JComponent or JPanel. See Performing Custom Painting for more information and examples. Also see Painting in AWT and Swing.
There is also an issue in drawPixel method, as the dimensions of the oval depend on the coordinates. Try using constant dimension. fillOval may suit better. Here is an example:
private void drawPixel(Graphics2D g, int x1, int y1) {
g.fillOval(x1, y1, 3, 3);
}