Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does all graphical objects have to inherit from JPanel?

Tags:

java

swing

I have a problem about Java Swing and JPanel. I could say that I am an unexperienced Java programmer, but not entirely new to programming.

My problem is that I have an class called RandomParticle,

public class RandomParticle extends Ellipse2D.Double {

    private Ellipse2D.Double circle;

    public RandomParticle(double xPos , double yPos,double rad) {
        setCircle(new Ellipse2D.Double(xPos, yPos, rad, rad));
    }

    public Ellipse2D.Double getCircle() {
        return circle;
    }

    public void setCircle(Ellipse2D.Double circle) {
        this.circle = circle;
    }
}

which I want to move on the screen (in a JFrame of course). The particle is a default object just to get up the graphics. However, it is said on many places, for example here, that to be able to draw the circle it has to override the method paintComponent in the JPanel. It does indeed feel reasonable that, to draw something in a JFrame it has to be a JPanel. However this may cause trouble since Java does not support multiple inheritance.

In this case I do not really need RandomParticle to be a child of ellipse2D, but as my classes gets more complicated I will most likely need to inherent from some other class at some point. However, I felt this level of the question has a good dept for SO, since it does not require any specific knowledge of my program. So what I wonder is: Is it possible to draw a circle without the class being a child to JPanel?

like image 515
patrik Avatar asked Jul 30 '15 06:07

patrik


1 Answers

Is it possible to draw a circle without the class being a child to JPanel?

Kind of, but it's wrought with issues. I'll try and explain

If you want to perform custom painting in Swing, you should override the paintComponent method of any component which extends from JComponent, JPanel generally be the easiest solution, this is how painting works

Have a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works.

Generally speaking it's unadvisable to try and paint directly to a top level container like JFrame as it contains a number of other child components which are painted on top it (the JRootPane, contentPane, glassPane, menuBar, etc), which could be painted independently of the frame cause some weird painting artifacts.

A more detailed view of what a JFrame actually looks like...

RootPane

JFrame is also not double buffered, meaning that if you did try and paint directly to it, trying to update it quickly, it would cause flickering. JComponent and it's decedents are double buffered by default

Swing itself uses a passive rendering engine, this means that you don't actually control the painting process, you are simply notified when your component needs to be painted (via the paintComponent method). Swing may choose to paint child components without needing to notify the parent container, which is one of the reasons why paintComponent is generally encouraged. It may also consolidate multiple paint requests in as few calls as possible, to optimise the process.

All of this is done without your knowledge or control.

If, however, you want more control over the paint process, you could consider using a BufferStrategy, which gives you direct (double buffered) control of the painting process, so you can decide when and what should be painted. But even this would require you to use a java.awt.Canvas as a base from which to generate your output.

As a general rule of thumb, it's generally discouraged to extend from JFrame (or most top level containers) and instead use one of the container classes as your base class. This way you gain much more freedom over how they should be displayed or re-used, adding them to what ever other container you wish

like image 119
MadProgrammer Avatar answered Sep 19 '22 00:09

MadProgrammer