摆动分层-透明组件会忽略底层的AWT元素

首先,要摆脱它,我绝对需要在Swing应用程序中使用重量级的AWT组件。我需要他们两个的功能。

任务很简单-渲染一个重量级的AWT画布(或任何其他元素),直接在其上渲染OpenGL场景,然后在其上方显示用于用户界面的Swing按钮。

我的问题是它运行一半。 我似乎对Z排序没有问题。我正在使用jLayeredPanes,并且可以在各层之间移动Canvas,并且在其他元素的上方或下方弹出框时,它实际上是有效的。

问题在于透明度。 关键是,Swing元素具有Opaque参数,并且将其设置为false(非不透明)时-它基本上应该是透明的,并且您应该看到它下面的下一个元素。但是,就我而言,AWT画布将被忽略,而您只能看到下一个基础SWING元素。

这是几个屏幕截图。它们来自我的一个独立测试项目。画布被拉伸到框架的大小,并且在左上方有一个JLayeredPane虚拟元素,它是菜单的简化版本。

第一张屏幕截图上,JLayeredPane的“不透明”设置设置为true,您可以看到其背景属性设置为“蓝色”。

第二屏幕截图中,所有内容都完全相同,但是Opaque设置为false。而不显示画布上的任何内容,而是在空的灰色jFrame背景中绘制内容。

最后,在第三屏幕截图中,我将Canvas放到了jPanel中,而不是独自保留。如您所见,通过透明的jLayeredPane可以看到面板的橙色,但是Canvas仍然被隐藏了。

摆动分层-透明组件会忽略底层的AWT元素

摆动分层-透明组件会忽略底层的AWT元素

摆动分层-透明组件会忽略底层的AWT元素

这是框架布局的代码。我现在不会发布渲染/上下文代码

frame = new JFrame("AWT test");
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setLayout(new BorderLayout());
    frame.setPreferredSize(new Dimension(width,height));

    canvas = new Canvas();
    canvas.setSize(width,height);

    //this part exists only in the third example
    JPanel p = new JPanel();
    p.setSize(width,height);
    p.setBackground(Color.orange);
    p.add(canvas);
    // third example end

    JLayeredPane pane = new JLayeredPane();
    JLayeredPane paneMenu = new JLayeredPane();
    JButton button = new JButton();
    button.setSize(20,20);
    paneMenu.setSize(200,200);
    paneMenu.add(button,new Integer(1));
    paneMenu.setBackground(Color.BLUE);
    paneMenu.setOpaque(false);           //True for the first example

    pane.add(p,new Integer(1));    // canvas for the first two examples
    pane.add(paneMenu,new Integer(2));

    pane.setOpaque(false);

    frame.add(pane);
    frame.pack();
    frame.setVisible(true);
    frame.transferFocus();

任何人都可以向我解释发生了什么以及如何做我需要做的事情。 我将再次重复-我必须使用重量级组件作为渲染目标。我知道像JOGL的GLPanel这样的解决方案,它是与Swing兼容的轻型组件。但是我尝试了该方法,并且性能确实很慢,因为它没有直接将其呈现为上下文目标,而是从内存中读取FrameBuffer,对其进行翻转,然后将其绘制为BufferedImage。该路径不适合我将要在其上运行的嵌入式系统的有限资源。

c0der说:请发布最少的可复制示例 Errrrm ....不是吗? 在这里,您可以根据需要以完整的Java类形式使用它,但我实际上是更改了一些常量变量。

import javax.swing.*;
import java.awt.*;

public class Main
{
    public static void main(String[] args)
    {
        JFrame frame = new JFrame("AWT test");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.setPreferredSize(new Dimension(500,500));

        Canvas canvas = new Canvas();
        canvas.setSize(500,500);
        canvas.setBackground(Color.RED);

        //this part exists only in the third example
        JPanel p = new JPanel();
        p.setSize(500,500);
        p.setBackground(Color.orange);
        p.add(canvas);
        // third example end

        JLayeredPane pane = new JLayeredPane();
        JLayeredPane paneMenu = new JLayeredPane();
        JButton button = new JButton();
        button.setSize(20,20);
        paneMenu.setSize(200,200);
        paneMenu.add(button,new Integer(1));
        paneMenu.setBackground(Color.BLUE);
        paneMenu.setOpaque(false);           //True for the first example

        pane.add(p,new Integer(1));    // canvas for the first two examples
        pane.add(paneMenu,new Integer(2));

        pane.setOpaque(false);

        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
        frame.transferFocus();
    }
}

一些更新:

我最初怀疑是因为Swing元素将所有图形委托给底层的重量级元素(在我的情况下为JFrame),然后发生的情况是,框架为其自身生成了一个frameBuffer,然后显示在Canvas的顶部。画布本身在这一代中没有得到处理,因此框架“覆盖”了画布。

似乎并非如此。我尝试使JFrame保持未装饰状态,所有面板均不透明,并显示图片。结果-画布仍处于“剪切”状态,通过该孔您可以看到基础的IDE菜单。 这使我认为,在绘制过程中的某个位置,画布本身会检测到它被另一个元素遮盖了,并且不需要绘制该区域。因此,它会“优化”自身,而不更新这些像素。

也许我错了。但是,这是另一个屏幕截图。这是与之前相同的示例,但是我取出了3d渲染,只是试图在背景设置为红色的情况下显示Canvas。

摆动分层-透明组件会忽略底层的AWT元素

ilys2013 回答:摆动分层-透明组件会忽略底层的AWT元素

再一次回答我自己的问题。

原来我需要做

setComponentMixingCutoutShape(paneMenu,new Rectangle());

位于按钮下方的菜单窗格。从本质上讲,这告诉Java不要从重量级基础组件中删除该元素。

本文链接:https://www.f2er.com/2927433.html

大家都在问