是否真的永远无法调用Component.getGraphics?

时间:2015-05-29 14:04:45

标签: java swing graphics2d repaint java-2d

MadProgrammer发表评论here说明你永远不应该使用我普遍认同的Component.getGraphics:几乎在所有情况下都是错误的。

但是以我多年前创建的这门课为例。我发布了我认为相关的代码。您可以找到完整的代码here

public class MouseDragOutliner extends MouseAdapter implements MouseMotionListener {
private class MyRunnable implements Runnable {
    public void run() {
        Graphics g = mComponent.getGraphics();
        if (g == null) {
            return;
        }
        Graphics2D g2 = (Graphics2D) g;
        Stroke s = g2.getStroke();
        g2.setStroke(DASH_STROKE);
        int x = Math.min(mStart.x, mEnd.x);
        int y = Math.min(mStart.y, mEnd.y);
        int w = Math.abs(mEnd.x - mStart.x);
        int h = Math.abs(mEnd.y - mStart.y);
        if (w == 0 || h == 0) return;
        g2.setXORMode(Color.WHITE);
        if (mCustomShape != null) {
            Rectangle r = mCustomShape.getBounds();
            AffineTransform scale = AffineTransform.getScaleInstance(w / (double)r.width, h / (double)r.height);
            AffineTransform trans = AffineTransform.getTranslateInstance(x - r.x, y-r.y);
            g2.transform(trans);
            g2.transform(scale);
            g2.draw(mCustomShape);
        } else {
            if (mShape == RECTANGLE) g2.drawRect(x, y, w, h);
            else if (mShape == OVAL) g2.drawOval(x, y, w, h);
            else if (mShape == LINE) g2.drawLine(mStart.x, mStart.y, mEnd.x, mEnd.y);
        }
        g2.setStroke(s);    
    }
}

public void doMouseDragged(MouseEvent me) {
    mEnd = me.getPoint();
    if (mStart != null) {
        mComponent = me.getComponent();
        mComponent.repaint();
        SwingUtilities.invokeLater(mRunner);
    }
}
}

从mouseDragged和mouseMoved(配置为)时调用doMouseDragged。如果它不明显,它所做的是在组件上调用重绘(因此组件准备好绘制),然后运行mRunner。我在很多情况下都非常成功地使用了它,其好处是MouseDragOutliner不需要任何自定义(在paintComponent中)来容纳的组件。

如果真的永远无法调用Component.getGraphics,有人可以建议更好的解决方案吗?

谢谢!

http://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/ui/drag/MouseDragOutliner.java#l66

1 个答案:

答案 0 :(得分:3)

我从不喜欢说永远不会。我认为您只需要注意使用不推荐的方法时的缺点。

关于getGrapahics()的要点是这幅画只是暂时的。每当Swing确定需要重新绘制组件时,您将丢失自定义绘画。例如,尝试创建轮廓,然后最小化或最大化框架,轮廓将丢​​失。如果您使用Alt + Tab在Windows中切换应用程序,您也将丢失该绘画。

我同意在这种情况下,用户不太可能做这样的事情,但它可能会导致问题并导致错误报告。所以你需要决定是否关心这个问题。谁知道,也许这是一项要求,所以这不是什么大问题?

根据@kiheru的建议,您可以使用JLayer类。在创建代码时,我认为JLayer不是API的一部分。我对它并不熟悉,但是在使用JLayer类时,Swing教程有一个关于Responding to Events的部分,这似乎表明你可以做你想做的事。

使用JLayer时,您无法动态地将功能添加到任何组件(代码的方式)。您需要在设计时添加功能,但我认为这不应该是一个问题。

相关问题