【问题标题】:Paint Panel Incorrect Rendering油漆面板不正确的渲染
【发布时间】:2015-06-13 19:31:28
【问题描述】:

这是怎么回事:

我想制作一个非常基本的绘图程序来练习使用绘图方法、处理图形、使用工具栏等等。我一直在阅读大量关于如何做这些事情的文章,我确信我在某处遗漏了重要的代码行,因为paintpanel 本身正在渲染一个不应该存在的 JMenu。我有一个使用 actionListeners 设置的 JMenu,但呈现为额外的 JMenu 不执行任何操作并且无法与之交互。这是一张图片:

如下图所示,我可以在菜单上绘画,但它仍然没有任何反应。另外,这次你可以看到程序中前一个窗口中的随机按钮是出于某种原因添加的。

这是该按钮的来源:

我不知道如何解决这个问题,所以这里是相关类的代码:

这是进行绘画的面板。 包装画家;

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;

    static Color currentColor = Color.black;

    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.
    @Override
    public void paintComponent(Graphics g)
    {
        // super.paintComponent(g);
         g.setColor(currentColor);
         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

    }
    public static void changeColor(Color color)
    {
        currentColor = color;
    }
}

这是添加到 PaintPanel、菜单和稍后的其他按钮等的主类。

package painter;

import java.awt.BorderLayout;

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

import painter.menu.FileMenu;
import painter.menu.ToolsMenu;

@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());
        menuBar.add(new ToolsMenu());

        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);
    }
}

这两个类应该是唯一与当前问题相关的类,但是如果需要其他类,请告诉我。我只是不想用无用的信息把帖子弄得乱七八糟。

现在,这是我已经尝试过的:

正如您在 PaintPanel 类中看到的,我添加了一个 super.paintComponent(g);方法调用。然而,虽然这完全解决了我的问题,但它一次只绘制一个黑色方块。我可以想象,因为它会用绘画调用覆盖面板,然后在每次调用 repaint 时绘制正方形。

这是一张添加了 super.paintComponent(g) 的照片:

我不确定这是否重要,但我使用的是 Windows 10。

感谢您提供的任何帮助。

【问题讨论】:

  • 您没有调用 super.paintComponent 方法,而是将其注释掉——这是危险的代码,不应该这样做。如果您希望图像保持不变,请将 Points 放入 ArrayList 并在您的paintComponent 中绘制点的 ArrayList。要么绘制到 BufferedImage,然后在 paintComponent 方法中绘制它。并且总是调用super的paintComponent方法。
  • Custom Painting Approaches 有一些工作示例,向您展示如何使用上面建议的ListBufferedImage 来持续绘画。
  • @HovercraftFullOfEels 我在测试时注释掉了 super.paintComponent(g)。

标签: java swing graphics jpanel paintcomponent


【解决方案1】:

我认为您需要致电 .repaint() 以减少您的 UI 故障。

【讨论】:

  • 我的代码中实际上有。如果我从不调用 repaint () 它不会绘制任何东西。
  • 至少它不在您提供的代码中,除了一键式处理程序。您应该在更改 UI 后调用它。
最近更新 更多