【问题标题】:How can I run background tasks with Swing?如何使用 Swing 运行后台任务?
【发布时间】:2017-04-24 03:46:21
【问题描述】:

我目前正在使用 Swing 组件制作某种“绘画”。 它只能绘制椭圆、矩形和直线。 问题是,每次我切换数字时,其他数字都不会保留在 JPanel 上。每个相同类型的图形都保留下来,例如: 如果我开始画线,它们会保留在 JPanel 中,直到我改变图形。 我正在绘制的每个图形都保存到我定义了以下属性的类中:

  • 起点
  • 最后一点
  • TypeOfFigure
  • OutLineColor
  • 填充颜色

并且该类的每个对象都保存到一个 ArrayList 中。 每次切换图形时如何重绘该数组列表的元素? 这是我的 draw() 方法

private void draw() {
        mMouseIsDragging = false;
        mMouseReleased = false;
        MyPanel.this.addMouseListener(new MouseAdapter() {
            private Coordenadas mDraw;
            @Override
            public void mousePressed(MouseEvent e) {
                mCoordenadas.add(new Coordenadas());
                mDraw = (Coordenadas) MyPanel.this.mCoordenadas.get(MyPanel.this.mCoordenadas.size() - 1);
                mDraw.setColor(mColorLinea);
                mDraw.setColorRelleno(mColorRelleno);
                mDraw.setTipo(mOpcion);
                mStartPoint = e.getPoint();
                mDraw.setFirstPoint(e.getPoint());
                mMouseIsDragging = true;
           }
            @Override
            public void mouseReleased(MouseEvent e) {
                mDraw = (Coordenadas) MyPanel.this.mCoordenadas.get(MyPanel.this.mCoordenadas.size() - 1);
                mPuntoFinal = e.getPoint();
                mDraw.setLastPoint(e.getPoint());
                mMouseReleased = true;
                mMouseIsDragging = false;
                repaint();
            }
        });
        MyPanel.this.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                mPuntoFinal = e.getPoint();
                mMouseReleased = false;
                mMouseIsDragging = true;
                repaint();
            }
        });
    }

这是绘制这些图形的paintComponent方法部分:

if (mMouseReleased == true && mMouseIsDragging == false) {
            for (int i = 0; i < mCoordenadas.size(); i++) {
                Coordenadas mCoord = (Coordenadas) mCoordenadas.get(i);
                switch (mCoord.getTipo()) {
                    case 1:
                        mG2D.setColor(mCoord.getColor());
                        mG2D.drawLine(mCoord.getFirstPoint().x, mCoord.getFirstPoint().y, mCoord.getLastPoint().x, mCoord.getLastPoint().y);
                        break;
                    case 2:
                        if (mCoord.getColorRelleno() != null) {
                            mG2D.setPaint(mCoord.getColorRelleno());
                            mG2D.fill(new Rectangle2D.Double(mCoord.getFirstPoint().x, mCoord.getFirstPoint().y, Math.abs(mCoord.getFirstPoint().x - mCoord.getLastPoint().x), Math.abs(mCoord.getFirstPoint().y - mCoord.getLastPoint().y)));
                        } else {
                            mG2D.setColor(mCoord.getColor());
                            mG2D.drawRect(mCoord.getFirstPoint().x, mCoord.getFirstPoint().y, Math.abs(mCoord.getFirstPoint().x - mCoord.getLastPoint().x), Math.abs(mCoord.getFirstPoint().y - mCoord.getLastPoint().y));
                        }
                        break;
                    case 3:
                        if (mCoord.getColorRelleno() != null) {
                            mG2D.setPaint(mCoord.getColorRelleno());
                            mG2D.fill(new Ellipse2D.Double(mCoord.getFirstPoint().y, mCoord.getFirstPoint().x, mCoord.getLastPoint().x, mCoord.getLastPoint().y));
                        } else {
                            mG2D.setColor(mCoord.getColor());
                            mG2D.drawOval(mCoord.getFirstPoint().x, mCoord.getFirstPoint().y, mCoord.getLastPoint().x, mCoord.getLastPoint().y);
                        }
                        break;
                }
            }
        }
