Article directory
- Swing custom title bar
-
- need
- The final effect is as shown below
- step
- additional requirements
Swing custom title bar
Requirements
If you want to achieve a title bar effect similar to IDEA, place the menu bar on the same row as the title bar, with the title in the center and buttons on the right. As shown in the picture:
The final effect is as shown
Steps
Use dependency FlatLaf
<!-- https://mvnrepository.com/artifact/com.formdev/flatlaf --> <dependency> <groupId>com.formdev</groupId> <artifactId>flatlaf</artifactId> <version>3.2.5</version> </dependency>
-
Cancel system title bar
frame.setUndecorated(true);
can be achieved. -
Custom title bar
class CustomTitlePane extends JMenuBar {<!-- --> public CustomTitlePane(JFrame frame) {<!-- --> // Create a blank panel to add left spacing JLabel blankLbl = new JLabel(" "); add(blankLbl); // add icon Image image = ImageManager.getImage("/images/logo.png"); ImageIcon icon = new ImageIcon(image); Image scaledImage = icon.getImage().getScaledInstance(16, 16, Image.SCALE_SMOOTH); JLabel iconLabel = new JLabel(new ImageIcon(scaledImage)); add(iconLabel); // Create a blank panel to add left spacing JLabel blankLbl2 = new JLabel(" "); add(blankLbl2); JMenuBar menuBar = ToolkitUtilities.getMenuBar(); add(menuBar); //Create and add a title tag, center aligned JLabel titleLabel = new JLabel(frame.getTitle()); titleLabel.setHorizontalAlignment(SwingConstants.CENTER); add(Box.createHorizontalGlue()); add(titleLabel); add(Box.createHorizontalGlue()); //Add minimize button JButton minimizeButton = new JButton("-"); minimizeButton.addActionListener(new ActionListener() {<!-- --> @Override public void actionPerformed(ActionEvent e) {<!-- --> frame.setExtendedState(JFrame.ICONIFIED); } }); add(minimizeButton); //Add maximize button JButton maximizeButton = new JButton("[]"); maximizeButton.addActionListener(new ActionListener() {<!-- --> @Override public void actionPerformed(ActionEvent e) {<!-- --> if (frame.getWidth() == screenSize.width) {<!-- --> frame.setSize(new Dimension(1280, 768)); frame.setLocationRelativeTo(null); } else {<!-- --> frame.setBounds(0, workArea.y, screenSize.width, workArea.height); } } }); add(maximizeButton); //Add close button JButton closeButton = new JButton("X"); closeButton.addActionListener(new ActionListener() {<!-- --> @Override public void actionPerformed(ActionEvent e) {<!-- --> frame.dispose(); } }); add(closeButton); } @Override public void updateUI() {<!-- --> super.updateUI(); //Set the appearance of the menu bar, using FlatMenuBarUI to match the FlatLaf theme setUI(new FlatMenuBarUI()); } }
-
Custom window drag and drop and resize
- First, the
getResizeCursor
method is provided to determine the current shape of the pointer based on the current position of the mouse. There are only two types according to requirements: the default pointer and the resized pointer.
private static int getResizeCursor(JFrame frame, Point p) {<!-- --> Insets insets = frame.getInsets(); int x = p.x; int y = p.y; int width = frame.getWidth(); int height = frame.getHeight(); if (x < BORDER_SIZE & amp; & amp; y < BORDER_SIZE) {<!-- --> return Cursor.NW_RESIZE_CURSOR; } if (x < BORDER_SIZE & amp; & y > height - BORDER_SIZE) {<!-- --> return Cursor.SW_RESIZE_CURSOR; } if (x > width - BORDER_SIZE & amp; & y < BORDER_SIZE) {<!-- --> return Cursor.NE_RESIZE_CURSOR; } if (x > width - BORDER_SIZE & amp; & y > height - BORDER_SIZE) {<!-- --> return Cursor.SE_RESIZE_CURSOR; } if (x < BORDER_SIZE) {<!-- --> return Cursor.W_RESIZE_CURSOR; } if (x > width - BORDER_SIZE) {<!-- --> return Cursor.E_RESIZE_CURSOR; } if (y < BORDER_SIZE) {<!-- --> return Cursor.N_RESIZE_CURSOR; } if (y > height - BORDER_SIZE) {<!-- --> return Cursor.S_RESIZE_CURSOR; } return Cursor.DEFAULT_CURSOR; }
-
Here we add four types of event listeners for the mouse:
-
MouseMoved
When the mouse moves, the current pointer position is determined according to the above method, and the mouse pointer icon is updated in a timely manner.
-
Mouse click mousePressed
When the mouse clicks, it is judged based on the current pointer icon:
? If it is the default icon, it is considered a drag operation, and the current coordinates need to be recorded;
? If it is another icon, it is considered a resize operation.
-
mouse released mouseReleased
The mouse needs to change back to the default pointer when released.
-
mouse drag mouseDragged
When dragging the mouse, it can be divided into two situations based on the current pointer icon:
? If it is the default icon, it is considered to be a moving position operation, and the frame position is modified through the
setLocation
method;? If it is not the default icon, it is considered to be a resize operation. For the resize operation, it is necessary to distinguish the specific type of the current pointer to determine which direction the displacement is, and at the same time, the distance between the current pointer coordinate point and the original pointer coordinate point needs to be calculated. Because during the resizing process, in addition to the
size
change, there is also alocation
change.? At the same time, if you want to limit the minimum
size
of the window, I also limit it here throughMIN_WIDTH
andMIN_HEIGHT
.
-
private static void addResizeWindowSupport(JFrame frame) {<!-- --> frame.addMouseListener(new MouseAdapter() {<!-- --> @Override public void mousePressed(MouseEvent e) {<!-- --> // Get the current pointer shape cursor = getResizeCursor(frame, e.getPoint()); // If it is the default pointer, it may be a drag operation if(cursor == Cursor.DEFAULT_CURSOR) {<!-- --> mouseAtX = e.getPoint().x; mouseAtY = e.getPoint().y; } } @Override public void mouseReleased(MouseEvent e) {<!-- --> // Release the pointer and change it back to the default pointer cursor = Cursor.DEFAULT_CURSOR; } }); frame.addMouseMotionListener(new MouseAdapter() {<!-- --> @Override public void mouseDragged(MouseEvent e) {<!-- --> // During the dragging process of the pointer, if it is not the default pointer, it is changing the size. if (cursor != Cursor.DEFAULT_CURSOR) {<!-- --> Point p = e.getPoint(); SwingUtilities.convertPointToScreen(p, frame); Point newLocation = frame.getLocation(); Dimension newSize = frame.getSize(); switch (cursor) {<!-- --> case Cursor.N_RESIZE_CURSOR: newSize.height = frame.getHeight() - p.y + frame.getLocation().y; newLocation.y = p.y; break; case Cursor.S_RESIZE_CURSOR: newSize.height = p.y - frame.getLocation().y; break; case Cursor.W_RESIZE_CURSOR: newSize.width = frame.getWidth() - p.x + frame.getLocation().x; newLocation.x = p.x; break; case Cursor.E_RESIZE_CURSOR: newSize.width = p.x - frame.getLocation().x; break; case Cursor.NW_RESIZE_CURSOR: newSize.height = frame.getHeight() - p.y + frame.getLocation().y; newLocation.y = p.y; newSize.width = frame.getWidth() - p.x + frame.getLocation().x; newLocation.x = p.x; break; case Cursor.NE_RESIZE_CURSOR: newSize.height = frame.getHeight() - p.y + frame.getLocation().y; newLocation.y = p.y; newSize.width = p.x - frame.getLocation().x; break; case Cursor.SW_RESIZE_CURSOR: newSize.height = p.y - frame.getLocation().y; newSize.width = frame.getWidth() - p.x + frame.getLocation().x; newLocation.x = p.x; break; case Cursor.SE_RESIZE_CURSOR: newSize.height = p.y - frame.getLocation().y; newSize.width = p.x - frame.getLocation().x; break; } frame.setBounds(newLocation.x, newLocation.y, Math.max(100, newSize.width), Math.max(100, newSize.height)); } else {<!-- --> // If it is the default pointer, it is dragging frame.setLocation(e.getXOnScreen() - mouseAtX, e.getYOnScreen() - mouseAtY); } } }); frame.addMouseMotionListener(new MouseAdapter() {<!-- --> @Override public void mouseMoved(MouseEvent e) {<!-- --> frame.setCursor(Cursor.getPredefinedCursor(getResizeCursor(frame, e.getPoint()))); } }); }
- First, the
Additional requirements
-
The default window is maximized and does not occupy taskbar space
If you don’t do anything, the default maximization will cause the taskbar to be covered. Here are some tips:
//Get the screen size screenSize = Toolkit.getDefaultToolkit().getScreenSize(); // Get the size of the screen working area workArea = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); // Set the initial position and size of the window to ensure that the bottom does not occupy the taskbar space frame.setBounds(0, workArea.y, screenSize.width, workArea.height);