Java JMenu错误地渲染两次

时间:2015-06-05 19:23:57

标签: java swing paint paintcomponent jmenu

感谢您提供的任何帮助。以下是我的问题概述:

我决定将脚趾浸入图形渲染的有趣水域,制作一个基本的“绘画”程序。这样做我想添加一个菜单栏,就像大多数程序一样。但是,此菜单栏呈现自身两次,一次在其工作且可点击的情况下,第二个仅是无法与之交互的重影图像。

这是我没有点击任何内容的程序图片:http://i.stack.imgur.com/i9wxd.png

这是在屏幕上更新任何内容之后: http://i.stack.imgur.com/NVZWB.png

带圆圈的“文件”按钮根本不起作用。然而,另一个确实如此。 我不知道为什么会发生这种情况,所以这里是我用来制作这个小程序的代码(请原谅这些评论,这些都是为了我自己的利益):

package painter;

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;

@SuppressWarnings("serial")
//This class will do the job of bringing together all the various sub-    classes and rendering everything.
public class MainPainterGUI extends JFrame
{
    private JPanel menuPanel;

    private JMenuBar menuBar;

    //These values are going to be used to set an initial window size.
    private final short WINDOW_HEIGHT = 1000;   
    private final short WINDOW_WIDTH = 1000;

    //This constructor will do the actual creation of the window.
    public MainPainterGUI()
    {
        //This does the same thing that setTitle does.
        super("Painter");
        //setTitle("Painter");

        //This method will set what the window is supposed to do when the red x is clicked.
        //Technically, the value passed is an integer.
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        //Obviously this method sets the initial size of the window.  It can be changed by the user however.
        setSize(WINDOW_WIDTH,WINDOW_HEIGHT);

        //This method sets the center of the window relative to whatever is passed.  In this case, null makes
        //the window appear in the center of the desktop regardless of the size.
        setLocationRelativeTo(null);

        menuPanel = new JPanel();

        menuBar = new JMenuBar();

        menuBar.add(new FileMenu());

        menuPanel.add(menuBar);

        //The add method simply attaches a component to whatever is calling, like a frame or another panel.
        //The BorderLayout is needed to use the draggable toolbar.
        add(new PaintPanel(), BorderLayout.CENTER);
        add(menuPanel, BorderLayout.NORTH);

        //This will allow the window to be seen.  Make sure this method is last, as if 
        //a component is created afterwards it may not be visible.
        setVisible(true);
    }
}

这是FileMenu类:

package painter;

import javax.swing.JMenu;
import javax.swing.JMenuItem;


public class FileMenu extends JMenu
{
    JMenuItem newFile, open, save, saveAs;

    public FileMenu()
    {
        super("File");

        newFile = new JMenuItem("New...");
        open = new JMenuItem("Open...");
        save = new JMenuItem("Save");
        saveAs = new JMenuItem("Save As...");

        add(newFile);
        add(open);
        addSeparator();
        add(save);
        add(saveAs);
    }

}

这是PaintPanel类:

package painter;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;

@SuppressWarnings("serial")
public class PaintPanel extends JPanel implements MouseInputListener
{
    //These two values will be used to determine where the mouse is and thus where to paint...stuff...
    public int xCoordinate, yCoordinate = -10;

    public PaintPanel()
    {
        //These two methods simply attaches the mouse listener methods listed below to the actual panel.
        addMouseListener(this);
        addMouseMotionListener(this);
    }
    //This method is an overwritten version of the default paint method.  It's job is to render custom graphics
    //objects on the screen.  The Graphics g argument is the item responsible for doing the actual rendering.
    public void paintComponent(Graphics g)
    {
         g.setColor(Color.black);
         g.fillRect(xCoordinate, yCoordinate, 10, 10);
    }

    @Override
    //This method, added because of the MouseInputListener implementation, is used when a user clicks the left mouse button.
    public void mouseClicked(MouseEvent e) 
    {
        xCoordinate = e.getX();
        yCoordinate = e.getY();
        repaint();
    }
    @Override
    public void mouseEntered(MouseEvent arg0) 
    {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent arg0)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent arg0) 
    {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent arg0) 
    {
        // TODO Auto-generated method stub

    }

    @Override
    //This method, added because of the MouseInputListener implementation, is used when a user presses and holds the
    //left mouse button while moving the mouse.
    public void mouseDragged(MouseEvent e) 
    {
        xCoordinate = e.getX();
        yCoordinate = e.getY();
        repaint();
    }

    @Override
    public void mouseMoved(MouseEvent arg0) 
    {
        // TODO Auto-generated method stub

    }
}

我尝试过添加“super.paintComponent(g);”到paintComponent()方法的开头,但是虽然这解决了问题,但它只会创建一个更糟糕的问题。它只是渲染一个黑色方块,跟随我的鼠标。

更新:只是为了帮助其他人,这里是我在撰写本文时建议和尝试过的内容摘要。

旁注 - 与此同时,我一直致力于该计划的其他部分,因此您可能会注意到顶部的“工具”菜单现在以前没有。但是,由于它根本不会影响当前的问题,因此无需提供更新的代码。

正如Andrew Thompson所建议的那样,将PaintPanel的paintComponent方法改为包含对super的paint方法的调用,结果如下:

@Override
public void paintComponent(Graphics g)
{
     super.paintComponent(g);
     g.setColor(currentColor);
     g.fillRect(xCoordinate, yCoordinate, 10, 10);
}

所有内容都正确渲染,除了现在所有的绘图都被删除,除了当前的单个黑色方块。 enter image description here

falijbour's(请参阅下面的答案,因为有很多变化)建议稍微好一点,除非需要更新面板(例如从最小化或文件菜单下降),它会删除绘制的进度。

这里有几张照片要说明:

这是初始图纸。 enter image description here

点击“文件”后 enter image description here

这是一个部分解决方案,但正如faljbour所阐明的那样,您需要保存像素的坐标并将其重绘在正在更新的窗口上。然而,除了单一颜色,笔大小,笔形和没有文字之外,其他任何东西都极具挑战性。

0 个答案:

没有答案