我正在制作分子设计应用程序。我可以绘制线条和圆圈,但每次单击时它都会清除旧线条,所以基本上,你只能设计具有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) {}
}
所有帮助表示赞赏!
答案 0 :(得分:4)
1)绘制BufferedImage然后显示在paintComponent
覆盖内部,或者2)将数据放入ArrayList或其他集合中,然后遍历paintComponent
内的集合。如果我将数据用于其他目的,我会做后者。此外,永远不要这样做:
public void update(Graphics g) {
paintComponent(g);
}
这不是Swing图形应该如何完成的,而且是潜在危险的代码。请阅读:
修改强>
关于选项1的更多细节:
getGraphics()
或createGrahpics()
(对于Graphics2D对象)从BufferedImage获取Graphics对象dispose()
图形对象。repaint()
让JVM重新绘制组件。paintComponent
,在您的g.drawImage(...)
方法中绘制图像,并传入缓冲的图像。好处:通常绘图更快,我经常使用它来绘制背景图像 缺点:数据点不可用,因此如果您需要对数据点进行操作或动画,这不是可行的方法。
答案 1 :(得分:3)
你没有,也不应该。
Swing中的 paint
是一个破坏性的过程,这就是它的设计方式。也就是说,期望当您要求组件绘制自己时,它会在绘制任何内容之前清理Graphics
上下文(尽管透明组件略有不同)。
Swing没有关于组件之前绘制的内容的概念,因为Graphics
上下文是在绘制的所有组件之间共享的,除非您先清除图形,否则最终会出现不需要的绘制工件
可能的解决方案可能包括......
BufferedImage
),使用paintComponent
方法绘制。这是有限的,因为它只是一个绘画程序,为图像绘制像素。当可见区域的大小发生变化时,您还需要提供功能,因为BufferedImage
将不知道。List
并在调用paintComponent
时迭代此列表。这更灵活一点,你可以控制绘制对象的顺序,删除对象并在你喜欢的地方插入新对象