项目地址 https://github.com/btkrc/WallPaper


遇到的问题

  • QSS覆盖的问题

    用格式化字符串或者拼接的方式解决(不够灵活,最好自己绘图)

  • 子类获取父类的数据

    用信号传递。

  • close()方法内存释放问题

    close()方法其实是调用的hide(),如果没有指定父对象,子对象需要手动释放内存。

    Closes this widget. Returns true if the widget was closed; otherwise returns false.
    First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.
    If the widget has the Qt::WA_DeleteOnClose flag, the widget is also deleted. A close events is delivered to the widget no matter if the widget is visible or not.

    也就是说close()只是隐藏组件并没有释放内存,除非它的父对象被关闭。如果要彻底关闭需要手动释放指针指向的内存,或者设置Qt::WA_DeleteOnClose


QT里的mouseMoveEvent默认情况下只有鼠标按下时才会触发

Mouse move events will occur only when a mouse button is pressed down, unless mouse tracking has been enabled with QWidget::setMouseTracking().

我还写了几个功能函数判断矩阵,结果发现多此一举


源码

main.cpp

1
2
3
4
5
6
7
8
9
10
#include "WallPaper.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[]){
QApplication a(argc, argv);
WallPaper w;
w.show();
return a.exec();
}

WallPaper.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#pragma once

#include <QtWidgets/QWidget>
#include "ui_WallPaper.h"
#include <QMouseEvent>
#include <QPoint>
#include <QDebug>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QRect>
#include "SettingWidget.h"
#include <QtMultimedia/QMediaPlayer>
#include <QtMultiMediaWidgets/QVideoWidget>
#include <QtMultiMedia/QMediaPlaylist>
#include <QUrl>
#include <Windows.h>


class WallPaper : public QWidget {
Q_OBJECT

public:
WallPaper(QWidget *parent = Q_NULLPTR);
~WallPaper();
private:
Ui::WallPaperClass ui;

QPoint startCoor;
QSystemTrayIcon *systemTray;

bool isDraging;
SettingWidget *settingWidget;
QString myStyleSheet;
QMediaPlayer *player;
QVideoWidget *videoWidget;
QMediaPlaylist *playlist;

void iniUi();
void iniStyleSheet();
void iniConnect();
void iniSystemTray();


private slots:
void onBtnMinimiseClicked();
void onSystemTrayActivated(QSystemTrayIcon::ActivationReason reason);
void onBtnSettingClicked();
void onSelectImage(QString *fileName);
void onSelectWallPaper(QString *fileName);

protected:
void mousePressEvent(QMouseEvent *event)override;
void mouseMoveEvent(QMouseEvent *event)override;
void mouseReleaseEvent(QMouseEvent *event)override;

};

WallPaper.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "WallPaper.h"

WallPaper::WallPaper(QWidget *parent)
: QWidget(parent), isDraging(false),settingWidget(nullptr) {
ui.setupUi(this);
iniUi();
iniStyleSheet();
iniSystemTray();
iniConnect();
}

WallPaper::~WallPaper(){
}

