Java Swing 中无边框窗口的抗锯齿圆角方案

最近在写 LiveDock 时,我需要做一个无边框、带圆角、还能正常拖动的 Swing 窗口。 一开始我对这件事很乐观。Swing 虽然老,但 JFrame.setUndecorated(true)、透明背景和 setShape(new RoundRectangle2D(...)) 这些能力都在,看起来只要把它们拼起来,再配合 Graphics2D 的抗锯齿绘制,应该就能得到一个还不错的现代窗口外观。 结果实际效果并不理想。 最开始我以为问题只是“没有开抗锯齿”,但真正做下去以后才发现,症结并不在 Graphics2D,而在 setShape() 本身。 目标其实有两个 如果只是想在 Swing 里“画一个圆角矩形”,事情并不复杂。真正麻烦的是这里其实有两个目标,而且它们并不完全一致: 视觉上看起来要是平滑的圆角。 窗口实际可点击、可命中的区域,也要是合理的圆角区域。 这两个目标分别对应两套不同层级的机制: Graphics2D 负责“你画出来什么” Window#setShape() 负责“窗口真正长成什么形状” 只要这两者完全重合,你就很容易碰到锯齿问题。 最初的实现 一开始我的代码很简单,大概就是这样: frame.setUndecorated(true); frame.setBackground(new Color(0, 0, 0, 0)); frame.setShape(new RoundRectangle2D.Double(0, 0, w, h, arc, arc)); 然后内容面板里再自己画一个圆角背景,比如: @Override protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(Color.DARK_GRAY); g2.fillRoundRect(0, 0, getWidth(), getHeight(), arc, arc); g2.dispose(); } 单看这段代码,逻辑几乎是无懈可击的: 窗口是无边框的 背景是透明的 窗口形状被裁成圆角矩形 面板绘制也开了抗锯齿 但最终效果仍然是边缘发硬,圆角不够干净。...

2025/05/06 · 2 分钟 · 265 字 · Pectics, OpenAI Codex