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.
Related
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.
Hi I am trying to create parabolic curves using lines in awt java but previous lines are getting removed as soon as some new lines are drawn.
I am using this code in paint method
static int x1 = 0;
static int y1 = 300;
static int x2 = 300;
static int y2 = 300;
#Override
protected void paintComponent(Graphics g) {
//super.paintComponent(g);
g.setColor(Color.RED);
for(int i = 0; i < 15;i++,x1 += 4, y2 -= 2) {
g.drawLine(x2, y2, x1, y1);
}
//repaint();
}
but if i iterate loop for 10 times then only its drawing lines correctly.
My ouput
what I want to acheive is draw parabolic curves in each quadrant like this
ignore the red text in second image.
Ref - https://www.mrsmilewski.com/parabolic-curve.html
Any help appreciated.
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
Hello I would like to prevent graphics drawing and drawing again but I don't know how to do, I just want my panel delete all painted graphics and restart with same code. I tried some methods posted here but no one does the job.
public class Main extends JPanel implements ActionListener {
Timer timer;
private double angle = 444;
private double scale = 1;
private double delta = 0.0001;
RoundRectangle2D.Float r = new RoundRectangle2D.Float();
int counter = 0;
public Main() {
timer = new Timer(55, this);
timer.start();
}
public void paint(Graphics g) {
counter++;
int h = getHeight();
int w = getWidth();
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(new Color(randomNumber(0, 155), randomNumber(0, 255),randomNumber(0, 155), randomNumber(0, 255)));
drawCircles(g2d, getWidth()/2, getHeight()/2, 250);
if(counter > 200){
g2d.clearRect (0, 0, getWidth(), getHeight());
super.paintComponent(g2d);
counter = 0;
}
}
public int randomNumber(int min, int max) {
int c = new Random().nextInt((max - min) + 1);
return c;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setUndecorated(true);
Dimension dim = new Dimension(Toolkit.getDefaultToolkit()
.getScreenSize().width, Toolkit.getDefaultToolkit()
.getScreenSize().height);
frame.setSize(dim);
frame.setLocation(0, 0);
frame.setBackground(new Color(0, 0, 0, 255));
frame.add(new Main());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
void drawCircles(Graphics graphics, int xMid, int yMid, int radius) {
// end recursion
if(radius < 5)
return;
// Draw circle
// start recursion
//left
drawCircles(graphics, xMid-radius, yMid, radius / 2);
((Graphics2D) graphics).rotate(angle);
graphics.drawOval(xMid - radius, yMid - radius, radius * 2, radius * 2);
//right
drawCircles(graphics, xMid+radius, yMid, radius / 2);
graphics.drawOval(xMid - radius, yMid - radius, radius * 2, radius * 2);
((Graphics2D) graphics).rotate(angle);
((Graphics2D) graphics).rotate(angle);
((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
}
public void actionPerformed(ActionEvent e) {
if (scale < 0.01)
delta = -delta;
else if (scale > 0.99)
delta = -delta;
scale += delta;
angle += 0.001;
repaint();
}
}
I am not sure I understand you fully, but you can use a JToggleButton (for example) where is the toggle button is down it prevents drawing. I can see something like this inside your drawCircles() method:
void drawCircles(Graphics graphics, int xMid, int yMid, int radius)
{
if(!toggleBtn.isSelected() // the toggle button is pressed
{
// draw something
}
}
In your example, you are drawing two circles and two ovals. If I understood you correctly, you want to be able to pause in the middle of the method, for example, and only draw the first circle. Then, at some point, you want to continue drawing the two ovals and the remaining circle. Unfortunately, you cannot do that. You cannot stop (or pause) a method in the middle of it.
Methods have to execute to completion (whether to the end, or an exception is thrown). However, you can create some kind of task to draw ONE shape (for example, a circle). If you create multiple tasks, you can draw many circles. To accomplish this, you will need to learn about Concurrency and probably about Java Tasks. You can have these tasks execute in some kind of order and because of concurrency, you could pause and resume these drawing tasks the way I think you would want.
Essentially, in this program bugs move around the screen eating food.
The issue that I am having is that graphics "circle" repaints fine and moves around the frame, but none of the bugs are repainted (However they are drawn initially).
I've tested it with console outputs and the x and y coordinates of the bugs do update, but the graphic in the frame does not.
So my question is, why is it the x/y of the circle is updated and repainted, but the bugs are not?
(As far as I can see, I'm approaching the task of changing the bugs x/y in the same way as with the circle)
(I've removed some of the things like the world getters and setters, and cut the code down a bit. The actual program has a movebug() method which handles the moving of the bugs in a correct fashion with hit detection.)
public class Run extends JPanel implements ActionListener{
double x, y, velX, velY, newx, newy;
public Timer t;
private static AWorld world1;
ArrayList<Ellipse2D> graphicBugArrayList = new ArrayList<Ellipse2D>();
public Run(){
x = 150;
y = 150;
velX = 2;
velY = 2;
t = new Timer(5, this);
setWorld1(new AWorld());
getWorld1().populatemap();
AWorld.direction directionchecker;
repaint();
t.start();
}
public void paintComponent(Graphics g){
//Creating circle that move
g.setColor(Color.BLACK);
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle = new Ellipse2D.Double(x, y, 10, 10);
//creating and drawing the bugs
for(int i=0; i<world1.getNumberofbugs(); i++)
{
Ellipse2D obscircle = new Ellipse2D.Double(getWorld1().bugArrayList.get(i).getHPosition(), getWorld1().bugArrayList.get(i).getVPosition(), 14, 15);
graphicBugArrayList.add(obscircle);
g2.setPaint(Color.RED);
g2.fill(graphicBugArrayList.get(i));
g2.draw(graphicBugArrayList.get(i));
}
//Drawing the circle that moves
g2.setPaint(Color.BLACK);
g2.draw(circle);
}
public void actionPerformed(ActionEvent arg0) {
//Moving the circle
if(x<0 || x > 500)
{
velX = -velX;
}
if(y<0 || y > 500)
{
velY = -velY;
}
x += velX;
y -= velY;
//Test moving the bugs
getWorld1().bugArrayList.get(i).setHPosition(getWorld1().bugArrayList.get(i).getHPosition()+1);
repaint();
}
}
You never clear your graphicBugArrayList, but only draw the first few elements over and over. Try this in your loop:
for(int i=0; i<world1.getNumberofbugs(); i++)
{
Ellipse2D obscircle = new Ellipse2D.Double(getWorld1().bugArrayList.get(i).getHPosition(), getWorld1().bugArrayList.get(i).getVPosition(), 14, 15);
graphicBugArrayList.add(i, obscircle);
g2.setPaint(Color.RED);
g2.fill(graphicBugArrayList.get(i));
g2.draw(graphicBugArrayList.get(i));
}