Программа для рисования дублирует JMenuBar

Я написал простую программу рисования на Java, которая позволяет пользователю выбирать между различными формами, размерами и цветами (в JMenuBar) и рисовать их с помощью мыши. После преодоления многих проблем с программой (изначально я написал ее в AWT, но был убежден переключиться на Swing, так что извините за плохое Swing кодирование, потому что я впервые использовал его), мне осталось решить одну проблему. Когда пользователь что-то рисует на экране (по умолчанию красный прямоугольник с черной рамкой), JMenuBar дублируется прямо под исходным JMenuBar. Я полагаю, что это что-то странное с тем, как paintComponent буферизует экран, но, поскольку я никогда не использовал его раньше, я понятия не имею, как это работает.

Есть идеи, как я могу заставить его перестать дублировать JMenuBar?

import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import javax.swing.*;

public class E3G04 extends JFrame implements WindowListener, ActionListener, MouseListener, MouseMotionListener
{
    //Variables are declared as volatile to ensure that they're always called from system RAM
    static volatile String type = "rectangle";
    static volatile Boolean fill = true;
    static Color lineColor = Color.BLACK;
    static Color fillColor = Color.RED;
    static int size = 1;

    CanvasEX cx = new CanvasEX();

    static boolean running = true;

    JMenuBar mb = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
            JMenuItem newItem = new JMenuItem("New");
            JMenuItem quitItem = new JMenuItem ("Quit");


    protected E3G04()
    {

        mb.add(fileMenu);
        fileMenu.add(newItem);
        fileMenu.add(quitItem);             
        newItem.setMnemonic('N');
        quitItem.setMnemonic('Q');
        newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
        quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));          
        newItem.addActionListener(this);
        quitItem.addActionListener(this);
        cx.setSize(800,600);
        cx.addMouseListener(this);
        cx.addMouseMotionListener(this);
        setJMenuBar(mb);
        setBounds(100,100,800,600);
        setLayout(new BorderLayout());
        add("Center",cx);
        addWindowListener(this);
        setResizable(true);
        setVisible(true);
    }

    public static void main(String [] args)
    {
        new E3G04();
    }


    public void stop()
    {
        newItem.removeActionListener(this);
        quitItem.removeActionListener(this);    
        dispose();
        System.exit(0);
    }

    public void actionPerformed(ActionEvent e)
    {
        Object o = e.getSource();

        if (o == newItem)
        {
            cx.erase = true;
            cx.repaint();
        }

        if (o == quitItem)
        {   
            running = false;
            stop();
        }

    }      

    public void mousePressed(MouseEvent m)
    {
        cx.start = m.getPoint();
        cx.end = cx.start;
        cx.cur = cx.start;
    }

    public void mouseDragged(MouseEvent m)
    {
        cx.cur = m.getPoint();
    }   

    public void mouseReleased(MouseEvent m)
    {
        cx.end = cx.cur;
        cx.repaint();
    }   
    public void itemStateChanged(ItemEvent e)
    {
        Object o = e.getSource();

    }
    public void windowClosing(WindowEvent e)
    {
        running = false;
        stop();
    }
    public void mouseClicked(MouseEvent m){}    
    public void mouseExited(MouseEvent m){}
    public void mouseEntered(MouseEvent m){}    
    public void mouseMoved(MouseEvent m){}
    public void windowClosed(WindowEvent e){}
    public void windowOpened(WindowEvent e){}
    public void windowActivated(WindowEvent e){}
    public void windowDeactivated(WindowEvent e){}
    public void windowIconified(WindowEvent e){}
    public void windowDeiconified(WindowEvent e){}
}


class CanvasEX extends JPanel
{
    Point start = new Point(100,100);
    Point cur = new Point(100,100);
    Point end = new Point(100,100);
    boolean erase = false;



    public void paintComponent(Graphics g)
    {

        Graphics buffer = g;
        if (erase)
        {
            g.dispose();
            erase = false;
        }   
        g.setColor(E3G04.lineColor);
        if (end.x > start.x && end.y > start.y)
            g.fillRect(start.x,start.y, Math.abs(end.x-start.x),Math.abs(end.y-start.y));
        if (end.x > start.x && end.y < start.y)
            g.fillRect(start.x,end.y, Math.abs(end.x-start.x),Math.abs(end.y-start.y));  
        if (end.x < start.x && end.y > start.y)
            g.fillRect(end.x, start.y, Math.abs(end.x-start.x),Math.abs(end.y-start.y));
        if (end.x < start.x && end.y < start.y)
            g.fillRect(end.x, end.y, Math.abs(end.x-start.x),Math.abs(end.y-start.y));
        g.setColor(E3G04.fillColor);
        if (end.x > start.x && end.y > start.y)
            g.fillRect(start.x + E3G04.size,start.y + E3G04.size, Math.abs(end.x-start.x) - 2 * E3G04.size,Math.abs(end.y-start.y) - 2 * E3G04.size);
        if (end.x > start.x && end.y < start.y)
            g.fillRect(start.x + E3G04.size,end.y + E3G04.size, Math.abs(end.x-start.x) - 2 * E3G04.size,Math.abs(end.y-start.y) - 2 * E3G04.size);  
        if (end.x < start.x && end.y > start.y)
            g.fillRect(end.x + E3G04.size, start.y + E3G04.size, Math.abs(end.x-start.x) - 2 * E3G04.size,Math.abs(end.y-start.y) - 2 * E3G04.size);
        if (end.x < start.x && end.y < start.y)
            g.fillRect(end.x + E3G04.size, end.y + E3G04.size, Math.abs(end.x-start.x) - 2 * E3G04.size,Math.abs(end.y-start.y) - 2 * E3G04.size);          
    }
}

person Alex Kibler    schedule 10.12.2012    source источник


Ответы (1)


Вы не соблюдаете цепочку рисования (что вам следует), вызывая super.paintComponent(Graphics g) в методе overriden paintComponent(..):

@Override
public void paintComponent(Graphics g)
{
     super.paintComponent(g);

    //do rest of painting etc
}  
person David Kroukamp    schedule 10.12.2012
comment
Хорошо, хорошо, это устранило проблему с существованием строки меню, но теперь мои рисунки не сохраняются. Как мне это исправить? - person Alex Kibler; 10.12.2012
comment
Вам нужно что-то вроде ArrayList, которое будет содержать все Rectanlges для рисования, а в paintComponent вы должны перебирать список массивов и перерисовывать каждый Rectangle, таким образом рисунки будут сохраняться. - person David Kroukamp; 10.12.2012
comment
Однако это не все прямоугольники. Разве нет способа создать изображение экрана (без JMenubar), а затем снова нарисовать это изображение на экране? - person Alex Kibler; 10.12.2012
comment
@AlexKibler Я уверен, что вы могли бы, но это был бы неправильный путь, вам просто нужно иметь больше списков массивов для хранения всех объектов или использования дженериков (каждый класс будет расширять класс Entity, который имеет такие основы, как x, y, ширина, высота и т. Д. ), поэтому в один и тот же список могут быть добавлены разные объекты. вот небольшой пример постоянных прямоугольников: stackoverflow.com/questions/13358658/ - person David Kroukamp; 10.12.2012
comment
Ладно, тогда я сделаю это. Спасибо! - person Alex Kibler; 10.12.2012