Pox
Pox

Reputation: 387

Painting on a JPanel from a different class in Swing

I am currently working on a test driven interactive 2D fluid dynamics simulation for my Bachelor thesis. The basic idea is that the user can draw shapes on his screen and the program will simulate how a fluid will flow around these shapes. So far I have only started with the painting process and I have already run into a little problem.

First, here is a little UML diagram that shows my project structure so far

As you can see, I have created a Painter class that can visit several shapes and will call one of the abstract paint methods depending on the shape type. Then there is the SwingPainter class which inherits from the Painter class and implements the three paint methods as well as the clear method. Here is the code for my SwingPainter:

public class SwingPainter extends Painter {

    private final GraphicPanel graphicPanel;

    public SwingPainter(GraphicPanel graphicPanel) {
        this.graphicPanel = graphicPanel;
    }

    private Graphics getGraphics() {
        return graphicPanel.getGraphics();
    }

    @Override
    protected void paintLine(Point start, Point end) {
        getGraphics().drawLine(start.getX(), start.getY(), end.getX(), end.getY());
    }

    @Override
    protected void paintRectangle(Point start, Point end) {
        int minX = start.getX() < end.getX() ? start.getX() : end.getX();
        int minY = start.getY() < end.getY() ? start.getY() : end.getY();
        int width = Math.abs(start.getX() - end.getX());
        int height = Math.abs(start.getY() - end.getY());
        getGraphics().drawRect(minX, minY, width, height);
    }

    @Override
    protected void paintCircle(Point center, double radius) {
        int minX = center.getX() - (int) radius;
        int minY = center.getY() - (int) radius;
        int diameter = (int) radius * 2;
        getGraphics().drawOval(minX, minY, diameter, diameter);
    }

    @Override
    public void clear() {
        graphicPanel.paintComponent(getGraphics());
    }
}

So my problem is that the GraphicPanelPresenter(see UML diagram) is responsible for passing the Painter/Visitor to the shapes when the user left clicks or moves the mouse(the second point of a line will follow the cursor for example). That means the actual painting is done outside of Swing's paint method. As a result I have encountered some flickering while painting and I was wondering if anyone knew how to fix that without throwing the whole painter/visitor functionality out the window(since there are other features concerning the shapes that still have to be implemented and could easily be handled by simply passing them another type of visitor).

Well, that was a rather lengthy description for a rather small problem, sorry for the wall of text, but I would be glad for any kind of hint!

Upvotes: 2

Views: 154

Answers (1)

NESPowerGlove
NESPowerGlove

Reputation: 5496

You need to do all the of painting in the various Swing paint methods that are designed to be overridden for custom painting (such as paintComponent). Only Swing will know when it's done drawing, or when a new frame needs to be drawn to.

What it really seems like you need to do, is to have your GraphicsPanel have a reference to the object that holds your shape's states, and then draw the graphics that represent that state in paintComponent.

This should also simplify your class relationship diagram as well, since within GraphicsPanel you can call the state object's methods from your listeners to change the state (I would choose different names to make the state object not aware that the changes are based on UI interactions, so if right click rotates, make the method called rotate instead of handleRightClick).

Upvotes: 1

Related Questions