Timmos
Timmos

Reputation: 3324

Painting on a Component from within its LayoutManager

I'm developing an application and I have a panel that needs a custom LayoutManager. To test my LayoutManager implementation, I would like to have some debug mode built in, very much like MigLayout's debug mode, which draws dashed rectangles when debug mode is on.

In my custom LayoutManager, this is what I tried:

@Override
public void layoutContainer(Container parent) {
    // compX.setBounds(...); // calculate for all components and set bounds

    parent.getGraphics().drawRect(0,0,parent.getWidth(), parent.getHeight());
}

It doesn't work as you probably expected.

I don't want to modify the panels that are being layed out - just like MigLayout, you specify "debug" in the MigLayout constructor and you have your dashed lines and you do not need to modify anything in the component that is being layed out.

How can I draw on parent while not modifying its internals?

Upvotes: 1

Views: 185

Answers (1)

kleopatra
kleopatra

Reputation: 51535

Assuming the thingies to paint are hidden details of the LayoutManager, that is the manager itself is indeed the only collaborator with enough knowledge to be able to do the painting, you need a debug painting hook which has no other means but use parent.getGraphics() As such painting doesn't survive for long, using code must call it repeatedly, f.i. in a Timer.

A LayoutManager with a debug painting hook (note: it's just an example, no hidden state that would justify the trick :)

public static class MyBorderLayout extends BorderLayout {
    Color[] colors = new Color[] {Color.RED, Color.BLUE, Color.GREEN, Color.CYAN, Color.MAGENTA};
    public void paintDebug(Container parent) {
        Graphics g = parent.getGraphics();

        for (int i = 0; i < parent.getComponentCount(); i++) {
            Component child = parent.getComponents()[i];
            g.setColor(colors[i % colors.length]);
            Rectangle r = child.getBounds();
            g.drawRect(r.x, r.y, r.width, r.height);
        }
    }
}

// usage:

final JComponent comp = new JPanel(new MyBorderLayout());
comp.add(new JTable(10, 3));
comp.add(new JLabel("east"), BorderLayout.EAST);
comp.add(new JLabel("west"), BorderLayout.WEST);
comp.add(new JLabel("north"), BorderLayout.NORTH);
comp.add(new JLabel("south"), BorderLayout.SOUTH);
ActionListener l = new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        ((MyBorderLayout) comp.getLayout()).paintDebug(comp);
    }

};
showInFrame(comp, "debug");
new Timer(400, l).start();

Upvotes: 2

Related Questions