Search code examples
javaswingjpanelgraphics2dpaintcomponent

Object-oriented approach to 2D graphics: delegating JPanel clicks to painted objects


Coming from Qt, I always use QGraphicsScene in association with QGraphicsItem objects to draw stuff like flowcharts, game boards, et cetera. Graphics scenes are widgets, which are the Qt equivalent of Swing components. These QGraphicsItem objects have their own click handlers, so clicks on certain parts of the graphics scene are automatically delegated to the correct graphics item.

I'm looking to replicate this workflow in Java Swing. So far I've only found a way to paint everything manually, which would also mean that I'd have to program the clicking logic manually. It involves subclassing a JPanel and overriding the paintComponent function as shown here:

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;

    for (int row = 0; row < _numRows; ++row) {
        for (int col = 0; col < _numCols; ++col) {
            g2.drawRect(2 + _squareSize*col, 2 + _squareSize*row, _squareSize, _squareSize);
        }
    }
}

Does Java Swing have a similar object-oriented way to draw 2D graphics?


Solution

  • Generally there are two ways to achieve that:

    1. Use single JComponent as base and draw all your "items" directly onto it (in paintComponent method). In this case you will have to handle all mouse/key events by yourself by adding mouse/key listeners to that JComponent and handling events depending on click location/hotkey pressed.

    2. Another way is to use any Container (or just simple JPanel) as base and place any other Component onto it using layouts (for example with "null" layout you can simply put components by absolute coordinates inside container, also called bounds). In this case different events will be passed directly to those components depending on their location inside container (basically - each component has a rectangle bounds in which all events are passed to that component if nothing lies on top of it, but you can change that "hit" area to any shape you like). Also in this case you can use either custom painted components as childs or standard Swing components (like JButton, JCheckBox and such).

    In most cases 2nd way is the best, though 1st might be useful sometimes (for e.g. when creating some image editor, paint-like application or any other application that works with graphics).