当前位置: 首页 > 知识库问答 >
问题:

JavaAWT自定义复合上下文

宗项禹
2023-03-14

我正在尝试为AWT Graphics2D实现类似于SWT GC的xor模式绘图。使用内置XORComposite不是一个选项,因为它不像SWT那样实现xor模式绘图。

SWT xor模式绘图通过二进制异或组合源颜色和目标颜色。AWT XORComposite(可通过g2d.setXORMode(Color))使用恒定的xor颜色,该颜色通过二进制异或与源颜色组合,即目标颜色不影响结果颜色。

所以我唯一的选择就是编写我自己的Composite和CompositeContext实现,将源代码和目标代码恰当地结合起来。

经过一番阅读,我想出了这个简单的实现:(是的,我知道getPixel(…),setPixel(…)开销我希望在优化之前它能正常工作。)

private static class XorComposite implements Composite {

    public static XorComposite INSTANCE = new XorComposite();

    private XorContext context = new XorContext();

    @Override
    public CompositeContext createContext(ColorModel srcColorModel,
            ColorModel dstColorModel, RenderingHints hints) {
        return context;
    }

}

private static class XorContext implements CompositeContext {

    public XorContext() {
    }

    @Override
    public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
        int w = Math.min(src.getWidth(), dstIn.getWidth());
        int h = Math.min(src.getHeight(), dstIn.getHeight());

        int[] srcRgba = new int[4];
        int[] dstRgba = new int[4];

        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                src.getPixel(x, y, srcRgba);
                dstIn.getPixel(x, y, dstRgba);
                for (int i = 0; i < 3; i++) {
                    dstRgba[i] ^= srcRgba[i];
                }
                dstOut.setPixel(x, y, dstRgba);
            }
        }
    }

    @Override
    public void dispose() {
    }

}

禁用抗锯齿时,此实现工作正常。如果启用了抗锯齿功能,只要我的图形完全可见,即在我绘制的JPanel内部,它就可以工作。但是,如果图形跨越JPanel的边界,则会引发RasterFormatException:

Exception in thread "AWT-EventQueue-0" java.awt.image.RasterFormatException: (y + height) is outside raster
    at sun.awt.image.IntegerInterleavedRaster.createWritableChild(IntegerInterleavedRaster.java:470)
    at sun.awt.image.IntegerInterleavedRaster.createChild(IntegerInterleavedRaster.java:514)
    at sun.java2d.pipe.GeneralCompositePipe.renderPathTile(GeneralCompositePipe.java:106)
    at sun.java2d.pipe.AAShapePipe.renderTiles(AAShapePipe.java:201)
    at sun.java2d.pipe.AAShapePipe.fillParallelogram(AAShapePipe.java:102)
    at sun.java2d.pipe.PixelToParallelogramConverter.fillRectangle(PixelToParallelogramConverter.java:322)
    at sun.java2d.pipe.PixelToParallelogramConverter.fill(PixelToParallelogramConverter.java:159)
    at sun.java2d.pipe.ValidatePipe.fill(ValidatePipe.java:160)
    at sun.java2d.SunGraphics2D.fill(SunGraphics2D.java:2422)
    at org.eclipse.gef4.graphics.examples.AwtXorTestPanel.paint(AwtXorTest.java:117)
    ... (irrelevant)

值得注意的是,我的Composite/CompositeContext不会引发异常,但AWT内部在尝试创建要传递给我的CompositeContext的光栅对象时会引发异常。

不幸的是,PixelToParallelogramConverter仅在启用抗锯齿时用于自定义合成。例如,内置的XORComposite使用本机方法进行绘制。我假设是AWT错误,但我不确定。

非常感谢您的帮助:)

更新:

正如Durandal所建议的,我用java-6-sun和java-1.6.0-openjdk测试了代码。我发现OpenJDK抛出异常,而Sun JDK没有。因此,我在OpenJDK bug跟踪器上报告了这个bug。

问题解决后,我会更新这个问题。请访问相应的OpenJDK错误,以获取有关当前进度的信息。

你好,马蒂亚斯

下面是一个示例程序,您可以在本地对其进行测试:

/*******************************************************************************
 * Copyright (c) 2013 itemis AG and others.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Matthias Wienand (itemis AG) - initial API and implementation
 * 
 *******************************************************************************/
package org.eclipse.gef4.graphics.examples;

import java.awt.Color;

public class AwtXorTest extends JApplet {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setTitle("AWT XorMode Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JApplet applet = new AwtXorTest();
        applet.init();
        frame.getContentPane().add(applet);
        frame.pack();
        frame.setVisible(true);
    }

    @Override
    public void init() {
        JPanel panel = new AwtXorTestPanel();
        getContentPane().add(panel);
    }

}

class AwtXorTestPanel extends JPanel {

    private static class XorComposite implements Composite {

        public static XorComposite INSTANCE = new XorComposite();

        private XorContext context = new XorContext();

