I have an assignment where I have to draw a circle in a panel and with that circle calculate the reaction time of the user when the circle changes size or color. I've got the paintComponent method. But now I have to call the method for the circles in another class and I don't know how to do that. Can someone please help me with this?
Here is my class where paintComponent is written:
public class ReactionPanel extends JPanel {
boolean setSmallCircle, setInitialCircle;
Color color = new Color (255,0,0); //color = red
Color c = new Color (255,255,0); //color = yellow
int size;
int x = 250;
int y = x;
public void paintComponent(Graphics g){
super.paintComponent(g);
if (setInitialCircle){
size = 50;
}
if (setSmallCircle) {
size = 50;
}
else {
size = 150;
}
g.drawOval(x,y,size,size);
g.fillOval(x,y,size,size);
}
void setInitialCircle(Graphics g, Color color){
g.setColor(color);
}
void setSmallCircle(Graphics g, Color c){
g.setColor(c);
}
void setBigCircle(Graphics g, Color c){
g.setColor(c);
}
}
Now I would need those (setInitialCircle etc) and call them in my main class ReactionExperiment like so:
void startTest(){
//draw red circle
}
How do I do this?
Thanks for the help!
I believe you want this ?
ReactionPanel reactionPanel = new ReactionPanel();
reactionPanel.setSmallCircle(x, x);
What this code does it instantiates ReactionPanel (it makes a new instance of it). As such you can then use its methods in another class.
I assume you have two classes, and you'd like to call a public function defined in one from the other. Since the method is not a static method, you'd have to instantiate an object for the class like -
ReactionPanel obj = new ReactionPanel();
then using this object, you can call any method defined in the first class, like
obj.paintComponent(g); // you'll have to define g first though
Related
I would like to draw rectangle, line etc. on canvas with GraphicsContext.
Rectangle rect = new Rectangle(20,20,10,10);
rect.setId("myRect");
gc.draw(rect);
Is there something like this in JavaFX? Or is there a way to access drawn canvas objects?
From what I know you can't draw Rectangles directly on a canvas - Rectangle is a JavaFX node, but the Canvas API is much lower level and only takes very basic drawing commands. For example, for drawing your rectangle, it would be:
GraphicsContext gc = theCanvas.getGraphicsContext2D();
gc.fillRect(20,20,10,10);
This however doesn't let you manipulate the rectangle any further. what I do is create a custom class DrawableRectangle (for example) with a method draw:
public class DrawableRectangle extends Rectangle {
Canvas theCanvas;
public DrawableRectangle(Rectangle r, Canvas c){
super(r.getX(),r.getY(),r.getWidth(),r.getHeight());
this.theCanvas = c;
}
public DrawableRectangle(int x, int y, int w, int h, Canvas c){
super(x,y,w,h);
this.theCanvas = c;
}
public void draw(){
GraphicsContext gc = theCanvas.getGraphicsContext2D();
gc.setFill(Paint.valueOf("black"));
gc.fillRect(getX(),getY(),getWidth(),getHeight());
}
}
Which you can then use like this:
GraphicsContext gc = theCanvas.getGraphicsContext2D();
DrawableRectangle rect = new DrawableRectangle(10,10,20,20, theCanvas);
// Draw it:
rect.draw();
// You can then manipulate it:
rect.setY(40);
rect.setHeight(60);
// You need to draw it again to see the changes:
// First clear the canvas:
gc.clearRect(0,0,theCanvas.getWidth(),theCanvas.getHeight());
// Then draw it:
rect.draw();
(I can't guarantee this is the best method, but it worked well for me. If you want to draw different shapes this way you should make an interface Drawable to abstract it.)
I have created a closed contour with a list of points which I want to be filled by a color.I have used boundary fill recursion algorithm but no luck the array index goes out of bounds since i cannot develop the if condition since the color inside the closed contour and color outside the contour is same.What method should i use to get the desired contour to be filled up by a specific color.Here is the code that i have tried
public class BoundaryFillAlgorithm {
public static BufferedImage toFill = MemoryPanel.Crect;
static Graphics g1 = toFill.getGraphics();
static int seedx = toFill.getWidth()/2;
static int seedy = toFill.getHeight()/2;
public static void BoundaryFill(int x,int y){
Color old = new Color(toFill.getRGB(x, y));
g1.setColor(Color.BLACK);
if(old!=Color.BLACK){
g1.fillOval(x, y, 1, 1);
BoundaryFill(x+1,y);
BoundaryFill(x,y+1);
BoundaryFill(x-1,y);
BoundaryFill(x,y-1);
}
}
Here's the image
Here's the method call
BoundaryFillAlgorithm.BoundaryFill(BoundaryFillAlgorithm.seedx,BoundaryFillAlgorithm.seedy);
g.setColor(Color.red); // Set color to red
g.fillRect(600, 400, 100, 100);// a filled-in RED rectangle
Why reinventing the wheel?
Graphics2D has a already a method fill(Shape).
There a many classes implementing the Shape interface, especially Polygon,
which you might reuse.
Finally corrected my code heres the corrected code:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class BoundaryFillAlgorithm {
public static BufferedImage toFill = MemoryPanel.Crect;
Graphics g1 = toFill.getGraphics();
public BoundaryFillAlgorithm(BufferedImage toFill){
int x = toFill.getWidth()/2-10;
int y = toFill.getHeight()/2;
int old = toFill.getRGB(x, y);
this.toFill = toFill;
fill(x,y,old);
}
private void fill(int x,int y,int old) {
if(x<=0) return;
if(y<=0) return;
if(x>=toFill.getWidth()) return;
if(y>=toFill.getHeight())return;
if(toFill.getRGB(x, y)!=old)return;
toFill.setRGB(x, y, 0xFFFF0000);
fill(x+1,y,old);
fill(x,y+1,old);
fill(x-1,y,old);
fill(x,y-1,old);
fill(x+1,y-1,old);
fill(x+1,y+1,old);
fill(x-1,y-1,old);
fill(x+1,y-1,old);
}
}
I am trying to draw fish at whatever location the user enters, but it will either say
drawFish.java:38: error: cannot find symbol
outer.add(sPanel1);
Or
Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container
at java.awt.Container.checkNotAWindow(Container.java:483)
at java.awt.Container.addImpl(Container.java:1084)
at java.awt.Container.add(Container.java:410)
at drawFish.main(drawFish.java:38)
I was thinking that I need to make a new panel for each fish, but how do I make a loop to create multiple panels? If that is even the problem? Also, I am supposed to use a method that takes an x and a y coordinate so the user can change the location of a fish, and draw a number of fish at different locations. But that's not what I'm doing. I've tried to make a method including the questions of x and y, but then it says that the variables aren't public and thus can't be used in the paint method. I would appreciate explanations for everything, because I want to comprehend everything that I am doing.
public class drawFish extends JPanel {
int x = Integer.parseInt(JOptionPane.showInputDialog(null, "What is the x location of the fish? "));
int y = Integer.parseInt(JOptionPane.showInputDialog(null, "What is the y location of the fish? "));
int w = 200;
int h = 100;
int a = x + 20;
int b = y + 30;
int d = 50;
public drawFish() {
setPreferredSize(
new Dimension(400,400));
}
public void paint(Graphics g) {
g.setColor(Color.GREEN);
g.fillOval(x, y, w, h);
g.fillOval((w-5), y, d, h);
g.setColor(Color.BLACK);
g.fillOval(a, b, 25, 25);
}
public static void main(String[] args) {
MyFrame frame1 = new MyFrame("Drawing Fish");
JPanel outer = new JPanel();
int fn = Integer.parseInt(JOptionPane.showInputDialog(null, "How many fish would you like to draw? "));
for(int i=0; i<fn; i++){
drawFish sPanel1 = new drawFish();
}
outer.add(sPanel1);
frame1.add(outer);
frame1.pack();
frame1.setVisible(true);
}
}
Don't make many JPanels, just make one drawing JPanel.
Create a Fish class that is not a JPanel nor a component, but has a draw(Graphics g) method so that can draw itself at its current location when asked to.
Give your JPanel an ArrayList<Fish> and fill the list with Fish objects.
In your JPanel's paintComponent(Graphics g) method (not the paint method), loop through the ArrayList calling draw(g) on each Fish object it contains.
Be sure to call super.paintComponent(g) as the first line of your drawing JPanel's paintComponent(Graphics g) method so that old drawings will be erased.
Your for loop logic is off. If you're going to create objects inside of a for loop, you need to add them to something from inside of the loop. Else all you're dong is creating objects and discarding them, never to use them.
You will want to learn and stick with Java naming conventions. Class names, such as DrawFish, should start with an upper-case letter, and methods and variables with a lower-case letter.
sPanel1 variable's scope finishes as soon as you get out of loop.
Therefore replace
for(int i=0; i<fn; i++){
drawFish sPanel1 = new drawFish();
}
outer.add(sPanel1);
with
for(int i=0; i<fn; i++){
drawFish sPanel1 = new drawFish();
outer.add(sPanel1);
}
Now all panels will be added.
Also consider using a LayeredPane.
Hope this helps.
I have defined a class called Stone to add graphical stones to a JPanel:
public class Stone {
private int x, y;
private Color color;
private static final int radius = 18;
Stone(Color color) {
this.color = color;
}
public Stone(int x, int y, Color color) {
this(color);
this.x = x;
this.y = y;
}
void draw(Graphics g) {
g.setColor(color);
g.fillOval(x - radius, y - radius, 2 * radius, 2 * radius);
}
void setX(int x) {
this.x = x;
}
void setY(int y) {
this.y = y;
}
}
I want to draw them on a JPanel. Do I have to do this within the paint method of JPanel or is it possible to use the add method of JPanel?
A quick answer is that you should extend a JComponent (because you want to add it to JPanel) and override the paintComponent method (because you want some custom painting of your object).
The easiest thing to try is to make your Stone class extend JComponent, rename draw() to paintComponent() and add a Stone instance to your JPanel.
It depends on what you want to do with it on the screen. As the others mentioned you could inherit from JComponent, which could be a good choice if the user wants to interact with it in some way.
A more light-weight approach could be to implement the Shape interface, or provide a method getShape().
You could use the ShapeIcon I wrote some time ago, to add it to a JLabel:
http://softsmithy.sourceforge.net/lib/docs/api/org/softsmithy/lib/swing/icon/ShapeIcon.html
Then add the JLabel to the JPanel.
But maybe instead of adding individual Stone icons to individual JLabels, you want to draw an image first and show that in the JPanel?
If you could tell us more about your goals we could help you better.
I'm trying to make a tower of hanoi solver which simply solves the hanoi without any mouse events. The problem is when I move the rectangle the original remains, even after I repaint. I've searched the net and tried changing the code around but nonthing worked. I am using a JFrame with a JPanel inside of it if that changes anything.
I have my disk class here which is just a rectangle with colour.
class Disk extends Rectangle {
Color diskColour;
public Disk(int a, int b, int c, int d, Color colour) {
x = a;
y = b;
width = c;
height = d;
diskColour = colour;
}
public Color getColour() {
return diskColour;
}
public void paintSquare(Graphics g) {
repaint();
g.setColor(diskColour);
g.fillRect(x, y, width, height);
repaint();
}
}
Here is my code where I actually call the paintSquare method:
public void simpleMoveDisk(Disk[] disks, int n, Graphics g) {
disks[n].setLocation(30,25);
disks[n].paintSquare(g);
repaint();
}
The paintSquare method paints the disk, while the setLocation method changes its coordinates.
When this runs the rectangle occurs in the new location, however the old one still remains. Any help is appreciated, thanks in advance.
You are calling repaint() in several places and you shouldn't be.
Have your the top level class that is doing the painting, call the paintSquare method and any other method that is needed. Those methods should not be calling repaint().
Also your simple move disk is really strange in the fact that it passes an array of Disks, an index, and a graphics object. Instead make it just take in a Disk. Just pass it the one out of the array that is needed to be updated. Then let whatever class that calls simpleMoveDisk, separately make a call to repaint instead of trying to paint and update the model in the same method.