how to override paintComponent method and use with JPanel [duplicate] - java

This question already has an answer here:
How to draw the radius of a circle without it being shorter or larger than the circumference
(1 answer)
Closed 5 years ago.
I have override paintComponents method, but when I am using it and run my program then it does not show any circle and lines. Recently frakcool said it is not paintComponents method, it is paintComponent method. I found out but I didn't get any paintComponent method.
This picture shows that i have not got any paintComponent method:
Codes are here.
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SecondActivity frame = new SecondActivity();
frame.setBackground(Color.WHITE);
frame.paintComponents(null);
// frame.paint(null);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
#Override
public void paintComponents(Graphics g) {
// TODO Auto-generated method stub
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g;
drawCircle(g2d,centerX,centerY,r);
drawLineAzim(g2d);
drawLineEle(g2d);
}

You are overriding the wrong method. Get rid of the "s" at the end of the method name. You need to override paintComponent(...).
But, you also need to override the paintComponent(...) method of a JPanel, You can't just add the method to your class and expect it to work. This is Java 101.
Start with the working examples found in the Swing tutorial on Custom Painting

Related

Animating a shape in a JPanel

first questing for me here. Been searching forever but cant seem to find the answer.
Im working on a school assignment. Got given an ui and are supposed to make the different panels in it do different things in separate threads. Anyway, Im trying to make a triangle rotate inside one of the JPanels. I have managed to draw it and somewhat rotate it, but when I try to make a loop to update it it just blinks and then disappears again. Heres the code Ive written.
StartAssignment, starts the application
public class StartAssignment1 {
public static void main(String[] args) {
Controller controller = new Controller();
}
Controller, recieves calls from the ui and executes various functions in other classes
public class Controller {
private GUIAssignment1 gui = new GUIAssignment1(this);
private RotateShape rotateShape;
private Thread t1;
public Controller() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gui.Start();
}
});
}
public void startT1(JPanel panel) {
rotateShape = new RotateShape(panel);
t1 = new Thread(rotateShape);
t1.start();
}
public void t1Shutdown() {
rotateShape.shutdown();
}
RotateShape, where Im trying to rotate the damned thing
public class RotateShape implements Runnable {
JPanel panel;
private volatile boolean t1Running = true;
public RotateShape(JPanel panel) {
this.panel = panel;
}
private void draw() {
Graphics2D g2 = (Graphics2D) panel.getGraphics();
g2.rotate(Math.toRadians(10));
g2.drawPolygon(new int[] {50, 100, 150}, new int[] {150, 50, 150}, 3);
}
public void shutdown() {
t1Running = false;
System.out.println("Shutdown");
}
#Override
public void run() {
while (t1Running) {
try {
draw();
Thread.sleep(500);
System.out.println("loop working");
panel.repaint();
panel.revalidate();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I'm not certain because I don't have access to your GUI code and therefore cannot test it myself, but here's an idea:
It looks like you're rotating your Graphics2D object by a fixed amount on every re-render (i.e. every invocation of draw()). It's possible that the internal JPanel code initiates the Graphics2D at a default rotation before every re-render, which may be why your rotation only causes the shape to "somewhat rotate."
Maybe try storing a variable for the radian offset (e.g. double offset;) as a member field of the RotateShapeclass, incrementing it on every re-render, then calling g2.rotate(Math.toRadians(offset));?
Addendum 1:
The reason that it may draw on top of the previous render is because the Graphics2D object is not clearing the canvas between re-renders. One way to fix this is to "clear" the canvas at the beginning of the draw() method by filling a rectangle that covers the whole canvas.
Addendum 2:
When you call panel.repaint(), it triggers the paintComponent() method of the JPanel object. So, by calling repaint() and your own draw() method, you are doing two separate renders, which may cause some graphical errors. If you were able to extends the JPanel class and use that, you should define an override to replace draw():
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// TODO: add your rendering operations here
}
This way, calls to repaint() should trigger this method.

Repaint function messes up the whole frame

I have a problem when trying to draw some elements using paint method in Swing.
As title says, my whole frame collapses and does some weird repeating.
I made a separate JPanel so I can manipulate drawn shapes:
public class PanelPovrsina extends JPanel{
private ArrayList<Oblik> listaOblika;
public PanelPovrsina() {
// svi oblici
this.listaOblika = new ArrayList<Oblik>();
this.listaOblika.add(new Kvadrat(new Tacka(50, 50), 50, "zuta", "crvena"));
this.setBackground(Color.WHITE);
this.setVisible(true);
}
public void paint(Graphics g) {
if(this.listaOblika.isEmpty()) return;
Iterator<Oblik> it = this.listaOblika.iterator();
while(it.hasNext()) {
it.next().crtajUBoji(g);
}
repaint(); // this causes problems!
}
public ArrayList<Oblik> getListaOblika() {
return this.listaOblika;
}
}
Here is the frame with this code:
And here it is without repaint method:
No, I know repaint method is essential in order to dynamically add shapes and actually draw, but I can't make this work correctly.
Also, as you can see from the code above, background of panel is set to white, but my frame would'n render it.
Hope there is enough information to solve my problem, if not, I will add code of my JFrame!
Thank you!
You should never override the paint method, as it handles a number of other things behind the scenes. You should override paintComponent instead.
As #Joe C answered, I should have been using paintComponent method, not paint! Working code:
public class PanelPovrsina extends JPanel{
private ArrayList<Oblik> listaOblika;
public PanelPovrsina() {
// svi oblici
this.listaOblika = new ArrayList<Oblik>();
this.listaOblika.add(new Kvadrat(new Tacka(50, 50), 50, "zuta", "crvena"));
this.setBackground(Color.PINK);
this.setVisible(true);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Oblik obl : this.listaOblika) {
obl.crtajUBoji(g);
}
repaint();
}
public ArrayList<Oblik> getListaOblika() {
return this.listaOblika;
}
}

How can I create an animation method and put that in paint method? My code doesn't work

Why doesn't this work? I created a method for an animation loop of two pictures called animation(),
and i want to put that in the paint method. How do i do this?
import java.applet.*;
import java.awt.*;
public class Slot_Machine extends Applet
{
Image back;
int coin=10;
// Place instance variables here
public void init ()
{
back= getImage(getDocumentBase(),"Images/Background/Slot Machine.png");
// Place the body of the initialization method here
} // init method
public void animation(Graphics g)
{
Image Title1,Title2;
Title1= getImage(getDocumentBase(),"Images/Title Animation/Title 1.png");
Title2= getImage(getDocumentBase(),"Images/Title Animation/Title 2.png");
while(true){
g.drawImage(Title2,200,0,this);
{ try { Thread.currentThread().sleep(2000); }
catch ( Exception e ) { } }
g.drawImage(Title1,200,0,this);
{ try { Thread.currentThread().sleep(2000); }
catch ( Exception e ) { } }
}//end while(true) loop
}//end animation
public void paint (Graphics g)
{
g.drawImage(back,0,0,this);
animation(); //FROM THE METHOD ABOVE, WHY DOESNT THIS WORK? HOW DO I FIX THIS?
String coins = String.valueOf(coin);
g.setColor(Color.white);
g.setFont(new Font("Impact",Font.PLAIN,30));
g.drawString(coins,405,350);
// Place the body of the drawing method here
} // paint method
}
Your animation() method has an infinite loop in it, which means that paint() never returns, which is causing the thread trying to start up the applet to hang while waiting for paint() to return.
If you want to run a forever-looping animation in the background, try doing it in another thread. Take a look at ExecutorService.

Draw on Jframe image

I want to read a file to get some points and then draw these points on an image. Currently, I am able to draw values on the image, but the file is read three times and the rectangles are drawn three times. I don't know where is the problem. Below is the code. The Read() function works fine seperately so I didn't include it in the code.
P.S: I am beginner in JAVA and don't know much about JFrame and Jcomponent.
public class LoadImageApp extends JComponent {
BufferedImage img;
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
Read(g);// This is the function in which I read a file.
}
public LoadImageApp() {
try {
img = ImageIO.read(this.getClass().getResource("/New York.jpg"));
} catch (IOException e) {
}
}
public Dimension getPreferredSize() {
if (img == null) {
return new Dimension(100,100);
} else {
return new Dimension(img.getWidth(null), img.getHeight(null));
}
}
public static void main(String[] args) {
JFrame f = new JFrame("Load Image Sample");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
LoadImageApp img = new LoadImageApp();
f.add(img);
f.pack();
f.setVisible(true);
}
}
Do not, do not, DO NOT read from a file from within any painting method such as paintComponent(...). :)
That method should be for painting only. The more you slow it down, the less responsive your GUI will seem.
You cannot control how many times the method gets called, since it is not under direct control by you, the programmer.
You can't even control fully if the paintComponent method gets called, since the JVM might decide that too many requests for redraw are being stacked up, and it may not honor all of them.
Instead
read in the data once in a constructor or something similar.
I would create a read method that stores my points in an ArrayList<Point>, and then inside of the paintComponent method, iterate through that ArrayList using a for loop and draw them.
If the points don't change during your program's run, you could even draw them directly on to the BufferedImage by getting its Graphics context and using that to paint the points on to the image, and then show the new BufferedImage in your paintComponent method.
Other suggestions:
That empty catch block where you read your image is a dangerous thing to do. It's the coding equivalent of driving a motorcycle with your eyes closed. At least print out a stacktrace.
The WindowListener is not needed. Instead simply set your JFrame's defaultCloseOperation to JFrame.EXIT_ON_CLOSE: f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Error in a simple applet

The following code is supposed to print
inside init()-- inside start()-- inside paint().
But it prints the last part inside paint() TWICE! Why is that?
public class SampleApplet extends Applet {
String msg;
#Override
public void init(){
setBackground(Color.BLACK);
setForeground(Color.yellow);
msg = "Inside init()-- ";
}
#Override
public void start(){
msg += "Inside start()-- ";
}
#Override
public void paint(Graphics g){
msg += "Inside paint().";
g.drawString(msg, 10, 30);
}
}
Quoted from: Paint():
the paint() method will be called as many times as necessary. If you
put another window over your GUI then the paint() method will be
called. If you then minimize that window and make your GUI visible
again then the paint() method will be called again. And so on.
So if you have something that is a problem if the paint() method is
called more than once, you have done it wrong. Don't do it that way.
The paint() method should only redraw its target from existing data,
it should never have to do calculations to figure out what to paint.
The paint method may be called by update when the component needs to repaint the content of the component state is invalidated.

Categories

Resources