        @Override
        public CompositeContext createContext(ColorModel srcColorModel,
                ColorModel dstColorModel, RenderingHints hints) {
            return context;
        }

    }

    private static class XorContext implements CompositeContext {

        public XorContext() {
        }

        @Override
        public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
            int w = Math.min(src.getWidth(), dstIn.getWidth());
            int h = Math.min(src.getHeight(), dstIn.getHeight());

            int[] srcRgba = new int[4];
            int[] dstRgba = new int[4];

            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    src.getPixel(x, y, srcRgba);
                    dstIn.getPixel(x, y, dstRgba);
                    for (int i = 0; i < 3; i++) {
                        dstRgba[i] ^= srcRgba[i];
                    }
                    dstOut.setPixel(x, y, dstRgba);
                }
            }
        }

        @Override
        public void dispose() {
        }

    }

    private static final long serialVersionUID = 1L;

    public AwtXorTestPanel() {
        setPreferredSize(new Dimension(640, 480));
    }

    @Override
    public void paint(Graphics graphics) {
        Graphics2D g2d = (Graphics2D) graphics;

        // comment out to see it working:
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setComposite(XorComposite.INSTANCE);
        g2d.setColor(new Color(0, 255, 255)); // resulting color should be red
        g2d.fill(new Rectangle(100, 100, 500, 500));
    }

}

共有2个答案

东方震博
2023-03-14

g2d剪辑区域有多个长方体,将引发RasterFormatException,因为其全尺寸光栅参考将替换为抗锯齿长方体的光栅。

陈鸿才
2023-03-14

警告:我已经有一段时间没碰锉刀了。

看起来您可能正在访问光栅外的像素。

光栅有一个minXminY,所以你的循环应该是这样的:

int srcMinX = src.getMinX();
int srcMinY = src.getMinY();
int dstInMinX = dstIn.getMinX();
int dstInMinY = dstIn.getMinY();
int dstOutMinX = dstOut.getMinX();
int dstOutMinY = dstOut.getMinY();

for (int x = 0; x < w; x++) {
    for (int y = 0; y < h; y++) {
        src.getPixel(x+srcMinX, y+srcMinY, srcRgba);
        dstIn.getPixel(x+dstInMinX, y+dstInMinY, dstRgba);
        for (int i = 0; i < 3; i++) {
            dstRgba[i] ^= srcRgba[i];
        }
        dstOut.setPixel(x+dstOutMinX, y+dstOutMinY, dstRgba);
    }
}
 类似资料:
  • 问题内容: 我目前正在开发的Android应用程序的主要活动已经变得非常大。这主要是因为它包含带有3个标签的。每个选项卡都有很多组件。活动必须一次控制所有这些组件。因此,我想您可以想象这个Activity有20个字段(几乎每个组件都有一个字段)。它还包含许多逻辑(单击侦听器,填充列表的逻辑等)。 我通常在基于组件的框架中所做的就是将所有内容拆分为自定义组件。每个自定义组件将承担明确的责任。它包含它

  • 这里有一个项目,我需要在WPF应用程序中自定义上下文菜单,其中将在所有MenuItems的底部放置一个按钮。 但是,如果我要通过XAML添加按钮,它将作为集合中的另一项出现在上下文菜单中,鼠标移过高亮显示将作用于它。 我希望有一个上下文菜单调优到网格样的样式,这样我就可以自定义样式下的它。 有什么想法可以实现这一点(最好是在XAML中)吗?

  • 我有一些不应该实例化的带有自定义注释的类(抽象类,它只是实际bean的子组件)。但是在这些类之上,在运行时,在上下文初始化阶段,我想在应用程序上下文中添加额外的bean。 因此,基本上我需要扫描类路径,处理结果,并将新bean引入curent应用程序上下文。 似乎是spring-mvc、spring-tasks和spring-integration在做这件事(我试着从源代码中学习--没有运气) 我

  • 描述 (Description) Framework7允许您将自定义上下文传递给任何动态页面或任何加载的Ajax。 data-context属性用于传递自定义上下文,您需要在其中放置有效的字符串化JSON,如下所示 - <a href = "interests.html" class = "item-link item-content" data-context = '{ "sport":

  • 问题内容: 我正在Django(1.11)上编写自己的自定义,并从auth0获取经过身份验证的用户的信息。这不是我第一次写它,我也不知道这个错误是从哪里来的: ImportError:模块“ auth.context_processors”未定义“ auth0_processors”属性/类 看起来是这样的: auth / settings.py: auth / context_processor

  • 问题内容: 我有一些带有自定义注释的类,不应实例化(抽象类,它只是真实bean的子组件)。但是在此类的顶部,在运行时,在上下文初始化阶段,我想将额外的bean放入应用程序上下文中。 因此,基本上,我需要扫描类路径,处理结果,并将新bean引入当前的应用程序上下文中。 似乎spring-mvc,spring-tasks和spring-integration正在这样做(我试图从源中学习它-没运气) 我