views:

34

answers:

3

Hi, I have an applet where I am drawing stuff by overriding the paint() method, and have added a Canvas to the applet, which will take up the whole screen. This canvas seems to be being drawn after my paint()ing, and so my applet's paint()ed stuff is invisible. Any ideas on how to force the canvas to be drawn before my paint method on my applet?

Thanks.

Edit:

public void paint(Graphics g) {
    super.paint(g);
    if (DEBUG) {
        g.setColor(Color.red);
        g.drawString("Memory free: " + ((Runtime.getRuntime().freeMemory()
            / 1024) / 1024) + "MB", 5, 20);
        g.drawString("Memory total: " + ((Runtime.getRuntime().totalMemory()
            / 1024) / 1024) + "MB", 5, 35);
        g.drawString("Memory used: " + (((Runtime.getRuntime().totalMemory()
            - Runtime.getRuntime().freeMemory()) / 1024) / 1024) + "MB", 5, 50);
    }
}
+1  A: 

Without seeing your code it's hard to guess what you have done.

The general code in the paint() method should probably be:

super.paint(g); // this will paint the children components added to the applet
// add your custom painting here

Also, it would be better to spend your time learning Swing rather that AWT since painting in Swing is somewhat different and you might as well spend time learning a more current GUI solution.

If you need more help post your SSCCE.

camickr
I am using an AWTGLCanvas (using LWJGL) to be precise, so Swing won't really help. My paint() method is:public void paint(Graphics g) { super.paint(g); if (DEBUG) { g.setColor(Color.red); g.drawString("Memory free: " + ((Runtime.getRuntime().freeMemory() / 1024) / 1024) + "MB", 5, 20); g.drawString("Memory total: " + ((Runtime.getRuntime().totalMemory() / 1024) / 1024) + "MB", 5, 35); g.drawString("Memory used: " + (((Runtime.getRuntime().totalMemory() - Runtime .getRuntime().freeMemory()) / 1024) / 1024) + "MB", 5, 50); } }
Adam Smith
+1  A: 

If you intend to paint something over that canvas component by overriding paint() of its container, it wont work. The thing is, AWT containers do not paint their children. This is true even for Swing containers by the way. If you need to paint something over the canvas Component, define your custom subclass of component and put your drawing code in its paint() method. and then set that component into your applet via setGlassPane() method. or, even better, simply override paint() of your Canvas (not its container) and do the painting after invoking super.paint(g)

Andrew Butenko
for painting over AWTGLCanvas, the glassPane approach could probably work. overriding the paint method may introduce flicker or other unwanted effects when drawing over opengl context
Andrew Butenko
I think Swing `paint()` invokes `paintChildren()`: http://java.sun.com/products/jfc/tsc/articles/painting/index.html
trashgod
I agree but what i meant to say is that repaint manager doesn't always go through entire hierarchy when some child component is enqueued to be repainted. it goes straight to that component and calls its paint method without calling paint of its parent. So even if your paint() is overriden to do nothing, child components will occasionally peek through (as consequence of somebody calling repaint() on those child components)
Andrew Butenko
Ah, I see; thanks for clarifying.
trashgod
A: 

Even if you must use AWT, you should be able to use a separate Panel for the GL content and the memory status:

import java.awt.*;
import java.awt.event.*;

public class AWTPaintTest {

    public static void main(String[] args) {
        Frame frame = new Frame();
        // frame.add(new AWTGLCanvas(), BorderLayout.CENTER);
        frame.add(new MemoryPanel(), BorderLayout.SOUTH);
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        frame.pack();
        frame.setVisible(true);
    }

    private static class MemoryPanel extends Panel {

        private final Runtime r = Runtime.getRuntime();

        public MemoryPanel() {
            this.setPreferredSize(new Dimension(240, 120));
            this.setForeground(Color.blue);
            this.setFont(new Font("Monospaced", Font.BOLD, 16));
            this.addMouseListener(new MouseAdapter() {

                @Override
                public void mousePressed(MouseEvent e) {
                    r.gc();
                    MemoryPanel.this.repaint();
                }
            });
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            long m = r.maxMemory();
            long t = r.totalMemory();
            long f = r.freeMemory();
            int y = g.getFontMetrics().getHeight() + 4;
            g.drawString("Memory max:   " + toMB(m), 5, 1 * y);
            g.drawString("Memory total: " + toMB(t), 5, 2 * y);
            g.drawString("Memory free:  " + toMB(f), 5, 3 * y);
            g.drawString("Memory used:  " + toMB(t - f), 5, 4 * y);
            g.drawString("Click to update.", 5, 5 * y);
        }

        private String toMB(long bytes) {
            return (bytes / 1024) / 1024 + " MB";
        }
    }
}
trashgod
Thanks, it cleared up some confusion and it works now (for me anyway)
Adam Smith