满屏飘动温馨提示窗口------Java Swing创意桌面应用开发
前言
在日常编程学习中,我们经常会遇到需要创建桌面应用程序的场景。今天我将分享一个基于Java Swing开发的创意桌面应用——满屏飘动温馨提示窗口。这个程序不仅具有实用价值,还展示了Swing图形界面编程的各种技巧。
项目概述
这是一个能够生成多个半透明浮动窗口的Java应用程序,每个窗口都显示一条温馨的提示信息。窗口会在屏幕随机位置显示,并配有优雅的淡入淡出效果。
主要特性
-
🎯 多窗口管理:同时创建和管理多达150个浮动窗口
-
🎨 美观UI:自定义标题栏、渐变背景、圆角边框
-
⚡ 智能文本适配:自动调整字体大小确保文字完整显示
-
🌈 随机配色:每个窗口都有独特的柔和配色
-
✨ 平滑动画:窗口关闭时的淡出效果
-
🎮 控制面板:实时监控和批量管理所有窗口
核心代码解析
1. 项目启动与初始化
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
TipWindowManager manager = new TipWindowManager();
manager.start();
});
}
使用SwingUtilities.invokeLater()确保GUI操作在事件分发线程中执行,这是Swing编程的最佳实践。
2. 控制面板创建
private void createControlPanel() {
controlFrame = new JFrame("温馨提示控制器");
// 设置窗口属性
controlFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
controlFrame.setSize(350, 180);
controlFrame.setLocation(100, 100);
controlFrame.setAlwaysOnTop(true);
// 创建UI组件
JLabel titleLabel = new JLabel("满屏温馨提示控制器", SwingConstants.CENTER);
statusLabel = new JLabel("正在创建窗口: 0/" + WINDOW_COUNT, SwingConstants.CENTER);
closeAllButton = new JButton("一键关闭所有窗口");
}
控制面板提供了:
-
实时状态显示
-
批量关闭功能
-
进度监控
3. 智能窗口创建机制
private void createRandomWindow() {
JDialog dialog = new JDialog();
dialog.setUndecorated(true); // 去除默认边框
// 固定窗口尺寸确保一致性
int windowWidth = 280;
int windowHeight = 150;
// 随机位置生成
int x = random.nextInt(Math.max(1, SCREEN_WIDTH - windowWidth - 10));
int y = random.nextInt(Math.max(1, SCREEN_HEIGHT - windowHeight - 10));
configureDialog(dialog, windowWidth, windowHeight, x, y);
}
4. 智能文本适配技术
这是项目的核心技术之一,解决了长文本显示不全的问题:
private JPanel createSmartMessagePanel(String text, Color bgColor, int panelWidth) {
// 计算合适的字体大小
int fontSize = calculateOptimalFontSize(text, panelWidth - 40);
// 创建智能标签
SmartTextLabel messageLabel = new SmartTextLabel(text, panelWidth - 30);
messageLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, fontSize));
return messagePanel;
}
private int calculateOptimalFontSize(String text, int availableWidth) {
String cleanText = text.replaceAll("<[^>]*>", "").replaceAll("[\\uD83C-\\uDBFF\\uDC00-\\uDFFF]", "");
int baseSize = 13;
int textLength = cleanText.length();
// 根据文本长度动态调整字体大小
if (textLength <= 6) {
baseSize = 15;
} else if (textLength <= 10) {
baseSize = 14;
} else if (textLength >= 15) {
baseSize = 11;
}
// 进一步根据可用宽度调整
Font testFont = new Font("Microsoft YaHei", Font.PLAIN, baseSize);
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(testFont);
int textWidth = metrics.stringWidth(cleanText);
if (textWidth > availableWidth * 0.9) {
baseSize = Math.max(10, baseSize - 1);
}
return baseSize;
}
5. 自定义文本标签类
private class SmartTextLabel extends JLabel {
private final String originalText;
private final int maxWidth;
public SmartTextLabel(String text, int maxWidth) {
this.originalText = text;
this.maxWidth = maxWidth;
setText(formatText(text));
}
private String formatText(String text) {
String cleanText = text.replaceAll("<[^>]*>", "");
if (cleanText.length() > 8 || containsEmoji(cleanText)) {
return "<html><div style='text-align: center; padding: 5px;'>" + cleanText + "</div></html>";
} else {
return "<html><div style='text-align: center; padding: 8px; font-size: 14px;'>" + cleanText + "</div></html>";
}
}
}
6. 优雅的关闭动画
private void closeWindowWithFade(JDialog dialog) {
Timer fadeTimer = new Timer(20, null);
fadeTimer.addActionListener(e -> {
try {
if (dialog.isVisible()) {
float opacity = dialog.getOpacity();
if (opacity > 0.1f) {
dialog.setOpacity(opacity - 0.05f);
} else {
fadeTimer.stop();
closeWindowImmediately(dialog);
}
}
} catch (Exception ex) {
fadeTimer.stop();
closeWindowImmediately(dialog);
}
});
fadeTimer.start();
}
技术亮点
1. 多线程处理
-
使用
SwingUtilities.invokeLater()确保线程安全 -
独立的窗口创建线程避免界面卡顿
-
状态更新线程实时反馈进度
2. 内存管理
-
使用
ArrayList管理活动窗口 -
窗口关闭时及时清理资源
-
AtomicInteger确保线程安全的计数
3. UI/UX优化
-
半透明效果提升视觉体验
-
柔和配色方案保护视力
-
响应式布局适配不同屏幕
4. 异常处理
try {
dialog.setOpacity(0.95f);
} catch (Exception e) {
// 透明度设置失败不影响主要功能
}
实际应用场景
-
桌面提醒工具 - 用于重要事项提醒
-
学习辅助 - 显示学习提示和鼓励语句
-
演示工具 - 展示Swing编程能力
-
UI组件库 - 可复用的窗口管理组件
总结
通过这个项目,我们不仅创建了一个实用的桌面应用,还深入学习了:
-
Swing高级组件使用
-
多线程在GUI编程中的应用
-
自定义UI组件开发
-
动画效果实现
-
内存管理和性能优化
这个项目充分展示了Java在桌面应用开发方面的能力,证明了即使在这个Web和移动应用为主的时代,桌面应用仍然有其独特的价值和魅力。
完整代码已在文末提供,欢迎大家下载学习、改进和扩展!
希望这篇博客对大家学习Java Swing编程有所帮助!如果有任何问题或建议,欢迎在评论区留言讨论。
完整代码如下
package com.datou.tipwindow;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 满屏飘动温馨提示窗口管理器
* 作者:DaTou
* 日期:2025年
*/
public class TipWindowManager {
// 配置常量
private static final int WINDOW_COUNT = 150; // 减少数量确保更好的显示效果
private static final int SCREEN_WIDTH = Toolkit.getDefaultToolkit().getScreenSize().width;
private static final int SCREEN_HEIGHT = Toolkit.getDefaultToolkit().getScreenSize().height;
// 窗口管理相关变量
private final List<JDialog> activeWindows = new ArrayList<>();
private final AtomicInteger windowsCreated = new AtomicInteger(0);
private final Random random = new Random();
// 控制窗口组件
private JFrame controlFrame;
private JButton closeAllButton;
private JLabel statusLabel;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
TipWindowManager manager = new TipWindowManager();
manager.start();
});
}
public void start() {
printStartInfo();
createControlPanel();
startWindowCreation();
}
/**
* 创建控制面板
*/
private void createControlPanel() {
controlFrame = new JFrame("温馨提示控制器");
controlFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
controlFrame.setSize(350, 180);
controlFrame.setLocation(100, 100);
controlFrame.setAlwaysOnTop(true);
JPanel controlPanel = new JPanel(new BorderLayout());
controlPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
controlPanel.setBackground(new Color(240, 240, 240));
JLabel titleLabel = new JLabel("满屏温馨提示控制器", SwingConstants.CENTER);
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
titleLabel.setForeground(new Color(0, 100, 200));
statusLabel = new JLabel("正在创建窗口: 0/" + WINDOW_COUNT, SwingConstants.CENTER);
statusLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
statusLabel.setForeground(Color.DARK_GRAY);
closeAllButton = new JButton("一键关闭所有窗口");
closeAllButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
closeAllButton.setBackground(new Color(220, 80, 80));
closeAllButton.setForeground(Color.WHITE);
closeAllButton.setEnabled(false);
closeAllButton.setFocusPainted(false);
closeAllButton.addActionListener(e -> closeAllWindows());
JPanel buttonPanel = new JPanel(new BorderLayout());
buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
buttonPanel.add(closeAllButton, BorderLayout.CENTER);
controlPanel.add(titleLabel, BorderLayout.NORTH);
controlPanel.add(statusLabel, BorderLayout.CENTER);
controlPanel.add(buttonPanel, BorderLayout.SOUTH);
controlFrame.add(controlPanel);
controlFrame.setVisible(true);
startStatusUpdateThread();
}
private void startStatusUpdateThread() {
new Thread(() -> {
try {
while (windowsCreated.get() < WINDOW_COUNT) {
SwingUtilities.invokeLater(() -> {
statusLabel.setText("正在创建窗口: " + windowsCreated.get() + "/" + WINDOW_COUNT);
});
Thread.sleep(100);
}
SwingUtilities.invokeLater(() -> {
statusLabel.setText("✅ 所有窗口创建完成!共 " + WINDOW_COUNT + " 个窗口");
closeAllButton.setEnabled(true);
closeAllButton.setBackground(new Color(76, 175, 80));
closeAllButton.setText("一键关闭所有窗口 (" + WINDOW_COUNT + "个)");
});
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
private void closeAllWindows() {
System.out.println("🚀 开始一键关闭所有窗口...");
closeAllButton.setEnabled(false);
closeAllButton.setBackground(new Color(255, 152, 0));
List<JDialog> windowsToClose = new ArrayList<>(activeWindows);
final int totalWindows = windowsToClose.size();
new Thread(() -> {
try {
int closedCount = 0;
for (JDialog window : windowsToClose) {
SwingUtilities.invokeLater(() -> closeWindowWithFade(window));
closedCount++;
final int currentCount = closedCount;
SwingUtilities.invokeLater(() -> {
closeAllButton.setText("关闭中: " + currentCount + "/" + totalWindows);
statusLabel.setText("正在关闭窗口: " + currentCount + "/" + totalWindows);
});
Thread.sleep(30);
}
SwingUtilities.invokeLater(() -> {
closeAllButton.setText("✅ 所有窗口已关闭");
closeAllButton.setBackground(new Color(33, 150, 243));
statusLabel.setText("🎉 所有窗口关闭完成!");
});
Thread.sleep(3000);
System.exit(0);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
private void startWindowCreation() {
Thread creationThread = new Thread(this::createWindowsRandomly);
creationThread.setDaemon(true);
creationThread.start();
}
private void createWindowsRandomly() {
System.out.println("🚀 开始创建对话框...");
long startTime = System.currentTimeMillis();
try {
while (windowsCreated.get() < WINDOW_COUNT) {
SwingUtilities.invokeLater(this::createRandomWindow);
Thread.sleep(random.nextInt(40) + 60);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
long endTime = System.currentTimeMillis();
System.out.println("⏱️ 所有 " + WINDOW_COUNT + " 个对话框创建完成!耗时: " +
(endTime - startTime) / 1000.0 + "秒");
}
private void createRandomWindow() {
if (windowsCreated.get() >= WINDOW_COUNT) return;
try {
JDialog dialog = new JDialog();
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
activeWindows.add(dialog);
windowsCreated.incrementAndGet();
// 固定窗口尺寸,确保文字显示完整
int windowWidth = 280; // 固定宽度
int windowHeight = 150; // 固定高度
// 随机位置
int x = random.nextInt(Math.max(1, SCREEN_WIDTH - windowWidth - 10));
int y = random.nextInt(Math.max(1, SCREEN_HEIGHT - windowHeight - 10));
configureDialog(dialog, windowWidth, windowHeight, x, y);
} catch (Exception e) {
System.err.println("创建窗口时出错: " + e.getMessage());
}
}
private void configureDialog(JDialog dialog, int width, int height, int x, int y) {
dialog.setUndecorated(true);
dialog.setBounds(x, y, width, height);
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
String tipText = getRandomTip();
Color bgColor = getRandomColor();
JPanel contentPanel = createContentPanel(tipText, bgColor, width);
dialog.setContentPane(contentPanel);
dialog.setAlwaysOnTop(true);
try {
dialog.setOpacity(0.95f);
} catch (Exception e) {
// 透明度设置失败不影响主要功能
}
dialog.setVisible(true);
}
/**
* 创建内容面板 - 修复文字显示不全问题
*/
private JPanel createContentPanel(String text, Color bgColor, int width) {
// 主面板
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.setBackground(bgColor);
// 创建标题栏
JPanel titlePanel = createTitlePanel();
// 创建内容区域 - 使用新的智能文本面板
JPanel contentPanel = createSmartMessagePanel(text, bgColor, width);
// 组装面板
mainPanel.add(titlePanel, BorderLayout.NORTH);
mainPanel.add(contentPanel, BorderLayout.CENTER);
// 设置边框
mainPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(100, 100, 100, 150), 2),
BorderFactory.createEmptyBorder(2, 2, 2, 2)
));
return mainPanel;
}
/**
* 创建标题栏面板
*/
private JPanel createTitlePanel() {
JPanel titlePanel = new JPanel(new BorderLayout());
titlePanel.setBackground(new Color(70, 130, 180));
titlePanel.setPreferredSize(new Dimension(0, 28));
titlePanel.setBorder(BorderFactory.createEmptyBorder(4, 12, 4, 12));
JLabel titleLabel = new JLabel("温馨提示");
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 13));
titleLabel.setForeground(Color.WHITE);
titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
JLabel iconLabel = new JLabel("💡");
iconLabel.setFont(new Font("Segoe UI Emoji", Font.PLAIN, 14));
titlePanel.add(iconLabel, BorderLayout.WEST);
titlePanel.add(titleLabel, BorderLayout.CENTER);
return titlePanel;
}
/**
* 智能消息面板 - 自动调整文字大小和换行
*/
private JPanel createSmartMessagePanel(String text, Color bgColor, int panelWidth) {
JPanel messagePanel = new JPanel(new BorderLayout());
messagePanel.setBackground(bgColor);
// 计算合适的字体大小
int fontSize = calculateOptimalFontSize(text, panelWidth - 40); // 减去边距
// 创建智能标签
SmartTextLabel messageLabel = new SmartTextLabel(text, panelWidth - 30);
messageLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, fontSize));
messageLabel.setForeground(new Color(47, 79, 79));
messageLabel.setHorizontalAlignment(SwingConstants.CENTER);
messageLabel.setVerticalAlignment(SwingConstants.CENTER);
// 设置合适的内边距
int verticalPadding = Math.max(10, (100 - getTextHeight(text, fontSize)) / 2);
messageLabel.setBorder(BorderFactory.createEmptyBorder(verticalPadding, 15, verticalPadding, 15));
messagePanel.add(messageLabel, BorderLayout.CENTER);
return messagePanel;
}
private class SmartTextLabel extends JLabel {
private final String originalText;
private final int maxWidth;
public SmartTextLabel(String text, int maxWidth) {
this.originalText = text;
this.maxWidth = maxWidth;
setText(formatText(text));
}
private String formatText(String text) {
String cleanText = text.replaceAll("<[^>]*>", "");
if (cleanText.length() > 8 || containsEmoji(cleanText)) {
return "<html><div style='text-align: center; padding: 5px;'>" + cleanText + "</div></html>";
} else {
return "<html><div style='text-align: center; padding: 8px; font-size: 14px;'>" + cleanText + "</div></html>";
}
}
private boolean containsEmoji(String text) {
return text.matches(".*[\\uD83C-\\uDBFF\\uDC00-\\uDFFF].*");
}
}
private int calculateOptimalFontSize(String text, int availableWidth) {
String cleanText = text.replaceAll("<[^>]*>", "").replaceAll("[\\uD83C-\\uDBFF\\uDC00-\\uDFFF]", "");
int baseSize = 13;
int textLength = cleanText.length();
// 根据文本长度调整字体大小
if (textLength <= 6) {
baseSize = 15;
} else if (textLength <= 10) {
baseSize = 14;
} else if (textLength >= 15) {
baseSize = 11;
}
// 进一步根据可用宽度调整
Font testFont = new Font("Microsoft YaHei", Font.PLAIN, baseSize);
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(testFont);
int textWidth = metrics.stringWidth(cleanText);
if (textWidth > availableWidth * 0.9) {
baseSize = Math.max(10, baseSize - 1);
}
return baseSize;
}
private int getTextHeight(String text, int fontSize) {
Font font = new Font("Microsoft YaHei", Font.PLAIN, fontSize);
FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
return metrics.getHeight();
}
private void closeWindowWithFade(JDialog dialog) {
if (!dialog.isVisible()) return;
Timer fadeTimer = new Timer(20, null);
fadeTimer.addActionListener(e -> {
try {
if (dialog.isVisible()) {
float opacity = dialog.getOpacity();
if (opacity > 0.1f) {
dialog.setOpacity(opacity - 0.05f);
} else {
fadeTimer.stop();
closeWindowImmediately(dialog);
}
}
} catch (Exception ex) {
fadeTimer.stop();
closeWindowImmediately(dialog);
}
});
fadeTimer.start();
}
private void closeWindowImmediately(JDialog dialog) {
SwingUtilities.invokeLater(() -> {
try {
if (dialog.isVisible()) {
dialog.dispose();
}
activeWindows.remove(dialog);
} catch (Exception e) {
System.err.println("关闭窗口时出错: " + e.getMessage());
}
});
}
/**
* 获取随机提示语 - 优化文本长度
*/
private String getRandomTip() {
String[] tips = {
"多喝水💧", "保持微笑😊", "元气满满✨", "吃水果🍎",
"好心情🌞", "爱自己❤️", "期待见面👋", "顺顺利利🎯",
"早点休息🌙", "烦恼消失🌈", "别熬夜⏰", "今天开心🎉",
"多穿衣服🧥", "保护眼睛👀", "珍惜当下🎁", "深呼吸🌬️",
"你真棒🎊", "一切会好🌻", "积极心态⚡", "加油🚀",
"幸福🎈", "温柔待人💝", "相信自己💪", "美好一天🌞",
"保持耐心⏳", "慢慢来🐢", "你很特别🌟", "世界美丽🌍"
};
return tips[random.nextInt(tips.length)];
}
private Color getRandomColor() {
Color[] colors = {
new Color(255, 240, 245), new Color(240, 255, 255),
new Color(245, 255, 250), new Color(255, 248, 220),
new Color(240, 248, 255), new Color(248, 248, 255),
new Color(245, 245, 245), new Color(250, 250, 210),
new Color(230, 230, 250), new Color(255, 228, 225),
new Color(255, 250, 240), new Color(253, 245, 230)
};
return colors[random.nextInt(colors.length)];
}
private void printStartInfo() {
System.out.println("=".repeat(60));
System.out.println("🎲 满屏温馨提示开始!");
System.out.println("🎯 目标: " + WINDOW_COUNT + " 个对话框");
System.out.println("💡 修复:文字显示完整优化");
System.out.println("🖥️ 屏幕尺寸: " + SCREEN_WIDTH + " x " + SCREEN_HEIGHT);
System.out.println("=".repeat(60));
}
}
更多推荐



所有评论(0)