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
相关产品推荐
相关产品推荐

