Java 使用 setWindowDecorationStyle(JRootPane.FRAME) 调整大小时,JFrame 出现奇怪的行为;

Java JFrame weird behavior when resizing with setWindowDecorationStyle(JRootPane.FRAME);

我正在创建一个 JFrame,使用名为 FlatLaf 的自定义外观。但是当我调整 window 大小时我遇到了奇怪的行为。我可以用这个片段复制完全相同的问题:

import com.formdev.flatlaf.intellijthemes.FlatOneDarkIJTheme;
import javax.swing.*;
import java.awt.*;

public class Main{
    public static void main(String[] args){

        try{ UIManager.setLookAndFeel(new FlatOneDarkIJTheme()); }
        catch(Exception e){}

        JFrame frame = new JFrame();
        frame.setSize(1280, 720);
        frame.setMinimumSize(new Dimension(750, 400));
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setUndecorated(true);
        frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);

        frame.setVisible(true);
    }
}

这样我就可以得到我需要的东西,这个: JFrame with Look and Feel

为了实现这一点,我使用了说明 frame.setUndecorated(true);frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);(因为正如我所说,我不想要默认的系统边框,像这样:Frame with default system border)

问题是当我从框架的左侧和顶部调整大小时,它开始朝那个方向移动,并且我还没有找到解决方案,这里有一个 gif 显示:JFrame with weird resize behavior.

当我删除这些行时,这个问题显然得到了解决:

frame.setUndecorated(true);
frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);

因为我找回了系统边框,但这不是我想要的。

我该如何解决这个问题?有没有更好的方法(或不同的方法)?

The problem is when I resize from the left and the top of the frame, it starts to move in that direction

之所以会出现这种效果,是因为您同时设置了 JFrame 的最小尺寸,同时您清除了边框装饰。所以不要设置最小尺寸,或者只启用装饰。如果您启用装饰并仍然设置最小尺寸,那么用户将能够调整框架的大小,直到它达到相应的最小尺寸,而不是移动,框架将留在原地。


关于标题栏,如果你需要它所有的好特性(比如右边的3个按钮,左边的框架的标题和图标,中间的栏,实际上可以被用户拖动移动框架),但你也希望它有一个特定的颜色,那么不要取消装饰它,只改变标题栏组件的颜色,可以这样做:

import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatLaf;
import javax.swing.*;
import java.awt.*;

public class Main {
    public static void main(final String[] args) {
        final FlatDarkLaf laf = new FlatDarkLaf();
        FlatLaf.install(laf);
        final Color controlColor = laf.getDefaults().getColor("control"); //Obtains the background color of FlatDarkLaf.

        //Change the title bar active and inactive color...
        UIManager.put("TitlePane.inactiveBackground", controlColor); //This is the color of the title bar when the frame doesn't have focus.
        UIManager.put("TitlePane.background", controlColor); //This is the color of the title bar when the frame has focus.
        
        final JFrame frame = new JFrame("Title");
        
        frame.setSize(1280, 720);
        frame.setMinimumSize(new Dimension(750, 400));
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

在这种情况下,您必须启用装饰。但这似乎没问题,因为你想要标题栏的特征,只是其中有不同的背景颜色。

我在 the source code of the class FlatTitlePane which as someone can see (in the source code of FlatRootPaneUI 的文档中发现了 properties/keys "TitlePane.inactiveBackground""TitlePane.background")这是在根窗格上安装的 class框架的标题栏。

我在 the source code of FlatLaf 中看到了 laf.getDefaults().getColor("control"); 部分(在 getDefaults 方法中)。

根据 some instructions of the FlatLaf's web page,您最好在安装 LAF 之后和创建组件之前设置这些属性。