You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gnome桌面下Swing无装饰JFrame实现透明拖动边框时保留GTK阴影与动画的求助

Gnome桌面下Swing无装饰JFrame实现透明拖动边框时保留GTK阴影与动画的求助

大家好,我现在正在做一个自定义的无装饰Swing JFrame,需求是:当按住标题栏的JLabel拖动窗口时,显示一个自定义的哑光边框,同时让窗口内其他元素都变透明不可见,直到拖动结束。

但现在遇到了一个棘手的矛盾:

  • 如果不在main方法里设置窗口背景为new Color(0,0,0,0),GTK的阴影和动画效果能保留,但拖动时的透明边框效果不对(达不到预期的透明状态)
  • 一旦加上这个透明背景设置,拖动边框的效果是对了,但GTK的阴影和动画直接失效了,而且鼠标悬停关闭/最小化按钮时还会出现视觉卡顿和残影

我期望的效果是:拖动时能显示透明边框,同时窗口原本的GTK阴影、动画效果都能正常保留,拖动过程也不会出现黑背景或者拖动中断的问题。

下面是我的最小可复现示例代码:

package javaaeroglassproject;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;

public class mcve extends JFrame {
    private boolean isDragging = false;
    private int pressX = 0, pressY = 0;

    public mcve() {
        setUndecorated(true);
        setSize(400, 180);
        setLocationRelativeTo(null);
        setLayout(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // Frame border (background panel)
        JLabel frameBorder = new JLabel();
        frameBorder.setOpaque(false);
        frameBorder.setBackground(new Color(230, 230, 230));
        frameBorder.setLayout(null);
        frameBorder.setLocation(0, 0);
        frameBorder.setSize(400, 180);
        add(frameBorder);

        // Title label
        JLabel title = new JLabel("Window Title");
        title.setFont(new Font("Segoe UI", Font.BOLD, 14));
        title.setForeground(Color.DARK_GRAY);
        title.setLocation(10, 0);
        title.setSize(330, 36);
        frameBorder.add(title);

        JButton closeButton = new JButton("X");
        closeButton.setForeground(Color.WHITE);
        closeButton.setBackground(new Color(200, 0, 0));
        closeButton.setBorder(new LineBorder(Color.DARK_GRAY));
        closeButton.setFocusable(false);
        closeButton.setLocation(371, 6);
        closeButton.setSize(23, 23);
        frameBorder.add(closeButton);
        closeButton.addActionListener(e -> System.exit(0));
        closeButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent e) {
                closeButton.setBackground(new Color(255, 50, 50));
            }
            public void mouseExited(java.awt.event.MouseEvent e) {
                closeButton.setBackground(new Color(200, 0, 0));
            }
            public void mousePressed(java.awt.event.MouseEvent e) {
                closeButton.setBackground(new Color(160, 0, 0));
            }
        });

        // Minimize button
        JButton minButton = new JButton("-");
        minButton.setForeground(Color.WHITE);
        minButton.setBackground(new Color(130, 130, 130));
        minButton.setBorder(new LineBorder(Color.DARK_GRAY));
        minButton.setFocusable(false);
        minButton.setLocation(345, 6);
        minButton.setSize(23, 23);
        frameBorder.add(minButton);
        minButton.addActionListener(e -> setState(Frame.ICONIFIED));
        minButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent e) {
                minButton.setBackground(new Color(160, 160, 160));
            }
            public void mouseExited(java.awt.event.MouseEvent e) {
                minButton.setBackground(new Color(130, 130, 130));
            }
            public void mousePressed(java.awt.event.MouseEvent e) {
                minButton.setBackground(new Color(100, 100, 100));
            }
        });

        // Inner content
        JPanel appInner = new JPanel();
        appInner.setLayout(null);
        appInner.setBackground(Color.WHITE);
        appInner.setBorder(new LineBorder(Color.GRAY));
        appInner.setLocation(5, 35);
        appInner.setSize(390, 140);
        frameBorder.add(appInner);

        JLabel message = new JLabel("<html>This is a dialog text. The quick brown fox jumps over the lazy dog.</html>");
        message.setLocation(20, 20);
        message.setSize(350, 80);
        appInner.add(message);

        title.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent e) {
                isDragging = true;
                pressX = e.getX();
                pressY = e.getY();
                closeButton.setVisible(false);
                appInner.setVisible(false);
                minButton.setVisible(false);
                title.setVisible(false);
                frameBorder.setBorder(new LineBorder(Color.GRAY, 2));
                frameBorder.setBackground(new Color(0,0,0,0));
                frameBorder.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
                setBackground(new Color(0, 0, 0, 0));
                getRootPane().setBackground(new Color(0,0,0,0));
                getContentPane().setBackground(new Color(0, 0, 0, 0));
            }
            public void mouseReleased(java.awt.event.MouseEvent e) {
                isDragging = false;
                frameBorder.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                frameBorder.setBorder(new LineBorder(Color.GRAY, 0));
            }
        });

        title.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent e) {
                if (isDragging) {
                    setLocation(e.getXOnScreen() - pressX, e.getYOnScreen() - pressY);
                }
            }
        });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new mcve().setVisible(true));
    }
}

有没有大佬能帮忙解决这个问题?实在是卡在这里好久了😭

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 12:44:37