void WallPaper::iniUi() {
settingWidget = nullptr;
player = new QMediaPlayer(this);
playlist = new QMediaPlaylist(this);
videoWidget = new QVideoWidget(this);
setWindowFlag(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
}

void WallPaper::iniStyleSheet() {
this->myStyleSheet = QString("\
#widget{\
border-image:url(%1);\
background-repeat:no-repeat;\
}\
QPushButton{\
background-color:pink;\
border-radius:10px;\
border:none;\
width:32px;\
height:32px;\
}\
QPushButton:hover{\
background-color:orange;\
}");
this->ui.widget->setStyleSheet(myStyleSheet.arg(":/WallPaper/Resources/wz.png"));
}

void WallPaper::iniConnect() {
QObject::connect(ui.btnMinimise, SIGNAL(clicked()), this, SLOT(onBtnMinimiseClicked()));
QObject::connect(this->systemTray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(onSystemTrayActivated(QSystemTrayIcon::ActivationReason)));
QObject::connect(ui.btnSetting, SIGNAL(clicked()), this, SLOT(onBtnSettingClicked()));
}

void WallPaper::iniSystemTray() {
/*系统托盘*/
systemTray = new QSystemTrayIcon(this);
systemTray->setIcon(QIcon(":/WallPaper/Resources/favicon.ico"));
systemTray->setVisible(true);
systemTray->setToolTip(QString(QStringLiteral("by btkrc")));
QMenu *menu = new QMenu(this);
menu->addAction(ui.actionExit);
systemTray->setContextMenu(menu);
}


void WallPaper::onSystemTrayActivated(QSystemTrayIcon::ActivationReason reason) {
if (reason == QSystemTrayIcon::Trigger) {
this->show();
systemTray->hide();
}
}

void WallPaper::onBtnSettingClicked(){
if (!settingWidget) {
/*从父类继承属性*/
settingWidget = new SettingWidget(this);
/*创建实例后连接槽函数*/
QObject::connect(settingWidget, SIGNAL(selectImage(QString *)), this, SLOT(onSelectImage(QString *)));
QObject::connect(settingWidget, SIGNAL(selectWallPaper(QString *)), this, SLOT(onSelectWallPaper(QString *)));

settingWidget->show();
settingWidget->move(QPoint(30, 30));
}
else {
settingWidget->close();
settingWidget = nullptr;
}
}

/*子类发射的信号,传递一个字符串指针*/
void WallPaper::onSelectImage(QString *fileName){
if (fileName)
this->ui.widget->setStyleSheet(myStyleSheet.arg(*fileName));
}

void WallPaper::onSelectWallPaper(QString *fileName){
if (fileName) {
/*没有父类,需要重新设置*/
videoWidget->setWindowFlag(Qt::FramelessWindowHint);
playlist->clear();
playlist->addMedia(QUrl::fromLocalFile("test.wmv"));

/*填充窗口*/
videoWidget->setAspectRatioMode(Qt::IgnoreAspectRatio);
player->setVideoOutput(videoWidget);
player->setPlaylist(playlist);
player->setMuted(true);
videoWidget->setFullScreen(true);//全屏
playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);

player->play();

videoWidget->show();

SetParent((HWND)(videoWidget->winId()), FindWindowEx(NULL, NULL, L"progman", NULL));

}
}

void WallPaper::mousePressEvent(QMouseEvent *event) {
startCoor = event->pos();//保存鼠标相对窗口的坐标
/*由于子组件不会触发此事件,所以要进行判断是否在主区域按下鼠标*/
isDraging = true;
QWidget::mousePressEvent(event);
}

void WallPaper::mouseMoveEvent(QMouseEvent *event) {
/*将返回值与鼠标左键枚举值进行位与运算*/
if (event->buttons() & Qt::LeftButton&&isDraging) {
this->move(event->globalPos() - startCoor);
}
QWidget::mouseMoveEvent(event);
}

void WallPaper::mouseReleaseEvent(QMouseEvent *event) {
isDraging = false;
QWidget::mouseReleaseEvent(event);
}

/*slots*/

void WallPaper::onBtnMinimiseClicked() {
this->hide();
systemTray->show();
}

/*slots end*/

SettingWidget.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#pragma once

#include <QtWidgets/QWidget>
#include "ui_SettingWidget.h"
#include <QFileDialog>
#include <QString>


class SettingWidget : public QWidget {
Q_OBJECT
public:
SettingWidget(QWidget*parent=Q_NULLPTR);

private:
Ui::SettingWidgetClass ui;

void iniUi();
void iniConnect();

signals:
void selectImage(QString *fileName);
void selectWallPaper(QString *fileName);

private slots:
void onBtnSelectImage();
void onBtnSelectWallPaper();
};

SettingWidget.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "SettingWidget.h"
SettingWidget::SettingWidget(QWidget *parent)
:QWidget(parent) {
ui.setupUi(this);
iniUi();
iniConnect();
}

void SettingWidget::iniUi() {
/*设置此属性,此指针指向的内存在关闭时会自动释放*/
setAttribute(Qt::WA_DeleteOnClose);
setStyleSheet("#widget{background-color:rgba(0,0,0,0.5);border-radius:10px;}\
QPushButton{color:orange;background-color:black;border-radius:10px;}");
}

void SettingWidget::iniConnect() {
QObject::connect(ui.btnSelectImage, SIGNAL(clicked()), this, SLOT(onBtnSelectImage()));
QObject::connect(ui.btnSelectWallPaper,SIGNAL(clicked()), this, SLOT(onBtnSelectWallPaper()));
}

