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

I am creating a JFrame, using a custom look and feel named FlatLaf. But I am experiencing weird behavior when I resize the window. I can replicate the exact same problem with this snippet:

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);
    }
}

With that I can get what I need, this: JFrame with Look and Feel

To achieve that I used the instructions frame.setUndecorated(true); and frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME); (Because as I said, I don’t want the default system border, like this: Frame with default system border)

The problem is when I resize from the left and the top of the frame, it starts to move in that direction, and I haven’t find a solution, here is a gif showing that: JFrame with weird resize behavior.

That problem is obviously solved when I remove the lines:

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

Because I get back the system border, but that’s not what I want.

How can I fix this?, Is there a better way to do it (Or different)?.

Answer

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

This effect happens because you are setting the minimum size of the JFrame, together with the fact that you clear the frame decorations. So don’t set the minimum size, or just leave the decorations enabled. If you leave the decorations enabled and still set the minimum size, then the user will be able to resize the frame until it reaches the minimum corresponding dimension where, instead of moving, the frame will stay in place.


As for the title bar, in case you need all of its good characteristics (such as the 3 buttons on the right, the title and icon of the frame on the left and the bar in the middle which can be actually dragged by the user to move the frame), but you also want it to have a specific color, then don’t undecorate it and only change the color of the title bar component, which can be done like so:

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);
    }
}

In this case, you have to leave the decorations enabled. But then that seems ok because you want the characteristics of the title bar, just with a different background color in it.

I found out about the properties/keys "TitlePane.inactiveBackground" and "TitlePane.background" in the documentation of the source code of the class FlatTitlePane which as someone can see (in the source code of FlatRootPaneUI) this is the class being installed on the root pane of the frame as its title bar.

I’ve seen about the laf.getDefaults().getColor("control"); part in the source code of FlatLaf (in the getDefaults method).

According to some instructions of the FlatLaf’s web page, you should better set those properties after installing the LAF and before creating the components.