保持绘制图形 – 删除super.paintComponent

我有一个名为Foo的类,它扩展了一个名为Bar的类,它扩展了JPanel并实现了ActionListener。 当我选择Circle并单击绘制按钮时,我绘制一个圆,当我按下矩形并单击绘制时,它会删除以前的形状并绘制一个矩形。

但是,我想在JPanel上保留所有形状,直到我选择单击“删除”按钮。 所以我删除了super.paintComponent(g)并且它可以工作,但它也会导致类Bar的按钮以一种小故障的方式重新出现。 如何再次停止绘画按钮? 我想不要扩展Bar并让Foo扩展JPanel。

  public class Bar extends JPanel implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getActionCommand() == "Draw") { this.requestDraw = true; repaint(); } if (e.getActionCommand() == "Circle") { requestRectangle = false; requestTriangle = false; requestCircle = true; } if (e.getActionCommand() == "Rectangle") { requestCircle = false; requestTriangle = false; requestRectangle = true; } if (e.getActionCommand() == "Right Triangle") { requestCircle = false; requestRectangle = false; requestTriangle = true; } } public class Foo extends Bar { @Override public void paintComponent(Graphics g) { //super.paintComponent(g); if(RequestDraw()) { if(RequestCircle()) circle.draw(g); if(RequestRectangle()) rectangle.draw(g); if(RequestTriangle()) rightTriangle.draw(g); } if(!RequestDraw()) { g.setColor(getBackground()); g.fillRect(0,0,getWidth(), getHeight()); } } } } 

在此处输入图像描述

建议:

  • 不要删除super.paintComponent(g)因为它具有必要的重要作用。
  • 相反,为什么不绘制到BufferedImage,然后在paintComponent(...)方法中覆盖BufferedImage。
  • 然后,如果要删除绘制的图像,只需创建一个新的BufferedImage,或绘制它。

顺便说一句,不要使用==比较字符串。 请改用equals(...)equalsIgnoreCase(...)方法。 理解==检查两个对象是否相同而不是你感兴趣的。另一方面,这些方法检查两个字符串是否具有相同顺序的相同字符,这就是重要的。 而不是

 if (fu == "bar") { // do something } 

做,

 if ("bar".equals(fu)) { // do something } 

要么,

 if ("bar".equalsIgnoreCase(fu)) { // do something } 

伴随着Hovercraft的所有评论

Graphics上下文在组件之间共享。 super.paintComponent的任务之一是在绘制之前“清理”图形上下文。

这就是为什么你看到两个版本的按钮…

我也会做很多不同的事情。 这应该有助于延长性和重用性,并且还可以减少逻辑。

我会…

  • 将形状抽象为具有最低要求的基本“形状”类,例如填充和描边颜色,位置,大小,笔划等,并且知道如何绘制自身。
  • 我会创建一种允许您分离和定义责任范围的模型。 组件的责任不是“管理”形状,它只关心在它们的表面上绘制它们。 同样,该组件并不关心“形状”是什么,它只想知道它们是如何被绘制的……
  • 我会使用Action来简单地创建这些形状并将它们添加到模型中……

在此处输入图像描述

我只创建了一个三角形形状(它没有超出位置和大小的属性),但我相信你会得到一般的想法…(ps你需要为动作提供你自己的三角形图标;))

 public class DrawMe { public static void main(String[] args) { new DrawMe(); } public DrawMe() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); DrawModel model = new DefaultDrawModel(); model.addElement(new Triangle(new Rectangle(10, 10, 100, 100))); DrawPane drawPane = new DrawPane(model); JToolBar toolBar = new JToolBar(); toolBar.add(new AddTriangleAction(model)); frame.add(toolBar, BorderLayout.NORTH); frame.add(drawPane); frame.setSize(400, 400); frame.setVisible(true); } }); } /** * Simple action used to add triangles to the model...the model acts * as a bridge between the action and the UI. */ protected class AddTriangleAction extends AbstractAction { private DrawModel model; public AddTriangleAction(DrawModel model) { // Supply your own icon putValue(SMALL_ICON, new ImageIcon(getClass().getResource("/shape_triangle.png"))); this.model = model; } public DrawModel getModel() { return model; } @Override public void actionPerformed(ActionEvent e) { // Randomly add the triangles... int x = (int)(Math.random() * 400); int y = (int)(Math.random() * 400); model.addElement(new Triangle(new Rectangle(x, y, 100, 100))); } } /** * This is the background pane, from which the draw pane extends... */ protected class BackgroundPane extends JPanel { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); int x = getWidth() / 2; int y = getHeight() / 2; Graphics2D g2d = (Graphics2D) g.create(); RadialGradientPaint rgp = new RadialGradientPaint( new Point(x, y), Math.max(getWidth(), getHeight()), new float[]{0f, 1f}, new Color[]{Color.GRAY, Color.WHITE} ); g2d.setPaint(rgp); g2d.fill(new Rectangle(0, 0, getWidth(), getHeight())); g2d.setBackground(Color.BLACK); g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1); g2d.dispose(); } } /** * This is a simple model, I stole the list model because it was quicker * and easier to demonstrate (don't need to write all the listeners) */ public interface DrawModel extends ListModel { public void addElement(DrawMeShape shape); public void removeElement(DrawMeShape shape); } /** * A default implementation of the DrawModel... */ public class DefaultDrawModel extends DefaultListModel implements DrawModel { @Override public void removeElement(DrawMeShape shape) { removeElement((Object)shape); } } /** * The actually "canvas" that shapes are rendered to */ protected class DrawPane extends BackgroundPane { // Should provide ability to setModel... private DrawModel model; public DrawPane(DrawModel model) { this.model = model; model.addListDataListener(new ListDataListener() { @Override public void intervalAdded(ListDataEvent e) { repaint(); } @Override public void intervalRemoved(ListDataEvent e) { repaint(); } @Override public void contentsChanged(ListDataEvent e) { repaint(); } }); } public DrawModel getModel() { return model; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // Draw the shapes from the model... Graphics2D g2d = (Graphics2D) g.create(); DrawModel model = getModel(); for (int index = 0; index < model.getSize(); index++) { DrawMeShape shape = model.getElementAt(index); shape.paint(g2d, this); } g2d.dispose(); } } /** * A abstract concept of a shape. Personally, if I was doing it, I would * generate an interface first, but this is just a proof of concept... */ public abstract class DrawMeShape { private Rectangle bounds; public void setBounds(Rectangle bounds) { this.bounds = bounds; } public Rectangle getBounds() { return bounds; } protected abstract Shape getShape(); /** * The shape knows how to paint, but it needs to know what to paint... * @param g2d * @param parent */ public void paint(Graphics2D g2d, JComponent parent) { g2d = (Graphics2D) g2d.create(); Rectangle bounds = getBounds(); Shape shape = getShape(); g2d.translate(bounds.x, bounds.y); g2d.setColor(Color.DARK_GRAY); g2d.fill(shape); g2d.setColor(Color.BLACK); g2d.draw(shape); g2d.dispose(); } } /** * An implementation of a Triangle shape... */ public class Triangle extends DrawMeShape { public Triangle(Rectangle bounds) { setBounds(bounds); } @Override protected Shape getShape() { // This should be cached ;) Path2D path = new Path2D.Float(); Rectangle bounds = getBounds(); path.moveTo(bounds.width / 2, 0); path.lineTo(bounds.width, bounds.height); path.lineTo(0, bounds.height); path.lineTo(bounds.width / 2, 0); path.closePath(); return path; } } } 

快乐的画...