void SettingWidget::onBtnSelectWallPaper(){
QString fileName("");//直接构造,不使用拷贝构造
fileName = QFileDialog::getOpenFileName(this, QString(QStringLiteral("选择一个视频")),
"../" + QApplication::applicationDirPath(),
"image (*.mp4;*.avi;*.wmv)");
if (fileName != "")
emit selectWallPaper(&fileName);
else
emit selectWallPaper(nullptr);

}

void SettingWidget::onBtnSelectImage() {
/*如果用户取消,则发送一个空指针*/
QString fileName("");
fileName = QFileDialog::getOpenFileName(this, QString(QStringLiteral("只支持png格式")), "", "image (*.png)");
if (fileName != "")
emit selectImage(&fileName);
else
emit selectImage(nullptr);
}

ui_WallPaper.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/********************************************************************************
** Form generated from reading UI file 'WallPaper.ui'
**
** Created by: Qt User Interface Compiler version 5.15.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef UI_WALLPAPER_H
#define UI_WALLPAPER_H

#include <QtCore/QVariant>
#include <QtGui/QIcon>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_WallPaperClass
{
public:
QAction *actionExit;
QWidget *widget;
QPushButton *btnSetting;
QPushButton *btnMinimise;
QPushButton *btnClose;

void setupUi(QWidget *WallPaperClass)
{
if (WallPaperClass->objectName().isEmpty())
WallPaperClass->setObjectName(QString::fromUtf8("WallPaperClass"));
WallPaperClass->resize(314, 471);
WallPaperClass->setMouseTracking(false);
WallPaperClass->setTabletTracking(false);
WallPaperClass->setWindowOpacity(1.000000000000000);
WallPaperClass->setStyleSheet(QString::fromUtf8(""));
actionExit = new QAction(WallPaperClass);
actionExit->setObjectName(QString::fromUtf8("actionExit"));
QIcon icon;
icon.addFile(QString::fromUtf8(":/WallPaper/Resources/\347\272\277\346\200\247\345\205\263\351\227\255.png"), QSize(), QIcon::Normal, QIcon::Off);
actionExit->setIcon(icon);
widget = new QWidget(WallPaperClass);
widget->setObjectName(QString::fromUtf8("widget"));
widget->setGeometry(QRect(0, 0, 311, 471));
widget->setMouseTracking(false);
btnSetting = new QPushButton(widget);
btnSetting->setObjectName(QString::fromUtf8("btnSetting"));
btnSetting->setGeometry(QRect(270, 90, 32, 23));
QIcon icon1;
icon1.addFile(QString::fromUtf8(":/WallPaper/Resources/xianxingshezhi.png"), QSize(), QIcon::Normal, QIcon::Off);
btnSetting->setIcon(icon1);
btnMinimise = new QPushButton(widget);
btnMinimise->setObjectName(QString::fromUtf8("btnMinimise"));
btnMinimise->setGeometry(QRect(270, 136, 32, 23));
QIcon icon2;
icon2.addFile(QString::fromUtf8(":/WallPaper/Resources/xianxingxiangxia.png"), QSize(), QIcon::Normal, QIcon::Off);
btnMinimise->setIcon(icon2);
btnClose = new QPushButton(widget);
btnClose->setObjectName(QString::fromUtf8("btnClose"));
btnClose->setGeometry(QRect(270, 182, 32, 23));
btnClose->setIcon(icon);

retranslateUi(WallPaperClass);
QObject::connect(btnClose, SIGNAL(clicked()), actionExit, SLOT(trigger()));
QObject::connect(actionExit, SIGNAL(triggered()), WallPaperClass, SLOT(close()));

QMetaObject::connectSlotsByName(WallPaperClass);
} // setupUi

void retranslateUi(QWidget *WallPaperClass)
{
WallPaperClass->setWindowTitle(QCoreApplication::translate("WallPaperClass", "WallPaper", nullptr));
actionExit->setText(QCoreApplication::translate("WallPaperClass", "\351\200\200\345\207\272", nullptr));
#if QT_CONFIG(tooltip)
actionExit->setToolTip(QCoreApplication::translate("WallPaperClass", "\351\200\200\345\207\272", nullptr));
#endif // QT_CONFIG(tooltip)
btnSetting->setText(QString());
btnMinimise->setText(QString());
btnClose->setText(QString());
} // retranslateUi

};

namespace Ui {
class WallPaperClass: public Ui_WallPaperClass {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_WALLPAPER_H