update qt

This commit is contained in:
ivaquero
2026-04-10 17:09:45 +08:00
parent cb2101db7f
commit 736f5b3a3b
12 changed files with 870 additions and 451 deletions
-26
View File
@@ -1,26 +0,0 @@
CompileFlags:
Add:
[
-Wno-documentation,
-Wno-missing-prototypes,
-std=c++17,
--include-directory=/opt/homebrew/include,
--include-directory=/opt/homebrew/include/QtGui,
--include-directory=/opt/homebrew/include/QtCore,
--include-directory=/opt/homebrew/include/QtWidgets,
]
Diagnostics:
ClangTidy:
Add:
[
performance-*,
bugprone-*,
modernize-*,
clang-analyzer-*,
readability-identifier*,
]
CheckOptions:
readability-identifier-naming.VariableCase: camelCase
Suppress: [-Wdeprecated-declarations]
+34 -4
View File
@@ -1,6 +1,36 @@
{ {
"includePath": "/opt/homebrew/include", "configurations": [
"compilerPath": "/usr/bin/clang++", {
"cStandard": "c11", "name": "macos-conda-qt",
"cppStandard": "c++17" "includePath": [
"${workspaceFolder}/**",
"${env:HOMEBREW_CELLAR}/qt/6.11.0/include/**",
],
"defines": [],
"compilerPath": "/usr/bin/clang++",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-arm64",
"configurationProvider": "kylinideteam.cmake-intellisence"
},
{
"name": "win-conda-qt",
"includePath": [
"${workspaceFolder}/**",
"${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\include",
"${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\include\\qt"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"compilerPath": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin\\g++.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-gcc-x64",
"configurationProvider": "kylinideteam.cmake-intellisence"
}
],
"version": 4
} }
+58
View File
@@ -0,0 +1,58 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Qt6",
"type": "cppdbg",
"request": "launch",
"targetArchitecture": "arm64",
"program": "${fileDirname}/${fileBasenameNoExtension}",
"args": [],
"stopAtEntry": false,
"externalConsole": false,
"cwd": "${fileDirname}",
"environment": [
{
"name": "DYLD_LIBRARY_PATH",
"value": "${env:HOMEBREW_CELLAR}/qt/6.11.0/lib"
}
],
"MIMode": "lldb",
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "Debug Qt6 on Windows",
"type": "cppdbg",
"request": "launch",
"targetArchitecture": "x86_64",
"program": "${fileDirname}/${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"externalConsole": false,
"cwd": "${fileDirname}",
"MIMode": "gdb",
"miDebuggerPath": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin\\gdb.exe",
"internalConsoleOptions": "openOnSessionStart",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": false
}
]
},
{
"name": "C/C++: clang++ build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}/${fileBasenameNoExtension}",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "lldb",
"preLaunchTask": "Build Qt6"
}
]
}
+78
View File
@@ -0,0 +1,78 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "Build Qt6",
"command": "/usr/bin/clang++",
"args": [
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
"-I",
"${env:HOMEBREW_CELLAR}/qtbase/6.11.0/include",
"-L",
"${env:HOMEBREW_CELLAR}/qtbase/6.11.0/lib",
"-lQt6Core",
"-lQt6Gui",
"-lQt6Widgets"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": "build"
},
{
"type": "cppbuild",
"label": "Build Qt6 on Windows",
"command": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}.exe",
"-I",
"${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\include",
"-I",
"${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\include\\qt6",
"-L",
"${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\lib",
"-lQt6Core",
"-lQt6Gui",
"-lQt6Widgets"
],
"options": {
"cwd": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin"
},
"problemMatcher": [
"$gcc"
],
"group": "build"
},
{
"type": "cppbuild",
"label": "C/C++: g++.exe build active file",
"command": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${env:SCOOP}\\apps\\msys2-cn\\current\\ucrt64\\bin"
},
"problemMatcher": [
"$gcc"
],
"group": "build",
"detail": "Task generated by Debugger."
}
]
}
+40 -10
View File
@@ -4,7 +4,10 @@ if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif() endif()
project(clock) project(FloatingClock)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
@@ -13,18 +16,45 @@ set(CMAKE_CXX_STANDARD 17 CACHE STRING "v")
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_PREFIX_PATH "/opt/homebrew/opt/qt")
find_package(Qt6 COMPONENTS Core Gui Widgets REQUIRED) # Homebrew Qt6 路径 (自动检测或手动设置)
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# 检测架构
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(QT6_PATH "/opt/homebrew/opt/qt" CACHE PATH "Qt6 installation path")
else()
set(QT6_PATH "/usr/local/opt/qt" CACHE PATH "Qt6 installation path")
endif()
include_directories(.) # 添加到 CMake 搜索路径
list(APPEND CMAKE_PREFIX_PATH "${QT6_PATH}/lib/cmake")
endif()
set (SRCS find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Xml)
flock.cpp
flock.h add_executable(${CMAKE_PROJECT_NAME} WIN32 MACOSX_BUNDLE main.cpp)
main.cpp
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
) )
add_executable(${CMAKE_PROJECT_NAME} ${SRCS}) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Qt6 Qt6::Core
Qt6::Gui
Qt6::Widgets
Qt6::Xml
)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets) # macOS 特定设置
if(APPLE)
set_target_properties(FloatingClock PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/Info.plist.in
)
# 修复运行时库路径
set_target_properties(FloatingClock PROPERTIES
INSTALL_RPATH "${QT6_PATH}/lib"
BUILD_WITH_INSTALL_RPATH TRUE
)
endif()
-166
View File
@@ -1,166 +0,0 @@
import sys
from PySide6.QtCore import QPoint, QSettings, Qt, QTime, QTimer
from PySide6.QtGui import QAction, QFont, QMouseEvent
from PySide6.QtWidgets import QApplication, QLabel, QMenu, QVBoxLayout, QWidget
class Clock(QWidget):
def __init__(self, parent=None) -> None:
super().__init__(parent)
# geometry of Mmin window (x, y, width, height)
self.setGeometry(1100, 800, 180, 60)
# hide frame
self.setWindowFlag(Qt.WindowStaysOnTopHint, True)
self.setWindowFlag(Qt.FramelessWindowHint, True)
self.setAttribute(Qt.WA_TranslucentBackground)
# mouse & menu
self.pressed = False
self.oldPos = QPoint(0, 0)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.mouseRightMenu)
# clock object
clock = QTimer(self)
clock.timeout.connect(self.showTime)
clock.start(1000) # update the clock per second
self.show()
self.settings = QSettings(f"{sys.argv[0]}/../config.ini", QSettings.IniFormat)
font = QFont()
font.setFamily(self.settings.value("USER/FONT_FAMILY"))
font.setPointSize(int(self.settings.value("USER/FONT_SIZE")))
# load settings
self.settings = QSettings(f"{sys.argv[0]}/../config.ini", QSettings.IniFormat)
# # font object
self.font = QFont()
self.font.setFamily(self.settings.value("DEFAULT/FONT_FAMILY"))
self.font_size_step = int(self.settings.value("USER/FONT_SIZE_STEP"))
# label object
self.label = QLabel()
self.label.setAlignment(Qt.AlignCenter)
# layout
layout = QVBoxLayout(self, spacing=0)
layout.addWidget(self.label)
self.setLayout(layout)
self.reloadUI()
def reloadUI(self):
self.font_size = int(self.settings.value("USER/FONT_SIZE"))
self.font.setPointSize(self.font_size)
self.label.setFont(self.font)
self.label.setStyleSheet(
f"color: {self.settings.value('USER/FONT_COLOR')}; "
f"background-color: {self.settings.value('USER/BG_COLOR')}"
)
def resetUI(self):
default_bg_color = self.settings.value("DEFAULT/BG_COLOR")
default_font_color = self.settings.value("DEFAULT/FONT_COLOR")
default_font_size = self.settings.value("DEFAULT/FONT_SIZE")
self.settings.setValue("USER/BG_COLOR", default_bg_color)
self.settings.setValue("USER/FONT_COLOR", default_font_color)
self.settings.setValue("USER/FONT_SIZE", default_font_size)
self.reloadUI()
def increaseFontSize(self):
self.font_size += self.font_size_step
self.changeFontSize()
def decreaseFontSize(self):
self.font_size -= self.font_size_step
self.changeFontSize()
def changeFontSize(self):
font = self.label.font()
font.setPointSize(self.font_size)
self.label.setFont(font)
def setFontColor(self, color: str) -> None:
self.settings.setValue("USER/FONT_COLOR", color)
self.reloadUI()
def setBackgroundColor(self, color: str) -> None:
self.settings.setValue("USER/BG_COLOR", color)
self.reloadUI()
def mousePressEvent(self, event: QMouseEvent) -> None:
self.pressed = True
self.oldPos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event: QMouseEvent) -> None:
if self.pressed:
self.move(self.pos() + (event.pos() - self.oldPos))
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event: QMouseEvent) -> None:
self.pressed = False
self.oldPos = event.pos()
super().mouseReleaseEvent(event)
def mouseRightMenu(self, pos) -> None:
menu = QMenu(self)
# font size
font_size_menu = menu.addMenu("font size")
larger_action = QAction("larger", self)
smaller_action = QAction("smaller", self)
larger_action.triggered.connect(self.increaseFontSize)
smaller_action.triggered.connect(self.decreaseFontSize)
font_size_menu.addAction(larger_action)
font_size_menu.addAction(smaller_action)
ft_colors = ["none", "blue", "orange", "green", "red", "yellow", "white"]
bg_colors = ["none", "blue", "orange", "green", "red", "yellow", "white"]
# font color
font_color_menu = menu.addMenu("font color")
font_color_actions = [
QAction(color, self, triggered=lambda c=color: self.setFontColor(c))
for color in ft_colors
]
font_color_menu.addActions(font_color_actions)
# background color
bg_color_menu = menu.addMenu("bg color")
bg_color_actions = [
QAction(color, self, triggered=lambda c=color: self.setBackgroundColor(c))
for color in bg_colors
]
bg_color_menu.addActions(bg_color_actions)
# reset
reset_action = QAction("reset", self)
reset_action.triggered.connect(self.resetUI)
menu.addAction(reset_action)
# quit
quit_action = QAction("quit", self)
quit_action.triggered.connect(self.close)
menu.addAction(quit_action)
menu.exec(self.mapToGlobal(pos))
def showTime(self):
current_time = QTime.currentTime().toString("hh:mm")
self.label.setText(current_time)
if __name__ == "__main__":
app = QApplication(sys.argv)
clock = Clock()
clock.show() # show all the widgets
app.exit(app.exec()) # start the app
-13
View File
@@ -1,13 +0,0 @@
[DEFAULT]
BG_COLOR=NONE
FONT_COLOR=blue
FONT_FAMILY=Arial
FONT_SIZE=50
FONT_SIZE_STEP=10
[USER]
BG_COLOR=NONE
FONT_COLOR=blue
FONT_FAMILY=Arial
FONT_SIZE=50
FONT_SIZE_STEP=10
+41
View File
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 浮动时钟配置文件 -->
<ClockConfig>
<!-- 窗口设置 -->
<Window>
<Width>350</Width>
<Height>180</Height>
<PosX>-1</PosX> <!-- -1表示屏幕居中 -->
<PosY>-1</PosY>
<BorderRadius>20</BorderRadius>
<BorderWidth>2</BorderWidth>
<BorderColor>#333333</BorderColor>
</Window>
<!-- 字体设置 -->
<Font>
<Size>96</Size>
<Family>Arial</Family>
<Bold>true</Bold>
<Italic>false</Italic>
<Color>#ff6600</Color>
</Font>
<!-- 背景设置 -->
<Background>
<Color>#1a000000</Color> <!-- 半透明黑色背景 -->
</Background>
<!-- 时间格式 -->
<Time>
<Format>HH:mm:ss</Format>
</Time>
<!-- 阴影效果 -->
<Shadow>
<BlurRadius>30</BlurRadius>
<OffsetX>4</OffsetX>
<OffsetY>4</OffsetY>
<Color>#80000000</Color>
</Shadow>
</ClockConfig>
-176
View File
@@ -1,176 +0,0 @@
#include "flock.h"
Clock::Clock(QWidget *parent) : QWidget{parent}, pressed(false) {
// geometry of Main Window (x, y, width, height)
setGeometry(1100, 800, 180, 60);
// hide frame
setWindowFlag(Qt::WindowStaysOnTopHint, true);
setWindowFlag(Qt::FramelessWindowHint, true);
setAttribute(Qt::WA_TranslucentBackground);
// setFixedSize(this->width(), this->height());
setWindowFlags(windowFlags() & ~Qt::WindowMaximizeButtonHint &
~Qt::WindowMinimizeButtonHint);
// clock object
QTimer *clock = new QTimer(this);
connect(clock, &QTimer::timeout, this, &Clock::showTime);
clock->start(1000); // update the clock per second
show();
settings = new QSettings(
QString("%1/config.ini").arg(QCoreApplication::applicationDirPath()),
QSettings::IniFormat);
font = QFont();
font.setFamily(settings->value("USER/FONT_FAMILY").toString());
font.setPointSize(settings->value("USER/FONT_SIZE").toInt());
// load settings
settings = new QSettings(QString("%1/../floating-clock/config.ini")
.arg(QCoreApplication::applicationDirPath()),
QSettings::IniFormat);
// font object
font = QFont();
font.setFamily(settings->value("DEFAULT/FONT_FAMILY").toString());
font_size_step = settings->value("USER/FONT_SIZE_STEP").toInt();
// label object
label = new QLabel();
label->setAlignment(Qt::AlignCenter);
// layout
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(label);
setLayout(layout);
reloadUI();
}
void Clock::showTime() {
QString current_time = QTime::currentTime().toString("hh:mm");
label->setText(current_time);
}
void Clock::reloadUI() {
font_size = settings->value("USER/FONT_SIZE").toInt();
font.setPointSize(font_size);
label->setFont(font);
label->setStyleSheet(QString("color: %1; background-color: %2")
.arg(settings->value("USER/FONT_COLOR").toString(),
settings->value("USER/BG_COLOR").toString()));
}
void Clock::resetUI() {
QString default_bg_color = settings->value("DEFAULT/BG_COLOR").toString();
QString default_font_color = settings->value("DEFAULT/FONT_COLOR").toString();
QString default_font_size = settings->value("DEFAULT/FONT_SIZE").toString();
settings->setValue("USER/BG_COLOR", default_bg_color);
settings->setValue("USER/FONT_COLOR", default_font_color);
settings->setValue("USER/FONT_SIZE", default_font_size);
reloadUI();
}
void Clock::increaseFontSize() {
font_size += font_size_step;
changeFontSize();
}
void Clock::decreaseFontSize() {
font_size -= font_size_step;
changeFontSize();
}
void Clock::changeFontSize() {
font.setPointSize(font_size);
label->setFont(font);
}
void Clock::setFontColor(const QString &color) {
settings->setValue("USER/FONT_COLOR", color);
reloadUI();
}
void Clock::setBackgroundColor(const QString &color) {
settings->setValue("USER/BG_COLOR", color);
reloadUI();
}
void Clock::mousePressEvent(QMouseEvent *event) {
pressed = true;
oldPos = event->pos();
QWidget::mousePressEvent(event);
}
void Clock::mouseMoveEvent(QMouseEvent *event) {
if (pressed) {
move(pos() + (event->pos() - oldPos));
}
QWidget::mouseMoveEvent(event);
}
void Clock::mouseReleaseEvent(QMouseEvent *event) {
pressed = false;
oldPos = event->pos();
QWidget::mouseReleaseEvent(event);
}
void Clock::contextMenuEvent(QContextMenuEvent *event) {
QMenu *menu = new QMenu();
// menu->setFixedWidth(100);
// font size
QMenu *font_size_menu = menu->addMenu("font size");
QAction *larger_action = new QAction("larger", this);
QAction *smaller_action = new QAction("smaller", this);
connect(larger_action, &QAction::triggered, this, &Clock::increaseFontSize);
connect(smaller_action, &QAction::triggered, this, &Clock::decreaseFontSize);
font_size_menu->addAction(larger_action);
font_size_menu->addAction(smaller_action);
QStringList ft_colors = {"none", "blue", "orange", "green",
"red", "yellow", "white"};
QStringList bg_colors = {"none", "blue", "orange", "green",
"red", "yellow", "white"};
// font color
QMenu *font_color_menu = menu->addMenu("font color");
QList<QAction *> font_color_actions;
for (const QString &color : ft_colors) {
QAction *action = new QAction(color, this);
connect(action, &QAction::triggered, [=]() { setFontColor(color); });
font_color_actions.append(action);
}
font_color_menu->addActions(font_color_actions);
// background color
QMenu *bg_color_menu = menu->addMenu("bg color");
QList<QAction *> bg_color_actions;
for (const QString &color : bg_colors) {
QAction *action = new QAction(color, this);
connect(action, &QAction::triggered, [=]() { setBackgroundColor(color); });
bg_color_actions.append(action);
}
bg_color_menu->addActions(bg_color_actions);
// reset
QAction *reset_action = new QAction("reset", this);
connect(reset_action, &QAction::triggered, this, &Clock::resetUI);
menu->addAction(reset_action);
// quit
QAction *quit_action = new QAction("quit", this);
connect(quit_action, &QAction::triggered, this, &Clock::close);
menu->addAction(quit_action);
// menu.exec(mapToGlobal(pos));
menu->exec(event->globalPos());
delete menu;
}
-52
View File
@@ -1,52 +0,0 @@
#ifndef CLOCK_H
#define CLOCK_H
#include <QApplication>
#include <QLabel>
#include <QLocale>
#include <QMenu>
#include <QMouseEvent>
#include <QPoint>
#include <QSettings>
#include <QTime>
#include <QTimer>
#include <QTranslator>
#include <QVBoxLayout>
#include <QWidget>
class Clock : public QWidget {
Q_OBJECT
public:
explicit Clock(QWidget *parent = nullptr);
void reloadUI();
void resetUI();
void increaseFontSize();
void decreaseFontSize();
void changeFontSize();
void setFontColor(const class QString &color);
void setBackgroundColor(const class QString &color);
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseRightMenu(const QPoint &pos);
signals:
public slots:
void showTime();
private:
bool pressed;
QPoint oldPos;
QSettings *settings;
QFont font;
int font_size_step;
int font_size;
QLabel *label;
void contextMenuEvent(QContextMenuEvent *e) override;
};
#endif // CLOCK_H
+619 -3
View File
@@ -1,10 +1,626 @@
#include <QApplication> #include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QVBoxLayout>
#include <QTimer>
#include <QTime>
#include <QMouseEvent>
#include <QMenu>
#include <QFontDialog>
#include <QColorDialog>
#include <QSettings>
#include <QGraphicsDropShadowEffect>
#include <QScreen>
#include <QPainter>
#include <QPainterPath>
#include <QInputDialog>
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QDomDocument>
#include <QMessageBox>
#include "flock.h" class FloatingClock : public QWidget
{
Q_OBJECT
auto main(int argc, char *argv[]) -> int { public:
FloatingClock(QWidget *parent = nullptr) : QWidget(parent)
{
// 先加载XML配置(在创建UI之前)
loadXmlConfig();
// 无边框、置顶、透明背景
setWindowFlags(Qt::FramelessWindowHint |
Qt::WindowStaysOnTopHint |
Qt::Tool |
Qt::WindowDoesNotAcceptFocus);
setAttribute(Qt::WA_TranslucentBackground);
// 创建时间标签
timeLabel = new QLabel(this);
timeLabel->setAlignment(Qt::AlignCenter);
updateStyle();
// 布局
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(timeLabel);
layout->setContentsMargins(20, 20, 20, 20);
setLayout(layout);
// 添加阴影效果
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
shadow->setBlurRadius(shadowBlurRadius);
shadow->setColor(shadowColor);
shadow->setOffset(shadowOffsetX, shadowOffsetY);
timeLabel->setGraphicsEffect(shadow);
// 定时器更新
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &FloatingClock::updateTime);
timer->start(1000);
updateTime();
// 加载用户设置(覆盖XML默认值)
loadUserSettings();
// 调整大小
resize(windowWidth, windowHeight);
// 如果位置未设置,居中显示
if (windowPosX < 0 || windowPosY < 0)
{
moveToCenter();
}
else
{
move(windowPosX, windowPosY);
}
}
protected:
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton)
{
dragging = true;
dragPos = event->globalPosition().toPoint() - frameGeometry().topLeft();
event->accept();
}
else if (event->button() == Qt::RightButton)
{
showContextMenu(event->globalPosition().toPoint());
}
}
void mouseMoveEvent(QMouseEvent *event) override
{
if (dragging && (event->buttons() & Qt::LeftButton))
{
move(event->globalPosition().toPoint() - dragPos);
event->accept();
}
}
void mouseReleaseEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton)
{
dragging = false;
saveUserSettings();
}
}
void paintEvent(QPaintEvent *) override
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制半透明背景
if (bgColor.alpha() > 0)
{
QPainterPath path;
path.addRoundedRect(rect(), borderRadius, borderRadius);
painter.fillPath(path, bgColor);
// 绘制边框
if (borderWidth > 0)
{
QPen pen(borderColor);
pen.setWidth(borderWidth);
painter.setPen(pen);
painter.drawPath(path);
}
}
}
private slots:
void updateTime()
{
QTime time = QTime::currentTime();
QString text = time.toString(timeFormat);
timeLabel->setText(text);
}
void changeFontSize()
{
bool ok;
int size = QInputDialog::getInt(this, "字体大小", "请输入字体大小:",
fontSize, 6, 300, 1, &ok);
if (ok)
{
fontSize = size;
updateStyle();
saveUserSettings();
}
}
void changeFontColor()
{
QColor color = QColorDialog::getColor(fontColor, this, "选择字体颜色",
QColorDialog::ShowAlphaChannel);
if (color.isValid())
{
fontColor = color;
updateStyle();
saveUserSettings();
}
}
void changeBgColor()
{
QColor color = QColorDialog::getColor(bgColor, this, "选择背景颜色",
QColorDialog::ShowAlphaChannel);
if (color.isValid())
{
bgColor = color;
update();
saveUserSettings();
}
}
void resetSettings()
{
// 重新加载XML默认配置
loadXmlConfig();
updateStyle();
update();
moveToCenter();
saveUserSettings();
}
void quitApp()
{
qApp->quit();
}
private:
void showContextMenu(const QPoint &pos)
{
QMenu menu(this);
menu.setStyleSheet(R"(
QMenu {
background-color: #f0f0f0;
border: 1px solid #cccccc;
border-radius: 8px;
padding: 5px;
}
QMenu::item {
padding: 8px 25px;
border-radius: 4px;
}
QMenu::item:selected {
background-color: #e0e0e0;
}
QMenu::item::right-arrow {
image: none;
width: 10px;
height: 10px;
border-left: 6px solid #333;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
margin-right: 5px;
}
)");
QMenu *fontMenu = menu.addMenu("▶ 字体大小");
for (int size : {36, 48, 64, 72, 96, 120})
{
QAction *action = fontMenu->addAction(QString::number(size));
connect(action, &QAction::triggered, this, [this, size]()
{
fontSize = size;
updateStyle();
saveUserSettings(); });
}
fontMenu->addSeparator();
QAction *customSize = fontMenu->addAction("自定义...");
connect(customSize, &QAction::triggered, this, &FloatingClock::changeFontSize);
QMenu *colorMenu = menu.addMenu("▶ 字体颜色");
QList<QPair<QString, QColor>> colors = {
{"蓝色", QColor(0, 0, 255)},
{"红色", QColor(255, 0, 0)},
{"绿色", QColor(0, 128, 0)},
{"黑色", QColor(0, 0, 0)},
{"白色", QColor(255, 255, 255)},
{"橙色", QColor(255, 165, 0)},
{"紫色", QColor(128, 0, 128)}};
for (auto &c : colors)
{
QPixmap pixmap(16, 16);
pixmap.fill(c.second);
QAction *action = colorMenu->addAction(QIcon(pixmap), c.first);
connect(action, &QAction::triggered, this, [this, color = c.second]() mutable
{
fontColor = color;
updateStyle();
saveUserSettings(); });
}
colorMenu->addSeparator();
QAction *customColor = colorMenu->addAction("自定义...");
connect(customColor, &QAction::triggered, this, &FloatingClock::changeFontColor);
QMenu *bgMenu = menu.addMenu("▶ 背景颜色");
QList<QPair<QString, QColor>> bgColors = {
{"透明", QColor(255, 255, 255, 0)},
{"白色半透明", QColor(255, 255, 255, 180)},
{"黑色半透明", QColor(0, 0, 0, 180)},
{"灰色半透明", QColor(128, 128, 128, 180)},
{"蓝色半透明", QColor(0, 100, 200, 180)},
{"自定义...", QColor()}};
for (auto &c : bgColors)
{
if (c.first == "自定义...")
{
QAction *action = bgMenu->addAction(c.first);
connect(action, &QAction::triggered, this, &FloatingClock::changeBgColor);
}
else
{
QPixmap pixmap(16, 16);
pixmap.fill(c.second);
QAction *action = bgMenu->addAction(QIcon(pixmap), c.first);
connect(action, &QAction::triggered, this, [this, color = c.second]() mutable
{
bgColor = color;
update();
saveUserSettings(); });
}
}
menu.addSeparator();
QAction *resetAction = menu.addAction("重置");
connect(resetAction, &QAction::triggered, this, &FloatingClock::resetSettings);
menu.addSeparator();
QAction *quitAction = menu.addAction("退出");
connect(quitAction, &QAction::triggered, this, &FloatingClock::quitApp);
menu.exec(pos);
}
void updateStyle()
{
QFont font(fontFamily, fontSize, fontWeight ? QFont::Bold : QFont::Normal);
if (fontItalic)
font.setItalic(true);
timeLabel->setFont(font);
QString style = QString("color: %1;").arg(fontColor.name());
timeLabel->setStyleSheet(style);
}
void moveToCenter()
{
QScreen *screen = QApplication::primaryScreen();
QRect geo = screen->geometry();
move((geo.width() - width()) / 2, (geo.height() - height()) / 2);
}
// 加载XML配置文件
void loadXmlConfig()
{
QString xmlPath = QApplication::applicationDirPath() + "/clock.xml";
// 如果XML不存在,创建默认配置
if (!QFile::exists(xmlPath))
{
createDefaultXml(xmlPath);
}
QFile file(xmlPath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
setDefaultValues();
return;
}
QDomDocument doc;
QString errorMsg;
int errorLine, errorColumn;
if (!doc.setContent(&file, &errorMsg, &errorLine, &errorColumn))
{
qWarning() << "XML解析错误:" << errorMsg << "行:" << errorLine << "列:" << errorColumn;
setDefaultValues();
file.close();
return;
}
file.close();
QDomElement root = doc.documentElement();
if (root.tagName() != "ClockConfig")
{
qWarning() << "XML根节点错误";
setDefaultValues();
return;
}
// 解析Window节点
QDomElement window = root.firstChildElement("Window");
if (!window.isNull())
{
windowWidth = getXmlInt(window, "Width", 300);
windowHeight = getXmlInt(window, "Height", 150);
windowPosX = getXmlInt(window, "PosX", -1);
windowPosY = getXmlInt(window, "PosY", -1);
borderRadius = getXmlInt(window, "BorderRadius", 15);
borderWidth = getXmlInt(window, "BorderWidth", 0);
borderColor = parseColor(getXmlString(window, "BorderColor", "#cccccc"));
}
// 解析Font节点
QDomElement font = root.firstChildElement("Font");
if (!font.isNull())
{
fontSize = getXmlInt(font, "Size", 72);
fontFamily = getXmlString(font, "Family", "Microsoft YaHei");
fontWeight = getXmlBool(font, "Bold", true);
fontItalic = getXmlBool(font, "Italic", false);
fontColor = parseColor(getXmlString(font, "Color", "#0000ff"));
}
// 解析Background节点
QDomElement background = root.firstChildElement("Background");
if (!background.isNull())
{
bgColor = parseColor(getXmlString(background, "Color", "#00ffffff"));
}
// 解析Time节点
QDomElement time = root.firstChildElement("Time");
if (!time.isNull())
{
timeFormat = getXmlString(time, "Format", "HH:mm");
}
// 解析Shadow节点
QDomElement shadow = root.firstChildElement("Shadow");
if (!shadow.isNull())
{
shadowBlurRadius = getXmlInt(shadow, "BlurRadius", 20);
shadowOffsetX = getXmlInt(shadow, "OffsetX", 2);
shadowOffsetY = getXmlInt(shadow, "OffsetY", 2);
shadowColor = parseColor(getXmlString(shadow, "Color", "#64000000"));
}
}
// 创建默认XML文件
void createDefaultXml(const QString &path)
{
QFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
setDefaultValues();
return;
}
QTextStream stream(&file);
stream.setEncoding(QStringConverter::Utf8);
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<!-- 浮动时钟配置文件 -->\n"
<< "<ClockConfig>\n"
<< " <!-- 窗口设置 -->\n"
<< " <Window>\n"
<< " <Width>300</Width>\n"
<< " <Height>150</Height>\n"
<< " <PosX>-1</PosX> <!-- -1表示屏幕居中 -->\n"
<< " <PosY>-1</PosY>\n"
<< " <BorderRadius>15</BorderRadius>\n"
<< " <BorderWidth>0</BorderWidth> <!-- 0表示无边框 -->\n"
<< " <BorderColor>#cccccc</BorderColor>\n"
<< " </Window>\n"
<< "\n"
<< " <!-- 字体设置 -->\n"
<< " <Font>\n"
<< " <Size>72</Size>\n"
<< " <Family>Microsoft YaHei</Family>\n"
<< " <Bold>true</Bold>\n"
<< " <Italic>false</Italic>\n"
<< " <Color>#0000ff</Color> <!-- 蓝色 -->\n"
<< " </Font>\n"
<< "\n"
<< " <!-- 背景设置 -->\n"
<< " <Background>\n"
<< " <Color>#00ffffff</Color> <!-- ARGB格式,00表示完全透明 -->\n"
<< " </Background>\n"
<< "\n"
<< " <!-- 时间格式 -->\n"
<< " <Time>\n"
<< " <Format>HH:mm</Format> <!-- 可选: HH:mm:ss, h:mm AP 等 -->\n"
<< " </Time>\n"
<< "\n"
<< " <!-- 阴影效果 -->\n"
<< " <Shadow>\n"
<< " <BlurRadius>20</BlurRadius>\n"
<< " <OffsetX>2</OffsetX>\n"
<< " <OffsetY>2</OffsetY>\n"
<< " <Color>#64000000</Color> <!-- 半透明黑色阴影 -->\n"
<< " </Shadow>\n"
<< "</ClockConfig>\n";
file.close();
}
// 设置默认值
void setDefaultValues()
{
windowWidth = 300;
windowHeight = 150;
windowPosX = -1;
windowPosY = -1;
borderRadius = 15;
borderWidth = 0;
borderColor = QColor("#cccccc");
fontSize = 72;
fontFamily = "Microsoft YaHei";
fontWeight = true;
fontItalic = false;
fontColor = QColor("#0000ff");
bgColor = QColor("#00ffffff");
timeFormat = "HH:mm";
shadowBlurRadius = 20;
shadowOffsetX = 2;
shadowOffsetY = 2;
shadowColor = QColor("#64000000");
}
// XML辅助函数
int getXmlInt(const QDomElement &parent, const QString &tagName, int defaultValue)
{
QDomElement elem = parent.firstChildElement(tagName);
if (elem.isNull())
return defaultValue;
return elem.text().toInt();
}
bool getXmlBool(const QDomElement &parent, const QString &tagName, bool defaultValue)
{
QDomElement elem = parent.firstChildElement(tagName);
if (elem.isNull())
return defaultValue;
QString text = elem.text().toLower();
return text == "true" || text == "1" || text == "yes";
}
QString getXmlString(const QDomElement &parent, const QString &tagName, const QString &defaultValue)
{
QDomElement elem = parent.firstChildElement(tagName);
if (elem.isNull())
return defaultValue;
return elem.text();
}
// 加载用户设置(覆盖XML默认值)
void loadUserSettings()
{
QSettings settings("FloatingClock", "Settings");
if (settings.contains("fontSize"))
{
fontSize = settings.value("fontSize").toInt();
}
if (settings.contains("fontColor"))
{
fontColor = settings.value("fontColor").value<QColor>();
}
if (settings.contains("bgColor"))
{
bgColor = settings.value("bgColor").value<QColor>();
}
if (settings.contains("pos"))
{
QPoint pos = settings.value("pos").toPoint();
if (!pos.isNull())
move(pos);
}
}
// 保存用户设置
void saveUserSettings()
{
QSettings settings("FloatingClock", "Settings");
settings.setValue("fontSize", fontSize);
settings.setValue("fontColor", fontColor);
settings.setValue("bgColor", bgColor);
settings.setValue("pos", pos());
}
// 解析颜色字符串 (#RGB, #RRGGBB, #ARGB, #AARRGGBB)
QColor parseColor(const QString &str)
{
QString s = str.trimmed();
if (s.startsWith("#"))
s = s.mid(1);
bool ok;
uint val = s.toUInt(&ok, 16);
if (!ok)
return QColor();
switch (s.length())
{
case 3: // #RGB
return QColor(
((val >> 8) & 0xF) * 17,
((val >> 4) & 0xF) * 17,
(val & 0xF) * 17);
case 6: // #RRGGBB
return QColor((val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF);
case 8: // #AARRGGBB
return QColor(
(val >> 16) & 0xFF,
(val >> 8) & 0xFF,
val & 0xFF,
(val >> 24) & 0xFF);
default:
return QColor();
}
}
QLabel *timeLabel;
// XML配置项
int windowWidth, windowHeight;
int windowPosX, windowPosY;
int borderRadius;
int borderWidth;
QColor borderColor;
int fontSize;
QString fontFamily;
bool fontWeight;
bool fontItalic;
QColor fontColor;
QColor bgColor;
QString timeFormat;
int shadowBlurRadius;
int shadowOffsetX, shadowOffsetY;
QColor shadowColor;
bool dragging = false;
QPoint dragPos;
};
#include "main.moc"
int main(int argc, char *argv[])
{
QApplication app(argc, argv); QApplication app(argc, argv);
Clock clock; // 高分屏适配
app.setAttribute(Qt::AA_EnableHighDpiScaling, true);
app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
FloatingClock clock;
clock.show();
return app.exec(); return app.exec();
} }
-1
View File
@@ -1 +0,0 @@
pyside6