【问题标题】:How to stop JComponent from clearing?如何阻止 JComponent 清除?
【发布时间】:2014-03-11 00:07:52
【问题描述】:

我正在制作一个分子设计应用程序。我可以画线和圆,但是每次点击它都会清除旧线,所以基本上,你只能设计2个原子的分子。 此外,如果您单击非常快,mouseEvents 也不会传递,这也是一个问题。 代码如下:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;
public class MoleculeDesigner extends JComponent implements MouseListener {
    private Point op, cp;
    private boolean first = true;
    public static final Color linecolor = new Color(0, 255, 0);
    private static final long serialVersionUID = 1L;
    private BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
    public MoleculeDesigner() {
        JFrame f = new JFrame("Molecule Designer");
        f.setBackground(Color.WHITE);
        f.addMouseListener(this);
        f.add(this);
        f.setSize(100, 100);
        f.setDefaultCloseOperation(3);
        f.setVisible(true);
    }
    public static void main(String[] args) {
        new MoleculeDesigner();
    }
    @Override
    protected void paintComponent(Graphics g) {
        if(op != null && cp != null) {
            Graphics2D g2 = img.createGraphics();
            super.paintComponent(g2);
            g2.setColor(linecolor);
            g2.drawLine((int) op.getX(), (int) op.getY(), (int) cp.getX(), (int) cp.getY());
            g2.setColor(Color.BLACK);
            g2.fillOval((int) cp.getX(), (int) cp.getY(), 10, 10);
            op = (Point) cp.clone();
            g2.dispose();
        }
    }
    @Override
    public Dimension getPreferredSize() {
        return getParent().getMaximumSize();
    }
    @Override
    public void mouseClicked(MouseEvent e) {
        if(!first) {
            cp = e.getPoint();
            cp.setLocation(cp.getX(), cp.getY() - 8);
        }
        else {
            op = e.getPoint();
            first = false;
        }
        repaint();
    }
    @Override public void mousePressed(MouseEvent e) {}
    @Override public void mouseReleased(MouseEvent e) {}
    @Override public void mouseEntered(MouseEvent e) {}
    @Override public void mouseExited(MouseEvent e) {}
}

感谢所有帮助!

【问题讨论】:

标签: java swing mouseevent paintcomponent repaint


【解决方案1】:

要么 1) 绘制一个 BufferedImage,然后将其显示在您的 paintComponent 覆盖内,或者 2) 将您的数据放入 ArrayList 或其他集合中,然后遍历 paintComponent 内的集合。如果我需要将数据用于其他目的,我会做后者。另外,永远不要这样做:

public void update(Graphics g) {
    paintComponent(g);
}

这不是 Swing 图形应该如何完成的,并且是潜在的危险代码。请阅读:


编辑
有关选项 1 的更多详细信息:

  • 使用其构造函数之一创建 BufferedImage。
  • 在图像上绘图。
    • 当您需要绘图时,使用getGraphics()createGrahpics()(对于 Graphics2D 对象)从 BufferedImage 中获取一个 Graphics 对象
    • 使用此 Graphics 对象绘图
    • 然后dispose() Graphics 对象。
  • 然后调用repaint()请求JVM重绘组件。
  • 通过调用g.drawImage(...),在您的paintComponent 方法中绘制图像,并传入您的缓冲图像。

好处:通常绘图速度更快,我经常用它来绘制背景图像。
缺点:数据点不可用,因此如果您需要对数据点进行操作或动画处理,这不是可行的方法。

【讨论】:

  • 好的,我删除了更新,使用了选项#1,但我不知道如何执行选项#1...请详细一点。
  • @HovercraftFullOfEels 好的。完成!
  • @JavaIsCool:太好了。现在也请投票给 MadProgrammer 的好建议答案。
  • 抱歉,我不能,因为我的声望低于 15。 @MadProgrammer 对不起!
【解决方案2】:

你不知道,也不应该。

paint 在 Swing 中是一个破坏性的过程,这就是它的设计方式。也就是说,当您的组件被请求绘制自身时,它会在绘制任何内容之前清理Graphics 上下文(尽管这对于透明组件略有不同)。

Swing 不知道之前在您的组件上绘制了什么,因为 Graphics 上下文在所有已绘制的组件之间共享,除非您先清除图形,否则最终可能会出现不需要的绘制工件

可能的解决方案可能包括...

  1. 绘制到某种后备缓冲区(例如BufferedImage),您使用paintComponent 方法进行绘制。这是有限的,因为它就像一个绘画程序,将像素绘画到图像上。当可视区域的大小发生变化时,您还需要提供功能,因为BufferedImage 不会知道。
  2. 将您想要绘制的每个对象放入某种List 中,并在调用paintComponent 时迭代此列表。这更灵活一点,您可以控制绘制对象的顺序、删除对象并在您喜欢的位置插入新对象

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 2013-11-16
    • 2017-10-19
    • 2016-02-08
    • 1970-01-01
    • 1970-01-01
    • 2015-01-19
    • 2014-04-25
    相关资源
    最近更新 更多