2

I'm working on a simple painting application in Java but Swing doesn't want to cooperate. At first I tried making a JTabbedPane that holds the DrawArea and a settings panel, but for some bizarre reason the second mouseDragged() (and by extension the drawArea.repaint() method) was triggered, the JTabbedPane seemed to duplicate. Imagine two identical tab panes stacked vertically. I thought this was just some bug in JTabbedPane, but I rewrote everything to a very simple custom menu using JButtons on a panel and the exact same thing happened. It's not like the GUI actually duplicated the top area; it's unusable and I can paint over it. Check it out: enter image description here

Edit: I found a similar question. If I call super.paintComponent(g), the problem goes away (and drawArea.setBackground(color) actually works!) but the function called on super (a new keyword for me) basically repaints the drawArea so the paint trail is no longer saved.

If I paint a rectangle to fill the drawArea it overwrites the issue even though mouseDragged is still fired. Here's the rendering code:

@Override
public void mouseDragged(MouseEvent e) {
    x = e.getX(); y = e.getY();
    drawArea.repaint();
}

// (subclass):
class DrawArea extends JPanel {
    public void paintComponent(Graphics g) {
        g.setColor(Color.WHITE);
        g.fillOval(x-3, y-3, 7, 7);
    }
}

And here's the GUI code:

    frame = new JFrame("Jadra");
    frame.setSize(650, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    menu = new JPanel();

    settingsButton = new JButton("Settings");
    clearButton = new JButton("Clear");
    exitButton = new JButton("Quit");

    menu.setLayout(new FlowLayout());
    menu.add(settingsButton);
    menu.add(clearButton);
    menu.add(exitButton);
    menu.setBackground(new Color(30, 90, 60));

    drawArea = new DrawArea();
    drawArea.setBackground(Color.red);
    drawArea.setOpaque(true);
    drawArea.addMouseMotionListener(this);

    frame.getContentPane().add(menu, BorderLayout.NORTH);
    frame.getContentPane().add(drawArea, BorderLayout.CENTER);

    Thread pt = new Thread(new Painter());
    frame.setVisible(true);
    pt.start();

Please tell me I did something really stupid. Otherwise this looks like a really annoying bug. I really appreciate your help. Thanks!

Community
  • 1
  • 1
ICoffeeConsumer
  • 882
  • 1
  • 8
  • 22

1 Answers1

5

Your DrawPanel.paintComponent() method should chain upward to the method it overrides from JPanel to allow default painting to occur. Simply add

super.paintComponent(g);

As the first line to this method.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • If I call super.paintComponent(g), the problem goes away (and drawArea.setBackground(color) actually works!) but the function called on super (a new keyword for me) basically repaints the drawArea so the paint trail is no longer saved. It acts just like it would if I wrote `g.fillRect(...); // size of screen` – ICoffeeConsumer Dec 08 '12 at 01:08
  • 1
    In java, classes inherit from parent classes as you may know. The super command refers to the parent class. just like you would use `this.somethingOrOther();` to have an object call its own method, you can use `super.somethingOrOther();` to call your class's parents' version of the method. – Sam Hazleton Dec 08 '12 at 01:18
  • 1
    @AlexReidy You need to save the ovals in some way, such as with a List, so that you can redraw them as needed. In fact, you need to do this anyway to solve another problem: what happens if the user opens another window on top of your paint program and then switches back to your paint program later? I suspect the "paint trail" doesn't redraw in this situation with your current code. – Code-Apprentice Dec 08 '12 at 01:24
  • @Code-Guru You're right about the window thing - it disappears. Once I can get this working to some degree I plan on making this a LAN drawing program so it will require that I use some sort of array/list as a buffer anyway. Thanks. – ICoffeeConsumer Dec 08 '12 at 01:27
  • @AlexReidy With that in mind, I strongly suggest that you design some kind of data structure to store the elements which appear on the screen. To start, a simple List will work. Eventually, you may need to use something more complex depending on what other kinds of drawing tools you want to provide. – Code-Apprentice Dec 09 '12 at 20:05