gpt4 book ai didi

java - Swing 分层 - 透明组件忽略底层 AWT 元素

转载 作者:行者123 更新时间:2023-12-01 19:24:59 25 4
gpt4 key购买 nike

首先,为了解决这个问题,我绝对需要在 swing 应用程序中使用重量级 AWT 组件。我需要他们两个的功能。

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

我的问题是它半途而废。我似乎对 Z 排序没有任何问题。我正在使用 jLayeredPanes,并且我可以在层之间移动 Canvas,它实际上可以工作,弹出到其他元素的顶部或下方。

问题在于透明度。问题是,Swing 元素有 Opaque 参数,当它设置为 false(非不透明)时 - 它基本上应该是透明的,您应该看到它下面的下一个元素。然而,在我的例子中,AWT Canvas 被忽略,您只能看到下一个底层 SWING 元素。

这里有一些屏幕截图。它们取 self 的一个独立测试项目。 Canvas 被拉伸(stretch)到框架的大小,左上角有一个 JLayeredPane 虚拟元素,它是菜单的简化版本。

第一个屏幕截图中,JLayeredPane 的不透明设置设置为 true,您可以看到它的背景属性设置为蓝色。

第二个屏幕截图中,一切都完全相同,但不透明设置为 false。不是显示 Canvas 上的任何内容,而是在空的灰色 jFrame 背景中绘制的内容。

最后,在第三个屏幕截图中,我将 Canvas 放入 jPanel 中,而不是将其单独保留。正如您所看到的,通过透明的 jLayeredPane 可以看到面板的橙色,但 Canvas 再次被隐藏。

paneMenu Opaque = true paneMenu.setOpaque(false) paneMenu.setOpaque(false) + Canvas inside jPanel

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

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 说:请发布最小的可重现示例呃……我不是吗?在这里,如果您愿意,您可以使用完整的 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 元素将所有绘图委托(delegate)给底层重量级元素(在我的例子中为 JFrame),所以发生的情况是框架为自己生成一个单独的frameBuffer,然后显示在 Canvas 之上。 Canvas 本身在这一代中没有得到处理,因此框架“覆盖”了 Canvas 。

事实似乎并非如此。我尝试使 JFrame 未经装饰,所有面板不透明,并显示图片。结果—— Canvas 仍然被“切割”,通过这个洞你可以看到底层的 IDE 菜单。这让我认为在绘图过程中的某个地方, Canvas 本身检测到它被另一个元素遮挡,并且它不需要绘制该区域。因此它会“优化”自身并且不会更新这些像素。

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

enter image description here

最佳答案

再次回答我自己的问题。

事实证明我需要做

setComponentMixingCutoutShape(paneMenu, new Rectangle());

用于位于按钮下方的菜单 Pane 。这本质上告诉 java 不要从重量级底层组件中删除该元素。

关于java - Swing 分层 - 透明组件忽略底层 AWT 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59321794/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com