Java?Swing實現自定義窗口CusFrame
一、背景
Swing 原生窗口 JFrame 的標題欄是系統(tǒng)自帶的,樣式陳舊且無法自定義。不同操作系統(tǒng)下標題欄風格不一致,也不支持圓角、自定義顏色、自定義按鈕等現代 UI 元素。 CusFrame 的作用就是:移除系統(tǒng)裝飾,自己繪制標題欄和窗口邊框,實現統(tǒng)一的窗口風格。同時支持窗口拖拽移動、調整大小、最小化、最大化、還原、多屏幕適配等功能。
二、類源碼
import lombok.Setter;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;
import java.util.function.BiConsumer;
/**
* 自定義窗口框架類
* 實現圓角窗口和自定義標題欄,支持拖拽移動、調整大小、最小化、最大化和關閉功能
* * 使用示例:
* CusFrame frame = new CusFrame("窗口標題");
* frame.setSize(800, 600);
* frame.setVisible(true);
*/
public class CusFrame extends JFrame {
private static final String ICON_PATH = "icons/logo.png";
/** 標題欄面板 */
private JPanel titlePanel;
/** 鼠標點擊初始位置,用于窗口拖拽 */
private Point initialClick;
/** 窗口是否最大化標志 */
@Setter
private boolean maximized = false;
/** 窗口是否已最大化 */
private boolean isMaximized = false;
private boolean maximizedDisable = false;
/** 窗口正常狀態(tài)下的邊界 */
private Rectangle normalBounds;
/** 圖標和標題面板 */
JPanel iconTitlePanel;
/** 標題標簽 */
private JLabel titleLabel;
/** 最小化按鈕 */
private JLabel minButton;
/** 最大化/還原按鈕 */
private JLabel maxButton;
/** 關閉按鈕 */
private JLabel closeButton;
/** 關閉按鈕事件 */
private Runnable closeAction;
/** 圓角半徑 */
private int cornerRadius = 15;
/** 是否正在調整窗口大小 */
private boolean isResizing = false;
/** 邊界檢測區(qū)域寬度 */
@Setter
private int resizeBorder = 10;
/** 當前調整方向 */
private int resizeDirection = 0;
/** 調整方向常量 */
private static final int NONE = 0;
private static final int TOP = 1;
private static final int BOTTOM = 2;
private static final int LEFT = 4;
private static final int RIGHT = 8;
private static final int TOP_LEFT = TOP | LEFT;
private static final int TOP_RIGHT = TOP | RIGHT;
private static final int BOTTOM_LEFT = BOTTOM | LEFT;
private static final int BOTTOM_RIGHT = BOTTOM | RIGHT;
/** 當前窗口所在的屏幕設備 */
private GraphicsDevice currentScreenDevice;
/** 父窗口引用,用于新窗口跟隨 */
@Setter
private CusFrame parentFrame;
/** 記錄窗口是否已經初始化位置 */
private boolean locationInitialized = false;
/** 記錄窗口的原始位置 */
private Point originalLocation;
/** 記錄窗口的原始大小 */
private Dimension originalSize;
/**
* 默認構造函數
*/
public CusFrame() throws HeadlessException {
this(null, null);
}
/**
* 帶標題的構造函數
* @param title 窗口標題
*/
public CusFrame(String title) throws HeadlessException {
this(title, null);
}
/**
* 帶標題和父窗口的構造函數
* @param title 窗口標題
* @param parentFrame 父窗口
*/
public CusFrame(String title, CusFrame parentFrame) throws HeadlessException {
this.parentFrame = parentFrame;
// 移除默認標題欄
setUndecorated(true);
// 設置窗口初始大小
setSize(new Dimension(800, 600));
// 創(chuàng)建自定義標題欄
createCustomTitleBar(title);
// 設置內容區(qū)域
setupContentArea();
// 設置圓角
setShape(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), cornerRadius, cornerRadius));
// 設置默認關閉方式
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 注:這里獲取圖片 需自行實現
setIconImage(xxxxxx);
// 保存正常狀態(tài)下的邊界
normalBounds = getBounds();
// 初始化當前屏幕設備
updateCurrentScreenDevice();
// 添加窗口大小變化監(jiān)聽器,更新圓角形狀
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
setShape(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), cornerRadius, cornerRadius));
}
@Override
public void componentMoved(ComponentEvent e) {
updateCurrentScreenDevice();
}
@Override
public void componentShown(ComponentEvent e) {
if (maximized) {
SwingUtilities.invokeLater(() -> {
toggleMaximize();
maximized = false;
});
}
}
});
}
/**
* 更新當前窗口所在的屏幕設備
*/
private void updateCurrentScreenDevice() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = ge.getScreenDevices();
Rectangle windowBounds = getBounds();
int centerX = windowBounds.x + windowBounds.width / 2;
int centerY = windowBounds.y + windowBounds.height / 2;
for (GraphicsDevice screen : screens) {
Rectangle screenBounds = screen.getDefaultConfiguration().getBounds();
if (screenBounds.contains(centerX, centerY)) {
currentScreenDevice = screen;
break;
}
}
if (currentScreenDevice == null) {
currentScreenDevice = ge.getDefaultScreenDevice();
}
}
/**
* 獲取當前窗口所在的屏幕設備
* @return 當前屏幕設備
*/
public GraphicsDevice getCurrentScreenDevice() {
if (currentScreenDevice == null) {
updateCurrentScreenDevice();
}
return currentScreenDevice;
}
/**
* 創(chuàng)建自定義標題欄
* @param title 標題文本
*/
private void createCustomTitleBar(String title) {
// 創(chuàng)建標題欄主面板
titlePanel = new JPanel(new BorderLayout());
// 左側:圖標和標題
iconTitlePanel = new JPanel(new BorderLayout());
iconTitlePanel.setOpaque(false);
iconTitlePanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
// 初始化標題標簽
titleLabel = new JLabel(title);
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
titleLabel.setForeground(Color.BLACK);
titleLabel.setBorder(BorderFactory.createEmptyBorder(8, 5, 5, 5));
// 使用包裝面板確保垂直居中
JPanel titleWrapper = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
titleWrapper.setOpaque(false);
titleWrapper.add(titleLabel);
iconTitlePanel.add(titleWrapper, BorderLayout.CENTER);
// 右側:窗口控制按鈕
JPanel buttonPanel = new JPanel(new BorderLayout());
buttonPanel.setOpaque(false);
buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
rightPanel.setOpaque(false);
// 最小化按鈕,圖片只是實例
minButton = createWindowBtn("icons/window/minimize.png", () -> setState(JFrame.ICONIFIED));
// 最大化/還原按鈕
maxButton = createWindowBtn("icons/window/maximize.png", this::toggleMaximize);
// 關閉按鈕
closeButton = createWindowBtn("icons/window/close.png", () -> {
if (null != closeAction) {
closeAction.run();
} else {
dispose();
}
});
rightPanel.add(minButton);
rightPanel.add(maxButton);
rightPanel.add(closeButton);
// 使用包裝面板確保按鈕垂直居中
JPanel buttonWrapper = new JPanel(new BorderLayout());
buttonWrapper.setOpaque(false);
buttonWrapper.add(rightPanel, BorderLayout.CENTER);
buttonPanel.add(buttonWrapper, BorderLayout.CENTER);
// 添加拖拽功能
addDragFunctionality(titlePanel);
// 將左右面板添加到標題欄
titlePanel.add(iconTitlePanel, BorderLayout.WEST);
titlePanel.add(buttonPanel, BorderLayout.EAST);
// 將標題欄添加到窗口頂部
getContentPane().add(titlePanel, BorderLayout.NORTH);
}
/**
* 關閉按鈕監(jiān)聽事件
* @param closeAction 關閉事件
*/
public void addCloseAction(Runnable closeAction) {
this.closeAction = closeAction;
}
/**
* 關閉按鈕監(jiān)聽事件(帶圖標)
* @param iconPath 圖標路徑
* @param closeAction 關閉事件
*/
public void addCloseAction(String iconPath, Runnable closeAction) {
// 注:根據iconPath獲取圖片需自行實現
ImageIcon icon = xxxxxx;
closeButton.setIcon(icon);
this.closeAction = closeAction;
}
/**
* 創(chuàng)建窗口控制按鈕
* @param iconPath 圖標路徑
* @param runnable 按鈕點擊時執(zhí)行的操作
* @return 創(chuàng)建的按鈕標簽
*/
private static JLabel createWindowBtn(String iconPath, Runnable runnable) {
// 注:根據iconPath獲取圖片需自行實現
ImageIcon icon = xxxxxx;
JLabel button = new JLabel(icon);
JLabel button = new JLabel();
button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
button.setBorder(BorderFactory.createEmptyBorder(8, 5, 8, 5));
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (null != runnable) {
runnable.run();
}
}
});
return button;
}
/**
* 設置內容區(qū)域并添加邊界調整監(jiān)聽器
*/
private void setupContentArea() {
// 創(chuàng)建內容面板
JPanel contentPanel = new JPanel(new BorderLayout());
getContentPane().add(contentPanel, BorderLayout.CENTER);
// 創(chuàng)建邊界調整監(jiān)聽器實例
ResizeMouseListener resizeListener = new ResizeMouseListener();
ResizeMouseMotionListener resizeMotionListener = new ResizeMouseMotionListener();
// 為整個窗口添加邊界調整監(jiān)聽器
addMouseListener(resizeListener);
addMouseMotionListener(resizeMotionListener);
// 為內容面板添加邊界調整監(jiān)聽器
contentPanel.addMouseListener(resizeListener);
contentPanel.addMouseMotionListener(resizeMotionListener);
// 為標題面板添加邊界調整監(jiān)聽器
titlePanel.addMouseListener(resizeListener);
titlePanel.addMouseMotionListener(resizeMotionListener);
// 為根面板添加邊界調整監(jiān)聽器
getRootPane().addMouseListener(resizeListener);
getRootPane().addMouseMotionListener(resizeMotionListener);
}
/**
* 為面板添加拖拽功能
* @param panel 要添加拖拽功能的面板
*/
private void addDragFunctionality(JPanel panel) {
MouseAdapter ma = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (resizeDirection == NONE) {
initialClick = e.getPoint();
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (isResizing) {
handleResize(e);
} else if (resizeDirection == NONE && !maximizedDisable) {
// 如果窗口是最大化的,先還原再移動
if (isMaximized) {
toggleMaximize();
int x = e.getXOnScreen() - getWidth() / 2;
int y = e.getYOnScreen() - titlePanel.getHeight() / 2;
setLocation(x, y);
initialClick = new Point(getWidth() / 2, titlePanel.getHeight() / 2);
}
int thisX = getLocation().x;
int thisY = getLocation().y;
int xMoved = e.getX() - initialClick.x;
int yMoved = e.getY() - initialClick.y;
setLocation(thisX + xMoved, thisY + yMoved);
}
}
@Override
public void mouseClicked(MouseEvent e) {
// 雙擊標題欄最大化/還原
if (e.getClickCount() == 2 && resizeDirection == NONE && !maximizedDisable) {
toggleMaximize();
}
}
};
panel.addMouseListener(ma);
panel.addMouseMotionListener(ma);
}
/**
* 切換窗口最大化/還原狀態(tài)
*/
public void toggleMaximize() {
if (isMaximized) {
// 還原到正常大小
setBounds(normalBounds);
isMaximized = false;
// 注:獲取圖片需自行實現
ImageIcon icon = xxxxxx;
maxButton.setIcon(icon);
} else {
// 保存當前位置和大小
normalBounds = getBounds();
originalLocation = getLocation();
// 獲取當前屏幕的最大可用邊界
GraphicsConfiguration config = getCurrentScreenDevice().getDefaultConfiguration();
Rectangle screenBounds = config.getBounds();
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(config);
int x = screenBounds.x + screenInsets.left;
int y = screenBounds.y + screenInsets.top;
int width = screenBounds.width - screenInsets.left - screenInsets.right;
int height = screenBounds.height - screenInsets.top - screenInsets.bottom;
setBounds(x, y, width, height);
isMaximized = true;
// 注:獲取圖片需自行實現
ImageIcon icon = xxxxxx;
maxButton.setIcon(icon);
}
}
/**
* 禁用最大化功能
*/
public void setMaximizedDisable() {
maximizedDisable = true;
}
/**
* 設置窗口圖標
* @param imagePath 圖標路徑
* @param width 圖標寬度
* @param height 圖標高度
*/
public void setIcon(String imagePath, int width, int height) {
// 注:根據imagePath獲取圖片需自行實現
ImageIcon icon = xxxxxx;
titleLabel.setIcon(icon);
titleLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
titleLabel.setVerticalTextPosition(SwingConstants.CENTER);
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 5));
int margin = (Math.max(height, 24) - 24) / 2;
minButton.setBorder(BorderFactory.createEmptyBorder(margin, 5, margin, 5));
maxButton.setBorder(BorderFactory.createEmptyBorder(margin, 5, margin, 5));
closeButton.setBorder(BorderFactory.createEmptyBorder(margin, 5, margin, 5));
iconTitlePanel.revalidate();
iconTitlePanel.repaint();
}
/**
* 設置窗口標題
* @param title 標題文本
*/
@Override
public void setTitle(String title) {
titleLabel.setText(title);
titleLabel.setVisible(true);
iconTitlePanel.revalidate();
iconTitlePanel.repaint();
}
/**
* 設置窗口標題和字體
* @param title 標題文本
* @param font 字體
*/
public void setTitle(String title, Font font) {
titleLabel.setText(title);
titleLabel.setFont(font);
titleLabel.setVisible(true);
iconTitlePanel.revalidate();
iconTitlePanel.repaint();
}
/**
* 設置標題欄樣式
* @param operate 自定義操作
*/
public void setTitleStyle(BiConsumer<JPanel, JLabel> operate) {
if (null != operate) {
operate.accept(titlePanel, titleLabel);
}
}
/**
* 設置標題欄下劃線(默認顏色)
*/
public void setUnderLine() {
setUnderLine(new Color(0, 183, 195));
}
/**
* 設置標題欄下劃線顏色
* @param color 下劃線顏色
*/
public void setUnderLine(Color color) {
setUnderLine(color, 1);
}
/**
* 設置標題欄下劃線
* @param color 下劃線顏色
* @param thickness 下劃線厚度
*/
public void setUnderLine(Color color, int thickness) {
titlePanel.setBorder(BorderFactory.createMatteBorder(0, 0, thickness, 0, color));
}
/**
* 隱藏最小化和最大化按鈕
*/
public void hideMinMax() {
minButton.setVisible(false);
maxButton.setVisible(false);
}
/**
* 設置圓角半徑
* @param radius 圓角半徑
*/
public void setCornerRadius(int radius) {
this.cornerRadius = radius;
setShape(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), cornerRadius, cornerRadius));
repaint();
}
/**
* 邊界調整大小的鼠標監(jiān)聽器
*/
private class ResizeMouseListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (resizeDirection != NONE) {
isResizing = true;
}
}
@Override
public void mouseReleased(MouseEvent e) {
isResizing = false;
resizeDirection = NONE;
setCursor(Cursor.getDefaultCursor());
}
}
/**
* 邊界調整大小的鼠標移動監(jiān)聽器
*/
private class ResizeMouseMotionListener extends MouseMotionAdapter {
@Override
public void mouseDragged(MouseEvent e) {
if (isResizing) {
handleResize(e);
}
}
@Override
public void mouseMoved(MouseEvent e) {
updateCursor(e.getPoint());
}
}
/**
* 更新鼠標光標
* @param p 鼠標位置點
*/
private void updateCursor(Point p) {
if (isMaximized) {
setCursor(Cursor.getDefaultCursor());
resizeDirection = NONE;
return;
}
int x = p.x;
int y = p.y;
int width = getWidth();
int height = getHeight();
boolean top = y < resizeBorder;
boolean bottom = y > height - resizeBorder - titlePanel.getHeight();
boolean left = x < resizeBorder;
boolean right = x > width - resizeBorder;
if (top && left) {
setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
resizeDirection = TOP_LEFT;
} else if (top && right) {
setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
resizeDirection = TOP_RIGHT;
} else if (bottom && left) {
setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
resizeDirection = BOTTOM_LEFT;
} else if (bottom && right) {
setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
resizeDirection = BOTTOM_RIGHT;
} else if (top) {
setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
resizeDirection = TOP;
} else if (bottom) {
setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
resizeDirection = BOTTOM;
} else if (left) {
setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
resizeDirection = LEFT;
} else if (right) {
setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
resizeDirection = RIGHT;
} else {
setCursor(Cursor.getDefaultCursor());
resizeDirection = NONE;
}
}
/**
* 處理調整大小
* @param e 鼠標事件
*/
private void handleResize(MouseEvent e) {
if (!isResizing) {
return;
}
int x = getX();
int y = getY();
int width = getWidth();
int height = getHeight();
int newX = x;
int newY = y;
int newWidth = width;
int newHeight = height;
if ((resizeDirection & LEFT) != 0) {
newX = e.getXOnScreen();
newWidth = width - (e.getXOnScreen() - x);
}
if ((resizeDirection & RIGHT) != 0) {
newWidth = e.getXOnScreen() - x;
}
if ((resizeDirection & TOP) != 0) {
newY = e.getYOnScreen();
newHeight = height - (e.getYOnScreen() - y);
}
if ((resizeDirection & BOTTOM) != 0) {
newHeight = e.getYOnScreen() - y;
}
int minWidth = 400;
int minHeight = 300;
if (newWidth < minWidth) {
if ((resizeDirection & LEFT) != 0) {
newX = x + width - minWidth;
}
newWidth = minWidth;
}
if (newHeight < minHeight) {
if ((resizeDirection & TOP) != 0) {
newY = y + height - minHeight;
}
newHeight = minHeight;
}
setBounds(newX, newY, newWidth, newHeight);
}
@Override
public void setVisible(boolean visible) {
if (visible) {
if (!locationInitialized) {
if (parentFrame != null) {
setLocationRelativeTo(parentFrame);
} else {
setLocationRelativeTo(null);
}
locationInitialized = true;
} else {
if (originalLocation != null) {
setLocation(originalLocation);
}
}
originalLocation = getLocation();
originalSize = getSize();
} else {
originalLocation = getLocation();
originalSize = getSize();
}
super.setVisible(visible);
}
/**
* 在指定屏幕居中顯示
* @param screenDevice 目標屏幕設備
*/
public void setLocationToScreen(GraphicsDevice screenDevice) {
if (screenDevice != null) {
Rectangle screenBounds = screenDevice.getDefaultConfiguration().getBounds();
int x = screenBounds.x + (screenBounds.width - getWidth()) / 2;
int y = screenBounds.y + (screenBounds.height - getHeight()) / 2;
setLocation(x, y);
currentScreenDevice = screenDevice;
originalLocation = getLocation();
locationInitialized = true;
}
}
/**
* 確保窗口在當前屏幕顯示
*/
public void ensureOnCurrentScreen() {
if (originalLocation != null) {
setLocation(originalLocation);
} else if (currentScreenDevice != null) {
setLocationToScreen(currentScreenDevice);
}
}
/**
* 保存當前位置信息
*/
public void saveCurrentLocation() {
this.originalLocation = getLocation();
this.originalSize = getSize();
updateCurrentScreenDevice();
}
/**
* 快速顯示窗口(帶內容組件)
* @param component 內容組件
* @param closeAction 關閉回調
*/
public void showFrame(JComponent component, Runnable closeAction) {
add(component);
setSize(new Dimension(1300, 800));
setTitleStyle((titlePanel, titleLabel) -> {
titlePanel.setOpaque(true);
titlePanel.setBackground(Color.decode("#CDE6E6"));
titlePanel.setBorder(BorderFactory.createEmptyBorder(5, 50, 5, 10));
// 注:獲取圖片需自行實現
ImageIcon icon = xxxxxx;
titleLabel.setIcon(icon);
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 20));
});
hideMinMax();
addCloseAction("icons/window/goback.png", () -> {
if (null != closeAction) {
closeAction.run();
}
});
setMaximized(true);
if (parentFrame != null) {
setLocationToScreen(parentFrame.getCurrentScreenDevice());
} else {
ensureOnCurrentScreen();
}
setVisible(true);
}
/**
* 創(chuàng)建跟隨父窗口的新窗口
* @param title 窗口標題
* @return 新的CusFrame實例
*/
public CusFrame createChildFrame(String title) {
CusFrame childFrame = new CusFrame(title, this);
childFrame.setLocationToScreen(this.getCurrentScreenDevice());
return childFrame;
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(new Color(0, 183, 195));
g2d.setStroke(new BasicStroke(1));
g2d.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, cornerRadius, cornerRadius);
g2d.dispose();
}
}
三、核心功能說明
窗口裝飾:
- setUndecorated(true):移除系統(tǒng)默認標題欄
- setShape(new RoundRectangle2D.Double(...)):設置圓角矩形形狀
- paint(Graphics g):繪制圓角邊框
自定義標題欄:
- 左側:圖標 + 標題文字
- 右側:最小化、最大化/還原、關閉按鈕
- 支持拖拽移動窗口
- 支持雙擊標題欄最大化/還原
窗口調整大?。?/strong>
- 鼠標移動到窗口邊緣時自動改變光標樣式
- 支持八個方向的拖拽調整(上、下、左、右、四個角)
- 置了最小寬度400px、最小高度300px
多屏幕適配:
- updateCurrentScreenDevice():檢測窗口當前所在的屏幕
- setLocationToScreen():在指定屏幕居中顯示
- ensureOnCurrentScreen():確保窗口在當前屏幕內可見
窗口狀態(tài)管理:
- toggleMaximize():切換最大化/還原,最大化時排除系統(tǒng)任務欄區(qū)域
- setMaximizedDisable():禁用最大化功能
- saveCurrentLocation():保存窗口位置,用于重新顯示時恢復
四、使用示例
4.1 創(chuàng)建基本窗口
CusFrame frame = new CusFrame("我的應用");
frame.setSize(1000, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
4.2 設置窗口圖標
// 注:圖片獲取需自行實現
frame.setIcon("icons/my_logo.png", 32, 32);
4.3 自定義標題欄樣式
frame.setTitleStyle((titlePanel, titleLabel) -> {
titlePanel.setBackground(new Color(50, 50, 80));
titleLabel.setForeground(Color.WHITE);
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 18));
});
frame.setUnderLine(new Color(100, 150, 200), 2);
4.4 禁用最大化
frame.setMaximizedDisable(); frame.hideMinMax();
4.5 設置關閉回調
frame.addCloseAction(() -> {
int result = JOptionPane.showConfirmDialog(frame, "確認退出?", "提示", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
System.exit(0);
}
});
4.6 多窗口跟隨(子窗口跟隨父窗口屏幕)
CusFrame mainFrame = new CusFrame("主窗口");
mainFrame.setSize(1200, 800);
mainFrame.setVisible(true);
CusFrame childFrame = mainFrame.createChildFrame("子窗口");
childFrame.setSize(600, 400);
childFrame.setVisible(true);
五、注意事項
- 代碼中涉及圖標加載的地方已注釋,需要讀者自行實現或替換
- 代碼中所有png圖片均為實例,可自行從網上下載
- 圓角邊框:最大化時會暫時禁用圓角(避免系統(tǒng)任務欄區(qū)域顯示異常)
- 線程安全:窗口操作已在 EDT 中執(zhí)行,無需額外處理
- 多屏幕:最大化時只在當前屏幕內最大化,不會跨屏幕
到此這篇關于Java Swing實現自定義窗口CusFrame的文章就介紹到這了,更多相關Java Swing自定義窗口內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot集成Apache POI實現Excel的導入導出
Apache POI是一個流行的Java庫,用于處理Microsoft Office格式文件,包括Excel文件,本文主要介紹了SpringBoot集成Apache POI實現Excel的導入導出,具有一定的參考價值,感興趣的可以了解一下2024-06-06
SpringBoot多環(huán)境打包與配置文件排除實踐記錄
本文介紹了SpringBoot項目多環(huán)境打包與配置文件排除實踐,包括多環(huán)境配置的實現方法、打包時排除配置文件的方法以及動態(tài)加載外部配置文件的最佳實踐,感興趣的朋友跟隨小編一起看看吧2024-11-11

