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

2023-12-13

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

但是,我想保留 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());
            }        
        }
    }
}

enter image description here


除了所有气垫船评论之外

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

这就是为什么您会看到两个版本的按钮......

我也会做一些不同的事情。随着时间的推移,这应该有助于可扩展性和重用,并且还可以稍微减少逻辑。

我会...

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

enter image description here

我只创建了一个三角形(除了位置和大小之外,它没有任何属性),但我相信您会得到总体想法...(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<DrawMeShape> {
        public void addElement(DrawMeShape shape);
        public void removeElement(DrawMeShape shape);
    }

    /**
     * A default implementation of the DrawModel...
     */
    public class DefaultDrawModel extends DefaultListModel<DrawMeShape> 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;
        }
    }
}

祝画画愉快...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

保持绘制图形 - 删除 super.paintComponent 的相关文章

随机推荐

  • Smarty 正则表达式匹配

    我有一个 smarty 变量 我想知道它是否与某些字符串匹配
  • Windows 应用商店应用程序中的 HtmlAgilityPack

    因此 我在控制台应用程序中有一些工作测试代码 我将其转移到 Windows 应用商店应用程序 现在的问题是 我刚刚复制了控制台应用程序中的 HtmlAgilityPack 代码 但现在它不起作用 我确实有 HtmlAgilityPack 作
  • 在 Android API 中调用私有(未发布)方法

    我需要检查当前在 OS 2 0 2 3 中连接了哪些 BT 耳机 不仅仅是配对 此类功能直到 API 版本 11 才出现 其中引入了蓝牙耳机类 但之前的 API 中已经存在一个名为 BluetoothHeadset 的类 但它无法公开访问
  • 如何将 wav 文件填充到特定长度?

    我正在使用波形文件来制作深度学习模型 它们的长度不同 所以我想全部填充 使用 python 达到 16 秒长度 如果我理解正确 问题是将所有长度固定为给定长度 因此 解决方案会略有不同 from pydub import AudioSegm
  • 未定义模板的隐式实例化:Boost Bug 还是 Clang Bug?

    我试图编译一些使用 Boost 1 49 的代码 并使用 trunk 中的 Clang libc 有问题的代码归结为以下内容 include
  • .NET 数据绑定的跨线程问题

    我有许多 Windows 窗体控件 用于与我的程序对象交互 目前 他们订阅对象上的 已更新 事件 并在需要时手动更新值 我想使用数据绑定替换所有 或尽可能多 的样板代码 我遇到的问题是对象状态可以随时被多个不同线程中的任何一个修改 目前我使
  • 基于 R 中不同数据帧的值进行子集化

    如果行中的每个值都大于不同数据框中的相应行 我想对数据进行子集化 我还需要跳过一些顶行 前面的这些问题对我没有帮助 但它是相关的 根据另一个数据帧的内容对数据帧进行子集化 使用来自不同数据帧的信息的数据子集 r gt A name1 nam
  • Propagation.REQUIRES_NEW 导致 LockWaitTimeOutException

    有两个函数 A 和 B 它们是用 Transactional 注解定义的 我从 A 给 B 打电话 Transactional value Constants READ WRITE REQUEST public int A B Transa
  • 将 stargazer 与 Zelig 结合使用

    我正在尝试使用 stargazer 版本 5 2 输出使用 Zelig 版本 5 0 13 估计的回归的标准摘要 结果 但是 我得到了错误 Error in envRefInferField x what getClass class x
  • 无法在 python 上找到图像

    我尝试在屏幕上找到图像 但它总是表明这一点 Traceback most recent call last File C Users MerazulIslam Desktop ZOOM BOT bot py line 20 in
  • 计算mysql中最后一行的总持续时间

    我有这个 mysql 查询 SELECT CONCAT u lastname u firstname AS Name start timestamp start end timestamp end timediff end timestam
  • 使用 matplotlib 在 Tkinter 中绘制数据 - 在列表之间切换

    我正在创建一个程序 利用Tkinter and matplotlib 我有 2 个列表列表 一个用于 x 轴 一个用于 y 轴 我希望有一个可以在列表中的列表之间切换的按钮 我从问题中获取了大部分代码基于Tkinter和matplotlib
  • 检测本地和远程之间不同步的所有标签

    有没有一种简单的方法可以确定本地存储库中哪些标签与远程不同步 不同步是指完全相同的标签名称指向本地与远程上的不同提交 我能想到的两种导致这种情况的方法可能是 有人 或某物 移动了我之前获取的标签 也许它被删除并重新创建 或者它是在它已经存在
  • 将 Java 代码与烘焙到 .jar 中的数据一起传送

    我需要发送一些具有关联数据集的 Java 代码 它是一个设备模拟器 我希望能够将用于模拟记录的所有数据包含在一个 JAR 文件中 在这种情况下 每个模拟记录包含四个字段 主叫方 被叫方 呼叫开始 呼叫持续时间 最好的方法是什么 我已经沿着以
  • 比较 ReadOnlyMemory 实例的最佳方法?

    The ReadOnlyMemory
  • 显示/隐藏 div,使用纯 JS

    My CSS a x200 visibility hidden width 200px height 200px background color black My JS 我的HTML div asd div
  • 如何将像素转换为 xamarin.forms 单位?

    每英寸有 160 个单位 2 如果我创建了一个Photoshop文件为 72dpi那么每英寸就有 72 个点 3 如果元素是88px身高在Photoshop那么我必须将其设置为xamarin 如果手机是 360dpi 那么 xamarin
  • 将双精度型转换为整型?

    我的代码如下 int main int argc char argv double f 18 40 printf d n int 10 f return 0 在VC6 0中结果是184 而Codeblock中结果是183 为什么呢 原因是
  • Symfony 任务 - 内存泄漏

    我编写了一个 symfony 任务来填充示例数据的数据库 这是一段示例代码 gc enable Propel disableInstancePooling public function test for i 0 i lt 10000 i
  • 保持绘制图形 - 删除 super.paintComponent

    我有一个名为 Foo 的类 它扩展了一个名为 Bar 的类 该类扩展了 JPanel 并实现了 ActionListener 当我选择圆形并单击绘制按钮时 我会绘制一个圆形 而当我按矩形并单击绘制时 它会擦除 以前的形状并绘制一个矩形 但是