【问题标题】:How to prevent the JPanel from being updated?如何防止 JPanel 被更新?
【发布时间】:2015-05-14 11:53:21
【问题描述】:

我正在创建一种绘画应用程序。用户可以通过按下/拖动鼠标在 JPanel 中移动一个圆圈。

我的JMenus 中有一个JCheckBoxMenuItem

JCheckBoxMenuItem checkitem = new JCheckBoxMenuItem("Draw mode",false);
  • 未激活时,只能移动圆圈(通过拖/按),前一个圆圈将被删除。
  • 激活时,圆圈只能移动,但前一个圆圈不会在鼠标拖/按时被删除(这与绘画程序的工作方式相同)

我的代码的缩短版本:

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

class GUI extends JFrame implements MouseListener, MouseMotionListener, ActionListener, ItemListener
{
    JPanel mainPan, colorPan;
    Color color = Color.BLACK;
    JCheckBoxMenuItem checkitem;
    boolean clear = true;

    public GUI(String header)
    {
        maker();

        mainPan.addMouseListener(this);
        mainPan.addMouseMotionListener(this);

        add(mainPan , BorderLayout.CENTER);
        add(colorPan, BorderLayout.PAGE_END); 
    }

    public void maker()
    {
        colorPan = new JPanel();
        colorPan.setLayout(new GridLayout(1, 0));

        mainPan = new JPanel(){
            @Override
            public void paintComponent(Graphics g)
            {
                //g.setColor(Color.WHITE);
                //g.fillRect(0,0,getWidth(),getHeight());
                if(clear)
                    super.paintComponent(g); //Do the same thing as above(Clear JPanel)

                g.setColor(color);
                g.fillOval(x,y,50,50); //x and y are integer variables that I use in my full program
            }
        };

        checkitem = new JCheckBoxMenuItem("Draw mode",false);
        //After adding this to a JMenu,
        checkitem.addItemListener(this);
    }

    public void itemStateChanged(ItemEvent e)
    {
        if(e.getStateChange() == ItemEvent.SELECTED)
        {
            clear = false;
        }
        else
        {
            clear = true;
        }
    }
}

下面的截图显示了我的完整程序的输出:

colorPan 是 JPanel,里面装满了不同颜色的 JButton。最上面是mainPan

目前,“绘图模式”无法按预期工作。我一直认为super.paintComponent(g); 是在调用repaint() 时清除/重置屏幕的那个。但我删除了它,看到程序的行为方式相同,我感到非常惊讶。

基本上,我的问题就在这里:

if(clear)
    super.paintComponent(g);

我需要防止在调用repaint() 时清除所有内容。我如何实现我想要的?

【问题讨论】:

标签: java swing graphics jpanel


【解决方案1】:

不应在此代码中进行更改。并且应该改变的不是绘画方法。在您或系统需要时涂漆。当窗口被调整大小或移动或部分覆盖时 - 它使用油漆再次绘制图片。 您真正应该做的是停止更新您绘制的椭圆的坐标。它可以在鼠标侦听器或坐标设置器中完成,或者更好的是,在管理这些坐标的控制部分中完成。您的复选框应该控制更改模型的能力。它不应该控制绘画。 有常用的模式Model-View-Controller - 看看吧。对于这么小的应用程序来说,它可能看起来有点矫枉过正,但即使是 Swing 本身也是建立在这种模式之上的,所以你已经遵循了它。当你试图打破它时,问题就会出现。所以 - 不要。

【讨论】:

  • "你真正应该做的是停止更新你绘制的椭圆的坐标" -- 无论复选框是否被激活,圆都应该更新。当它被激活时,不应该删除以前绘制的圆圈。并且当它没有被激活时,应该删除以前的圆圈图(即使复选框被激活,现在也会发生这种情况)
  • 不要将paint() 视为一次绘制。它被大量调用。要查看它 - 将其他一些窗口拖到您的应用程序上。它会迫使油漆画很多次,你会看到的。
  • 嗯。这是有道理的。
【解决方案2】:

不能“阻止JPanel被更新;” paintComponent() 将根据系统要求异步调用。取而代之的是,以允许您的paintComponent() 实现每当调用它时呈现所有内容的方式来调节视图类的属性。

在下面的示例中,每次单击鼠标都会更改前景色,paintComponent() 使用修改后的设置。在引用here 的更详细的示例中,ClearAction 清除了定义图模型的List<Node>List<Edge>。如果没有对 super.paintComponent(g) 的调用,否则 opaque 组件需要调用,在 paintComponent() 中调用 fillRect() 会清除所有剩余的选择工件。

public void actionPerformed(ActionEvent e) {
    nodes.clear();
    edges.clear();
    repaint();
}

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

/** @see https://stackoverflow.com/a/5312702/230513 */
public class MouseDragTest extends JPanel {

    private static final String TITLE = "Drag me!";
    private static final Random r = new Random();
    private static final int W = 640;
    private static final int H = 480;
    private Point textPt = new Point(W / 2, H / 2);
    private Point mousePt;
    private Color color = Color.black;

    public MouseDragTest() {
        this.setFont(new Font("Serif", Font.ITALIC + Font.BOLD, 32));
        this.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                mousePt = e.getPoint();
                setColor(Color.getHSBColor(r.nextFloat(), 1, 1));
                repaint();
            }
        });
        this.addMouseMotionListener(new MouseMotionAdapter() {

            @Override
            public void mouseDragged(MouseEvent e) {
                int dx = e.getX() - mousePt.x;
                int dy = e.getY() - mousePt.y;
                textPt.setLocation(textPt.x + dx, textPt.y + dy);
                mousePt = e.getPoint();
                repaint();
            }
        });
    }

    public void setColor(Color color) {
        this.color = color;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(W, H);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(color);
        int w2 = g.getFontMetrics().stringWidth(TITLE) / 2;
        g.drawString(TITLE, textPt.x - w2, textPt.y);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame f = new JFrame(TITLE);
                f.add(new MouseDragTest());
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}

【讨论】:

  • 好的。我将研究示例程序。感谢您发布答案。
猜你喜欢
  • 1970-01-01
  • 2016-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-30
  • 1970-01-01
  • 2011-05-03
相关资源
最近更新 更多