if (mMouseReleased == false && mMouseIsDragging == true) {
            if (mColorRelleno != null) {
                mG2D.setBackground(mColorRelleno);
            } else {
                mG2D.setColor(mColorLinea);
            }
            switch (mOpcion) {
                case 1:
                    mG2D.drawLine(mPuntoInicio.x, mPuntoInicio.y, mPuntoFinal.x, mPuntoFinal.y);
                    break;
                case 2:
                    mG2D.drawRect(mPuntoInicio.x, mPuntoInicio.y, Math.abs(mPuntoInicio.x - mPuntoFinal.x), Math.abs(mPuntoInicio.y - mPuntoFinal.y));
                    break;
                case 3:
                    mG2D.drawOval(mPuntoInicio.x, mPuntoInicio.y, mPuntoFinal.x, mPuntoFinal.y);
                    break;
            }
        }

抱歉在这里混用了英语和西班牙语,我刚做了这个 D: 第一个 if 在释放鼠标并且没有明显拖动时进入,但是当我切换图形时,它不会绘制数组列表中的图形,在这种情况下是 mCoordenadas。 我怎样才能在另一个线程中运行它?或者更好地表达,我需要一个线程来处理这个吗?

【问题讨论】:

    标签: java multithreading swing


    【解决方案1】:

    想象一个画家在画布上工作。他时不时地抓起一个装着颜料的桶,把它倒在他的画布上。之前存在的一切……“消失”了。

    这就是你调用时所做的

    mG2D.fill(new Rectangle2D.Double(mCoord.getFirstPoint().x, ...                         
    

    在您的 paintComponent() 方法中。

    问题是:你有某种(复杂的)情况;基本上发生的事情是:只要正确的条件结合在一起,你就会用洪水填满你的画布;从而“覆盖”任何先前的内容。

    除此之外:这可能是DRY 原则的一个很好的例子:你在不同的地方有相同的代码;并且忘记了。

    相反:确保任何您的代码应该做的事情都写在完全在一个的地方。

    换句话说:您不应该有多个电话来填充。相反:退后一步,找出“常见行为块”——并将它们提取到一个方法中。

    【讨论】:

    • mG2D 是 Graphics2D 对象,它是通过从 paintComponent 方法中投射 Graphics G 对象而创建的。
    • 是的,那些填充调用正在造成问题,刚刚检查过。我需要找出的是为什么只有在我改变身材后才会发生这种情况:(
    • 我看就知道了。谢谢!我正在重构一切。
    • 重构总是一个很好的答案 ;-) ...该评论对我的意义几乎与我从答案中得到的 25 分一样重要。几乎;-)
    【解决方案2】:

    或者更好的表达,我需要一个线程来处理这个吗?

    线程与此无关。

    mCoordenadas.add(new Coordenadas());
    

    不要添加新面板。所有绘画必须在同一个面板上完成。

    ArrayList 必须包含一个通用的“形状”对象。因此 ArrayList 可以包含椭圆、矩形和线条形状。每个“形状”都必须知道如何绘制自己。

    切换图形时可能会发生变化的是 MouseListener 逻辑。您可以删除旧的侦听器并为新选择的形状添加新的侦听器。

    它不会绘制数组列表中的数字,

    另一种选择是直接绘制到BufferedImage,然后您不必担心重新绘制对象。

    查看Custom Painting Approaches 了解两种方法的工作示例:1) 从 ArrayList 绘制和 2) 绘制到 BufferedImage。

    【讨论】:

    • 很抱歉造成在同一个文件中以西班牙语和英语书写的混淆。我会纠正它。 Coordenadas 是创建每个图形的坐标点的类。可以说:在每次释放鼠标并按下鼠标时,都会将一个点传递给该实例,并且该实例已在 arraylist 中初始化。我的 JPanel 是 JPanel 类,您在这里看到的所有这些方法都存储在其中(paintComponent 方法中的两个 if 子句)。
    • @RenéVidrialesTrujillo,并没有真正改变我的答案。我们无法调试您的代码,因为我们无权访问整个代码。如果形状正在消失,那么我会说正在发生两件事之一:1)您正在创建一个要在其上绘制的新面板或 2)您正在从 ArrayList 中清除形状。您不应该在 MouseListener 代码中访问 Graphics 对象。我向您展示了如何做到这一点的两种方法。
    猜你喜欢
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    相关资源
    最近更新 更多