新增无边框方案项目
parent
a4c35ec100
commit
47daf5e186
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
|
@ -1,6 +1,8 @@
|
||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
#定义了ordered表示子项目按照添加的顺序来编译
|
#定义了ordered表示子项目按照添加的顺序来编译
|
||||||
CONFIG += ordered
|
CONFIG += ordered
|
||||||
|
|
||||||
|
#挨个添加子项目
|
||||||
SUBDIRS += lightbutton #高亮按钮控件
|
SUBDIRS += lightbutton #高亮按钮控件
|
||||||
SUBDIRS += movewidget #通用控件移动类
|
SUBDIRS += movewidget #通用控件移动类
|
||||||
SUBDIRS += flatui #模仿flatui类
|
SUBDIRS += flatui #模仿flatui类
|
||||||
|
@ -35,7 +37,9 @@ SUBDIRS += imageswitch #图片开关控件
|
||||||
SUBDIRS += netserver #网络中转服务器
|
SUBDIRS += netserver #网络中转服务器
|
||||||
SUBDIRS += base64 #图片文字base64互换
|
SUBDIRS += base64 #图片文字base64互换
|
||||||
SUBDIRS += smoothcurve #平滑曲线
|
SUBDIRS += smoothcurve #平滑曲线
|
||||||
|
SUBDIRS += frameless #无边框方案支持win、linux、mac等
|
||||||
|
|
||||||
|
#限定windows系统加载下面的项目
|
||||||
win32 {
|
win32 {
|
||||||
SUBDIRS += ffmpegdemo #视频流播放ffmpeg内核
|
SUBDIRS += ffmpegdemo #视频流播放ffmpeg内核
|
||||||
SUBDIRS += vlcdemo #视频流播放vlc内核
|
SUBDIRS += vlcdemo #视频流播放vlc内核
|
||||||
|
@ -46,8 +50,10 @@ SUBDIRS += miniblink #miniblink示例
|
||||||
#如果你电脑对应的Qt版本有webkit或者webengine组件可以自行打开
|
#如果你电脑对应的Qt版本有webkit或者webengine组件可以自行打开
|
||||||
#SUBDIRS += echartgauge #echart仪表盘含交互支持webkit及webengine
|
#SUBDIRS += echartgauge #echart仪表盘含交互支持webkit及webengine
|
||||||
|
|
||||||
lessThan(QT_MAJOR_VERSION, 4) {
|
#这个项目依赖QtDesigner模块,一般在arm上默认没有这个模块需要自行编译
|
||||||
#SUBDIRS += designer #QtDesigner4源码
|
#所以arm上如果没有QtDesigner模块不要加载下面这个子项目
|
||||||
|
lessThan(QT_MAJOR_VERSION, 5) {
|
||||||
|
SUBDIRS += designer #QtDesigner4源码
|
||||||
}
|
}
|
||||||
|
|
||||||
#qwt项目需要等官方适配了qwt组件才能适配
|
#qwt项目需要等官方适配了qwt组件才能适配
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
1. **可以选择打开QWidgetDemo.pro一次性编译所有的,也可以进入到目录下打开pro进行编译。**
|
1. **可以选择打开QWidgetDemo.pro一次性编译所有的,也可以进入到目录下打开pro进行编译。**
|
||||||
2. **如果发现有些子项目没有加载请打开QWidgetDemo.pro仔细看里面的注释。**
|
2. **如果发现有些子项目没有加载请打开QWidgetDemo.pro仔细看里面的注释。**
|
||||||
3. **编译好的可执行文件在源码同级目录下的bin目录。**
|
3. **编译好的可执行文件在源码同级目录下的bin目录。**
|
||||||
4. **亲测Qt4.6到Qt6.1所有版本,亲测win、linux、mac、uos等系统。**
|
4. **亲测Qt4.6到Qt6.2所有版本,亲测win、linux、mac、uos等系统。**
|
||||||
|
|
||||||
| 编号 | 文件夹 | 描述 |
|
| 编号 | 文件夹 | 描述 |
|
||||||
| ------ | ------ | ------ |
|
| ------ | ------ | ------ |
|
||||||
|
@ -49,6 +49,7 @@
|
||||||
| 41 | miniblink | miniblink示例 |
|
| 41 | miniblink | miniblink示例 |
|
||||||
| 42 | base64 | 图片文字base64互换 |
|
| 42 | base64 | 图片文字base64互换 |
|
||||||
| 43 | smoothcurve | 平滑曲线 |
|
| 43 | smoothcurve | 平滑曲线 |
|
||||||
|
| 44 | frameless | 地表最强最简单无边框方案 |
|
||||||
|
|
||||||
### 二、学习群
|
### 二、学习群
|
||||||
1. **Qt交流大会群 853086607(雨田哥)**
|
1. **Qt交流大会群 853086607(雨田哥)**
|
||||||
|
@ -100,3 +101,4 @@
|
||||||
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/miniblink.jpg)
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/miniblink.jpg)
|
||||||
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/base64.png)
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/base64.png)
|
||||||
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/smoothcurve.gif)
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/smoothcurve.gif)
|
||||||
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/frameless.gif)
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include "appinit.h"
|
||||||
|
#include "qmutex.h"
|
||||||
|
#include "qapplication.h"
|
||||||
|
#include "qevent.h"
|
||||||
|
#include "qwidget.h"
|
||||||
|
|
||||||
|
QScopedPointer<AppInit> AppInit::self;
|
||||||
|
AppInit *AppInit::Instance()
|
||||||
|
{
|
||||||
|
if (self.isNull()) {
|
||||||
|
static QMutex mutex;
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
if (self.isNull()) {
|
||||||
|
self.reset(new AppInit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppInit::AppInit(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AppInit::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
QWidget *w = (QWidget *)watched;
|
||||||
|
if (!w->property("canMove").toBool()) {
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QPoint mousePoint;
|
||||||
|
static bool mousePressed = false;
|
||||||
|
|
||||||
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||||
|
if (mouseEvent->type() == QEvent::MouseButtonPress) {
|
||||||
|
if (mouseEvent->button() == Qt::LeftButton) {
|
||||||
|
mousePressed = true;
|
||||||
|
mousePoint = mouseEvent->globalPos() - w->pos();
|
||||||
|
}
|
||||||
|
} else if (mouseEvent->type() == QEvent::MouseButtonRelease) {
|
||||||
|
mousePressed = false;
|
||||||
|
} else if (mouseEvent->type() == QEvent::MouseMove) {
|
||||||
|
if (mousePressed) {
|
||||||
|
w->move(mouseEvent->globalPos() - mousePoint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppInit::start()
|
||||||
|
{
|
||||||
|
qApp->installEventFilter(this);
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef APPINIT_H
|
||||||
|
#define APPINIT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class AppInit : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static AppInit *Instance();
|
||||||
|
explicit AppInit(QObject *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QScopedPointer<AppInit> self;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void start();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // APPINIT_H
|
|
@ -0,0 +1,5 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>image/fontawesome-webfont.ttf</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
|
@ -0,0 +1,34 @@
|
||||||
|
#指定编译产生的文件分门别类放到对应目录
|
||||||
|
MOC_DIR = temp/moc
|
||||||
|
RCC_DIR = temp/rcc
|
||||||
|
UI_DIR = temp/ui
|
||||||
|
OBJECTS_DIR = temp/obj
|
||||||
|
|
||||||
|
#指定编译生成的可执行文件放到源码上一级目录下的bin目录
|
||||||
|
!android {
|
||||||
|
!wasm {
|
||||||
|
DESTDIR = $$PWD/../bin
|
||||||
|
}}
|
||||||
|
|
||||||
|
#把所有警告都关掉眼不见为净
|
||||||
|
CONFIG += warn_off
|
||||||
|
#开启大资源支持
|
||||||
|
CONFIG += resources_big
|
||||||
|
#开启后会将打印信息用控制台输出
|
||||||
|
#CONFIG += console
|
||||||
|
|
||||||
|
#引入全志H3芯片依赖
|
||||||
|
include ($$PWD/h3.pri)
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/appinit.h \
|
||||||
|
$$PWD/iconhelper.h \
|
||||||
|
$$PWD/quihelper.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/appinit.cpp \
|
||||||
|
$$PWD/iconhelper.cpp \
|
||||||
|
$$PWD/quihelper.cpp
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
$$PWD/common.qrc
|
|
@ -0,0 +1,6 @@
|
||||||
|
unix:!macx {
|
||||||
|
contains(DEFINES, arma7) {
|
||||||
|
INCLUDEPATH += /usr/local/openssl-1.0.2m-h3-gcc-4.9.2/include
|
||||||
|
LIBS += -L/usr/local/openssl-1.0.2m-h3-gcc-4.9.2/lib -lssl -lcrypto
|
||||||
|
LIBS += -L/usr/local/h3_rootfsv -lXdmcp
|
||||||
|
}}
|
|
@ -0,0 +1,351 @@
|
||||||
|
#include "iconhelper.h"
|
||||||
|
|
||||||
|
IconHelper *IconHelper::iconFontAliBaBa = 0;
|
||||||
|
IconHelper *IconHelper::iconFontAwesome = 0;
|
||||||
|
void IconHelper::initFont()
|
||||||
|
{
|
||||||
|
static bool isInit = false;
|
||||||
|
if (!isInit) {
|
||||||
|
isInit = true;
|
||||||
|
if (iconFontAliBaBa == 0) {
|
||||||
|
iconFontAliBaBa = new IconHelper(":/image/iconfont.ttf", "iconfont");
|
||||||
|
}
|
||||||
|
if (iconFontAwesome == 0) {
|
||||||
|
iconFontAwesome = new IconHelper(":/image/fontawesome-webfont.ttf", "FontAwesome");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setIcon(QLabel *lab, int icon, quint32 size)
|
||||||
|
{
|
||||||
|
initFont();
|
||||||
|
|
||||||
|
//自动根据不同的字体的值选择对应的类,fontawesome 0xf开头 iconfont 0xe开头
|
||||||
|
if (icon > 0xe000 && icon < 0xf000) {
|
||||||
|
iconFontAliBaBa->setIcon1(lab, icon, size);
|
||||||
|
} else if (icon > 0xf000) {
|
||||||
|
iconFontAwesome->setIcon1(lab, icon, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setIcon(QAbstractButton *btn, int icon, quint32 size)
|
||||||
|
{
|
||||||
|
initFont();
|
||||||
|
|
||||||
|
//自动根据不同的字体的值选择对应的类,fontawesome 0xf开头 iconfont 0xe开头
|
||||||
|
if (icon > 0xe000 && icon < 0xf000) {
|
||||||
|
iconFontAliBaBa->setIcon1(btn, icon, size);
|
||||||
|
} else if (icon > 0xf000) {
|
||||||
|
iconFontAwesome->setIcon1(btn, icon, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setPixmap(QAbstractButton *btn, const QColor &color, int icon, quint32 size,
|
||||||
|
quint32 width, quint32 height, int flags)
|
||||||
|
{
|
||||||
|
initFont();
|
||||||
|
|
||||||
|
//自动根据不同的字体的值选择对应的类,fontawesome 0xf开头 iconfont 0xe开头
|
||||||
|
if (icon > 0xe000 && icon < 0xf000) {
|
||||||
|
iconFontAliBaBa->setPixmap1(btn, color, icon, size, width, height, flags);
|
||||||
|
} else if (icon > 0xf000) {
|
||||||
|
iconFontAwesome->setPixmap1(btn, color, icon, size, width, height, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap IconHelper::getPixmap(const QColor &color, int icon, quint32 size,
|
||||||
|
quint32 width, quint32 height, int flags)
|
||||||
|
{
|
||||||
|
initFont();
|
||||||
|
|
||||||
|
//自动根据不同的字体的值选择对应的类,fontawesome 0xf开头 iconfont 0xe开头
|
||||||
|
QPixmap pix;
|
||||||
|
if (icon > 0xe000 && icon < 0xf000) {
|
||||||
|
pix = iconFontAliBaBa->getPixmap1(color, icon, size, width, height, flags);
|
||||||
|
} else if (icon > 0xf000) {
|
||||||
|
pix = iconFontAwesome->getPixmap1(color, icon, size, width, height, flags);
|
||||||
|
}
|
||||||
|
return pix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setStyle(QWidget *widget, QList<QPushButton *> btns,
|
||||||
|
QList<int> icons, const IconHelper::StyleColor &styleColor)
|
||||||
|
{
|
||||||
|
initFont();
|
||||||
|
|
||||||
|
//自动根据不同的字体的值选择对应的类,fontawesome 0xf开头 iconfont 0xe开头
|
||||||
|
int icon = icons.first();
|
||||||
|
if (icon > 0xe000 && icon < 0xf000) {
|
||||||
|
iconFontAliBaBa->setStyle1(widget, btns, icons, styleColor);
|
||||||
|
} else if (icon > 0xf000) {
|
||||||
|
iconFontAwesome->setStyle1(widget, btns, icons, styleColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setStyle(QWidget *widget, QList<QToolButton *> btns,
|
||||||
|
QList<int> icons, const IconHelper::StyleColor &styleColor)
|
||||||
|
{
|
||||||
|
initFont();
|
||||||
|
|
||||||
|
//自动根据不同的字体的值选择对应的类,fontawesome 0xf开头 iconfont 0xe开头
|
||||||
|
int icon = icons.first();
|
||||||
|
if (icon > 0xe000 && icon < 0xf000) {
|
||||||
|
iconFontAliBaBa->setStyle1(widget, btns, icons, styleColor);
|
||||||
|
} else if (icon > 0xf000) {
|
||||||
|
iconFontAwesome->setStyle1(widget, btns, icons, styleColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setStyle(QWidget *widget, QList<QAbstractButton *> btns,
|
||||||
|
QList<int> icons, const IconHelper::StyleColor &styleColor)
|
||||||
|
{
|
||||||
|
initFont();
|
||||||
|
|
||||||
|
//自动根据不同的字体的值选择对应的类,fontawesome 0xf开头 iconfont 0xe开头
|
||||||
|
int icon = icons.first();
|
||||||
|
if (icon > 0xe000 && icon < 0xf000) {
|
||||||
|
iconFontAliBaBa->setStyle1(widget, btns, icons, styleColor);
|
||||||
|
} else if (icon > 0xf000) {
|
||||||
|
iconFontAwesome->setStyle1(widget, btns, icons, styleColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconHelper::IconHelper(const QString &fontFile, const QString &fontName, QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
//判断图形字体是否存在,不存在则加入
|
||||||
|
QFontDatabase fontDb;
|
||||||
|
if (!fontDb.families().contains(fontName)) {
|
||||||
|
int fontId = fontDb.addApplicationFont(fontFile);
|
||||||
|
QStringList listName = fontDb.applicationFontFamilies(fontId);
|
||||||
|
if (listName.count() == 0) {
|
||||||
|
qDebug() << QString("load %1 error").arg(fontName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fontDb.families().contains(fontName)) {
|
||||||
|
iconFont = QFont(fontName);
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
|
||||||
|
iconFont.setHintingPreference(QFont::PreferNoHinting);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IconHelper::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
//根据不同的
|
||||||
|
if (watched->inherits("QAbstractButton")) {
|
||||||
|
QAbstractButton *btn = (QAbstractButton *)watched;
|
||||||
|
int index = btns.indexOf(btn);
|
||||||
|
if (index >= 0) {
|
||||||
|
//不同的事件设置不同的图标,同时区分选中的和没有选中的
|
||||||
|
if (btn->isChecked()) {
|
||||||
|
if (event->type() == QEvent::MouseButtonPress) {
|
||||||
|
QMouseEvent *mouseEvent = (QMouseEvent *)event;
|
||||||
|
if (mouseEvent->button() == Qt::LeftButton) {
|
||||||
|
btn->setIcon(QIcon(pixChecked.at(index)));
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::Enter) {
|
||||||
|
btn->setIcon(QIcon(pixChecked.at(index)));
|
||||||
|
} else if (event->type() == QEvent::Leave) {
|
||||||
|
btn->setIcon(QIcon(pixChecked.at(index)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (event->type() == QEvent::MouseButtonPress) {
|
||||||
|
QMouseEvent *mouseEvent = (QMouseEvent *)event;
|
||||||
|
if (mouseEvent->button() == Qt::LeftButton) {
|
||||||
|
btn->setIcon(QIcon(pixPressed.at(index)));
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::Enter) {
|
||||||
|
btn->setIcon(QIcon(pixHover.at(index)));
|
||||||
|
} else if (event->type() == QEvent::Leave) {
|
||||||
|
btn->setIcon(QIcon(pixNormal.at(index)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::toggled(bool checked)
|
||||||
|
{
|
||||||
|
//选中和不选中设置不同的图标
|
||||||
|
QAbstractButton *btn = (QAbstractButton *)sender();
|
||||||
|
int index = btns.indexOf(btn);
|
||||||
|
if (checked) {
|
||||||
|
btn->setIcon(QIcon(pixChecked.at(index)));
|
||||||
|
} else {
|
||||||
|
btn->setIcon(QIcon(pixNormal.at(index)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setIcon1(QLabel *lab, int icon, quint32 size)
|
||||||
|
{
|
||||||
|
iconFont.setPixelSize(size);
|
||||||
|
lab->setFont(iconFont);
|
||||||
|
lab->setText((QChar)icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setIcon1(QAbstractButton *btn, int icon, quint32 size)
|
||||||
|
{
|
||||||
|
iconFont.setPixelSize(size);
|
||||||
|
btn->setFont(iconFont);
|
||||||
|
btn->setText((QChar)icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setPixmap1(QAbstractButton *btn, const QColor &color, int icon, quint32 size,
|
||||||
|
quint32 width, quint32 height, int flags)
|
||||||
|
{
|
||||||
|
btn->setIcon(getPixmap1(color, icon, size, width, height, flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap IconHelper::getPixmap1(const QColor &color, int icon, quint32 size,
|
||||||
|
quint32 width, quint32 height, int flags)
|
||||||
|
{
|
||||||
|
//主动绘制图形字体到图片
|
||||||
|
QPixmap pix(width, height);
|
||||||
|
pix.fill(Qt::transparent);
|
||||||
|
|
||||||
|
QPainter painter;
|
||||||
|
painter.begin(&pix);
|
||||||
|
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||||
|
painter.setPen(color);
|
||||||
|
|
||||||
|
iconFont.setPixelSize(size);
|
||||||
|
painter.setFont(iconFont);
|
||||||
|
painter.drawText(pix.rect(), flags, (QChar)icon);
|
||||||
|
painter.end();
|
||||||
|
return pix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setStyle1(QWidget *widget, QList<QPushButton *> btns, QList<int> icons, const IconHelper::StyleColor &styleColor)
|
||||||
|
{
|
||||||
|
QList<QAbstractButton *> list;
|
||||||
|
foreach (QPushButton *btn, btns) {
|
||||||
|
list << btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle(widget, list, icons, styleColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setStyle1(QWidget *widget, QList<QToolButton *> btns, QList<int> icons, const IconHelper::StyleColor &styleColor)
|
||||||
|
{
|
||||||
|
QList<QAbstractButton *> list;
|
||||||
|
foreach (QToolButton *btn, btns) {
|
||||||
|
list << btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle(widget, list, icons, styleColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IconHelper::setStyle1(QWidget *widget, QList<QAbstractButton *> btns, QList<int> icons, const IconHelper::StyleColor &styleColor)
|
||||||
|
{
|
||||||
|
int btnCount = btns.count();
|
||||||
|
int iconCount = icons.count();
|
||||||
|
if (btnCount <= 0 || iconCount <= 0 || btnCount != iconCount) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString position = styleColor.position;
|
||||||
|
quint32 iconSize = styleColor.iconSize;
|
||||||
|
quint32 iconWidth = styleColor.iconWidth;
|
||||||
|
quint32 iconHeight = styleColor.iconHeight;
|
||||||
|
quint32 borderWidth = styleColor.borderWidth;
|
||||||
|
|
||||||
|
//根据不同的位置计算边框
|
||||||
|
QString strBorder;
|
||||||
|
if (position == "top") {
|
||||||
|
strBorder = QString("border-width:%1px 0px 0px 0px;padding-top:%1px;padding-bottom:%2px;")
|
||||||
|
.arg(borderWidth).arg(borderWidth * 2);
|
||||||
|
} else if (position == "right") {
|
||||||
|
strBorder = QString("border-width:0px %1px 0px 0px;padding-right:%1px;padding-left:%2px;")
|
||||||
|
.arg(borderWidth).arg(borderWidth * 2);
|
||||||
|
} else if (position == "bottom") {
|
||||||
|
strBorder = QString("border-width:0px 0px %1px 0px;padding-bottom:%1px;padding-top:%2px;")
|
||||||
|
.arg(borderWidth).arg(borderWidth * 2);
|
||||||
|
} else if (position == "left") {
|
||||||
|
strBorder = QString("border-width:0px 0px 0px %1px;padding-left:%1px;padding-right:%2px;")
|
||||||
|
.arg(borderWidth).arg(borderWidth * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果图标是左侧显示则需要让没有选中的按钮左侧也有加深的边框,颜色为背景颜色
|
||||||
|
QStringList qss;
|
||||||
|
if (styleColor.textBesideIcon) {
|
||||||
|
qss << QString("QWidget[flag=\"%1\"] QAbstractButton{border-style:solid;border-radius:0px;%2border-color:%3;color:%4;background:%5;}")
|
||||||
|
.arg(position).arg(strBorder).arg(styleColor.normalBgColor).arg(styleColor.normalTextColor).arg(styleColor.normalBgColor);
|
||||||
|
} else {
|
||||||
|
qss << QString("QWidget[flag=\"%1\"] QAbstractButton{border-style:none;border-radius:0px;padding:5px;color:%2;background:%3;}")
|
||||||
|
.arg(position).arg(styleColor.normalTextColor).arg(styleColor.normalBgColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
//悬停+按下+选中
|
||||||
|
qss << QString("QWidget[flag=\"%1\"] QAbstractButton:hover{border-style:solid;%2border-color:%3;color:%4;background:%5;}")
|
||||||
|
.arg(position).arg(strBorder).arg(styleColor.borderColor).arg(styleColor.hoverTextColor).arg(styleColor.hoverBgColor);
|
||||||
|
qss << QString("QWidget[flag=\"%1\"] QAbstractButton:pressed{border-style:solid;%2border-color:%3;color:%4;background:%5;}")
|
||||||
|
.arg(position).arg(strBorder).arg(styleColor.borderColor).arg(styleColor.pressedTextColor).arg(styleColor.pressedBgColor);
|
||||||
|
qss << QString("QWidget[flag=\"%1\"] QAbstractButton:checked{border-style:solid;%2border-color:%3;color:%4;background:%5;}")
|
||||||
|
.arg(position).arg(strBorder).arg(styleColor.borderColor).arg(styleColor.checkedTextColor).arg(styleColor.checkedBgColor);
|
||||||
|
|
||||||
|
//窗体背景颜色+按钮背景颜色
|
||||||
|
qss << QString("QWidget#%1{background:%2;}")
|
||||||
|
.arg(widget->objectName()).arg(styleColor.normalBgColor);
|
||||||
|
qss << QString("QWidget>QAbstractButton{border-width:0px;background-color:%1;color:%2;}")
|
||||||
|
.arg(styleColor.normalBgColor).arg(styleColor.normalTextColor);
|
||||||
|
qss << QString("QWidget>QAbstractButton:hover{background-color:%1;color:%2;}")
|
||||||
|
.arg(styleColor.hoverBgColor).arg(styleColor.hoverTextColor);
|
||||||
|
qss << QString("QWidget>QAbstractButton:pressed{background-color:%1;color:%2;}")
|
||||||
|
.arg(styleColor.pressedBgColor).arg(styleColor.pressedTextColor);
|
||||||
|
qss << QString("QWidget>QAbstractButton:checked{background-color:%1;color:%2;}")
|
||||||
|
.arg(styleColor.checkedBgColor).arg(styleColor.checkedTextColor);
|
||||||
|
|
||||||
|
//设置样式表
|
||||||
|
widget->setStyleSheet(qss.join(""));
|
||||||
|
|
||||||
|
//可能会重复调用设置所以先要移除上一次的
|
||||||
|
for (int i = 0; i < btnCount; i++) {
|
||||||
|
for (int j = 0; j < this->btns.count(); j++) {
|
||||||
|
if (this->btns.at(j) == btns.at(i)) {
|
||||||
|
disconnect(btns.at(i), SIGNAL(toggled(bool)), this, SLOT(toggled(bool)));
|
||||||
|
this->btns.at(j)->removeEventFilter(this);
|
||||||
|
this->btns.removeAt(j);
|
||||||
|
this->pixNormal.removeAt(j);
|
||||||
|
this->pixHover.removeAt(j);
|
||||||
|
this->pixPressed.removeAt(j);
|
||||||
|
this->pixChecked.removeAt(j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//存储对应按钮对象,方便鼠标移上去的时候切换图片
|
||||||
|
int checkedIndex = -1;
|
||||||
|
for (int i = 0; i < btnCount; i++) {
|
||||||
|
int icon = icons.at(i);
|
||||||
|
QPixmap pixNormal = getPixmap1(styleColor.normalTextColor, icon, iconSize, iconWidth, iconHeight);
|
||||||
|
QPixmap pixHover = getPixmap1(styleColor.hoverTextColor, icon, iconSize, iconWidth, iconHeight);
|
||||||
|
QPixmap pixPressed = getPixmap1(styleColor.pressedTextColor, icon, iconSize, iconWidth, iconHeight);
|
||||||
|
QPixmap pixChecked = getPixmap1(styleColor.checkedTextColor, icon, iconSize, iconWidth, iconHeight);
|
||||||
|
|
||||||
|
//记住最后选中的按钮
|
||||||
|
QAbstractButton *btn = btns.at(i);
|
||||||
|
if (btn->isChecked()) {
|
||||||
|
checkedIndex = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
btn->setIcon(QIcon(pixNormal));
|
||||||
|
btn->setIconSize(QSize(iconWidth, iconHeight));
|
||||||
|
btn->installEventFilter(this);
|
||||||
|
connect(btn, SIGNAL(toggled(bool)), this, SLOT(toggled(bool)));
|
||||||
|
|
||||||
|
this->btns << btn;
|
||||||
|
this->pixNormal << pixNormal;
|
||||||
|
this->pixHover << pixHover;
|
||||||
|
this->pixPressed << pixPressed;
|
||||||
|
this->pixChecked << pixChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
//主动触发一下选中的按钮
|
||||||
|
if (checkedIndex >= 0) {
|
||||||
|
QMetaObject::invokeMethod(btns.at(checkedIndex), "toggled", Q_ARG(bool, true));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
#ifndef ICONHELPER_H
|
||||||
|
#define ICONHELPER_H
|
||||||
|
|
||||||
|
#include <QtGui>
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
|
||||||
|
#include <QtWidgets>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超级图形字体类 作者:feiyangqingyun(QQ:517216493) 2016-11-23
|
||||||
|
* 1. 可传入多种图形字体文件
|
||||||
|
* 2. 可设置 QLabel+QAbstractButton 图形字体
|
||||||
|
* 3. 可设置按钮图标
|
||||||
|
* 4. 可获取指定尺寸的图形字体图片
|
||||||
|
* 5. 超级导航栏样式设置,带图标和效果切换+悬停颜色+按下颜色+选中颜色
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef quc
|
||||||
|
class Q_DECL_EXPORT IconHelper : public QObject
|
||||||
|
#else
|
||||||
|
class IconHelper : public QObject
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
//样式颜色结构体
|
||||||
|
struct StyleColor {
|
||||||
|
QString position; //位置 left right top bottom
|
||||||
|
bool textBesideIcon; //文字在图标左侧
|
||||||
|
|
||||||
|
quint32 iconSize; //图标字体尺寸
|
||||||
|
quint32 iconWidth; //图标图片宽度
|
||||||
|
quint32 iconHeight; //图标图片高度
|
||||||
|
|
||||||
|
quint32 borderWidth; //边框宽度
|
||||||
|
QString borderColor; //边框颜色
|
||||||
|
|
||||||
|
QString normalBgColor; //正常背景颜色
|
||||||
|
QString normalTextColor; //正常文字颜色
|
||||||
|
QString hoverBgColor; //悬停背景颜色
|
||||||
|
QString hoverTextColor; //悬停文字颜色
|
||||||
|
QString pressedBgColor; //按下背景颜色
|
||||||
|
QString pressedTextColor; //按下文字颜色
|
||||||
|
QString checkedBgColor; //选中背景颜色
|
||||||
|
QString checkedTextColor; //选中文字颜色
|
||||||
|
|
||||||
|
StyleColor() {
|
||||||
|
position = "left";
|
||||||
|
textBesideIcon = false;
|
||||||
|
|
||||||
|
iconSize = 12;
|
||||||
|
iconWidth = 15;
|
||||||
|
iconHeight = 15;
|
||||||
|
|
||||||
|
borderWidth = 3;
|
||||||
|
borderColor = "#029FEA";
|
||||||
|
|
||||||
|
normalBgColor = "#292F38";
|
||||||
|
normalTextColor = "#54626F";
|
||||||
|
hoverBgColor = "#40444D";
|
||||||
|
hoverTextColor = "#FDFDFD";
|
||||||
|
pressedBgColor = "#404244";
|
||||||
|
pressedTextColor = "#FDFDFD";
|
||||||
|
checkedBgColor = "#44494F";
|
||||||
|
checkedTextColor = "#FDFDFD";
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置常规颜色 普通状态+加深状态
|
||||||
|
void setColor(const QString &normalBgColor,
|
||||||
|
const QString &normalTextColor,
|
||||||
|
const QString &darkBgColor,
|
||||||
|
const QString &darkTextColor) {
|
||||||
|
this->normalBgColor = normalBgColor;
|
||||||
|
this->normalTextColor = normalTextColor;
|
||||||
|
this->hoverBgColor = darkBgColor;
|
||||||
|
this->hoverTextColor = darkTextColor;
|
||||||
|
this->pressedBgColor = darkBgColor;
|
||||||
|
this->pressedTextColor = darkTextColor;
|
||||||
|
this->checkedBgColor = darkBgColor;
|
||||||
|
this->checkedTextColor = darkTextColor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//阿里巴巴图形字体类
|
||||||
|
static IconHelper *iconFontAliBaBa;
|
||||||
|
//FontAwesome图形字体类
|
||||||
|
static IconHelper *iconFontAwesome;
|
||||||
|
//初始化图形字体
|
||||||
|
static void initFont();
|
||||||
|
|
||||||
|
static void setIcon(QLabel *lab, int icon, quint32 size = 12);
|
||||||
|
static void setIcon(QAbstractButton *btn, int icon, quint32 size = 12);
|
||||||
|
|
||||||
|
static void setPixmap(QAbstractButton *btn, const QColor &color,
|
||||||
|
int icon, quint32 size = 12,
|
||||||
|
quint32 width = 15, quint32 height = 15,
|
||||||
|
int flags = Qt::AlignCenter);
|
||||||
|
static QPixmap getPixmap(const QColor &color, int icon, quint32 size = 12,
|
||||||
|
quint32 width = 15, quint32 height = 15,
|
||||||
|
int flags = Qt::AlignCenter);
|
||||||
|
|
||||||
|
static void setStyle(QWidget *widget, QList<QPushButton *> btns, QList<int> icons, const StyleColor &styleColor);
|
||||||
|
static void setStyle(QWidget *widget, QList<QToolButton *> btns, QList<int> icons, const StyleColor &styleColor);
|
||||||
|
static void setStyle(QWidget *widget, QList<QAbstractButton *> btns, QList<int> icons, const StyleColor &styleColor);
|
||||||
|
|
||||||
|
//默认构造函数,传入字体文件+字体名称
|
||||||
|
explicit IconHelper(const QString &fontFile, const QString &fontName, QObject *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFont iconFont; //图形字体
|
||||||
|
QList<QAbstractButton *> btns; //按钮队列
|
||||||
|
QList<QPixmap> pixNormal; //正常图片队列
|
||||||
|
QList<QPixmap> pixHover; //悬停图片队列
|
||||||
|
QList<QPixmap> pixPressed; //按下图片队列
|
||||||
|
QList<QPixmap> pixChecked; //选中图片队列
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
//按钮选中状态切换处理
|
||||||
|
void toggled(bool checked);
|
||||||
|
|
||||||
|
public:
|
||||||
|
//设置图形字体到标签
|
||||||
|
void setIcon1(QLabel *lab, int icon, quint32 size = 12);
|
||||||
|
//设置图形字体到按钮
|
||||||
|
void setIcon1(QAbstractButton *btn, int icon, quint32 size = 12);
|
||||||
|
|
||||||
|
//设置图形字体到图标
|
||||||
|
void setPixmap1(QAbstractButton *btn, const QColor &color,
|
||||||
|
int icon, quint32 size = 12,
|
||||||
|
quint32 width = 15, quint32 height = 15,
|
||||||
|
int flags = Qt::AlignCenter);
|
||||||
|
//获取指定图形字体,可以指定文字大小,图片宽高,文字对齐
|
||||||
|
QPixmap getPixmap1(const QColor &color, int icon, quint32 size = 12,
|
||||||
|
quint32 width = 15, quint32 height = 15,
|
||||||
|
int flags = Qt::AlignCenter);
|
||||||
|
|
||||||
|
//指定导航面板样式,带图标和效果切换+悬停颜色+按下颜色+选中颜色
|
||||||
|
void setStyle1(QWidget *widget, QList<QPushButton *> btns, QList<int> icons, const StyleColor &styleColor);
|
||||||
|
void setStyle1(QWidget *widget, QList<QToolButton *> btns, QList<int> icons, const StyleColor &styleColor);
|
||||||
|
void setStyle1(QWidget *widget, QList<QAbstractButton *> btns, QList<int> icons, const StyleColor &styleColor);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ICONHELPER_H
|
Binary file not shown.
|
@ -0,0 +1,374 @@
|
||||||
|
#include "quihelper.h"
|
||||||
|
|
||||||
|
int QUIHelper::getScreenIndex()
|
||||||
|
{
|
||||||
|
//需要对多个屏幕进行处理
|
||||||
|
int screenIndex = 0;
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
|
||||||
|
int screenCount = qApp->screens().count();
|
||||||
|
#else
|
||||||
|
int screenCount = qApp->desktop()->screenCount();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (screenCount > 1) {
|
||||||
|
//找到当前鼠标所在屏幕
|
||||||
|
QPoint pos = QCursor::pos();
|
||||||
|
for (int i = 0; i < screenCount; ++i) {
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
|
||||||
|
if (qApp->screens().at(i)->geometry().contains(pos)) {
|
||||||
|
#else
|
||||||
|
if (qApp->desktop()->screenGeometry(i).contains(pos)) {
|
||||||
|
#endif
|
||||||
|
screenIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return screenIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect QUIHelper::getScreenRect(bool available)
|
||||||
|
{
|
||||||
|
QRect rect;
|
||||||
|
int screenIndex = QUIHelper::getScreenIndex();
|
||||||
|
if (available) {
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
|
||||||
|
rect = qApp->screens().at(screenIndex)->availableGeometry();
|
||||||
|
#else
|
||||||
|
rect = qApp->desktop()->availableGeometry(screenIndex);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
|
||||||
|
rect = qApp->screens().at(screenIndex)->geometry();
|
||||||
|
#else
|
||||||
|
rect = qApp->desktop()->screenGeometry(screenIndex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QUIHelper::deskWidth()
|
||||||
|
{
|
||||||
|
return getScreenRect().width();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QUIHelper::deskHeight()
|
||||||
|
{
|
||||||
|
return getScreenRect().height();
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *QUIHelper::centerBaseForm = 0;
|
||||||
|
void QUIHelper::setFormInCenter(QWidget *form)
|
||||||
|
{
|
||||||
|
int formWidth = form->width();
|
||||||
|
int formHeight = form->height();
|
||||||
|
|
||||||
|
//如果=0表示采用系统桌面屏幕为参照
|
||||||
|
QRect rect;
|
||||||
|
if (centerBaseForm == 0) {
|
||||||
|
rect = getScreenRect();
|
||||||
|
} else {
|
||||||
|
rect = centerBaseForm->geometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
int deskWidth = rect.width();
|
||||||
|
int deskHeight = rect.height();
|
||||||
|
QPoint movePoint(deskWidth / 2 - formWidth / 2 + rect.x(), deskHeight / 2 - formHeight / 2 + rect.y());
|
||||||
|
form->move(movePoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QUIHelper::appName()
|
||||||
|
{
|
||||||
|
//没有必要每次都获取,只有当变量为空时才去获取一次
|
||||||
|
static QString name;
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
name = qApp->applicationFilePath();
|
||||||
|
//下面的方法主要为了过滤安卓的路径 lib程序名_armeabi-v7a
|
||||||
|
QStringList list = name.split("/");
|
||||||
|
name = list.at(list.count() - 1).split(".").at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QUIHelper::appPath()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
//return QString("/sdcard/Android/%1").arg(appName());
|
||||||
|
return QString("/storage/emulated/0/%1").arg(appName());
|
||||||
|
#else
|
||||||
|
return qApp->applicationDirPath();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QUIHelper::getUuid()
|
||||||
|
{
|
||||||
|
QString uuid = QUuid::createUuid().toString();
|
||||||
|
uuid.replace("{", "");
|
||||||
|
uuid.replace("}", "");
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::initRand()
|
||||||
|
{
|
||||||
|
//初始化随机数种子
|
||||||
|
QTime t = QTime::currentTime();
|
||||||
|
srand(t.msec() + t.second() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::newDir(const QString &dirName)
|
||||||
|
{
|
||||||
|
QString strDir = dirName;
|
||||||
|
|
||||||
|
//如果路径中包含斜杠字符则说明是绝对路径
|
||||||
|
//linux系统路径字符带有 / windows系统 路径字符带有 :/
|
||||||
|
if (!strDir.startsWith("/") && !strDir.contains(":/")) {
|
||||||
|
strDir = QString("%1/%2").arg(QUIHelper::appPath()).arg(strDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir dir(strDir);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkpath(strDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::sleep(int msec)
|
||||||
|
{
|
||||||
|
if (msec > 0) {
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
|
||||||
|
QTime endTime = QTime::currentTime().addMSecs(msec);
|
||||||
|
while (QTime::currentTime() < endTime) {
|
||||||
|
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
QThread::msleep(msec);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::setStyle()
|
||||||
|
{
|
||||||
|
//打印下所有内置风格的名字
|
||||||
|
qDebug() << "Qt内置的样式" << QStyleFactory::keys();
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
|
||||||
|
qApp->setStyle(QStyleFactory::create("Fusion"));
|
||||||
|
#else
|
||||||
|
qApp->setStyle(QStyleFactory::create("Cleanlooks"));
|
||||||
|
#endif
|
||||||
|
//qApp->setPalette(QPalette("#FFFFFF"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::setFont(int fontSize)
|
||||||
|
{
|
||||||
|
QFont font;
|
||||||
|
font.setFamily("MicroSoft Yahei");
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
font.setPixelSize(15);
|
||||||
|
#elif __arm__
|
||||||
|
font.setPixelSize(25);
|
||||||
|
#else
|
||||||
|
font.setPixelSize(fontSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef rk3399
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
|
||||||
|
qApp->setFont(font);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::setCode(bool utf8)
|
||||||
|
{
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
|
||||||
|
#if _MSC_VER
|
||||||
|
QTextCodec *codec = QTextCodec::codecForName("gbk");
|
||||||
|
#else
|
||||||
|
QTextCodec *codec = QTextCodec::codecForName("utf-8");
|
||||||
|
#endif
|
||||||
|
QTextCodec::setCodecForLocale(codec);
|
||||||
|
QTextCodec::setCodecForCStrings(codec);
|
||||||
|
QTextCodec::setCodecForTr(codec);
|
||||||
|
#else
|
||||||
|
//如果想要控制台打印信息中文正常就注释掉这个设置
|
||||||
|
if (utf8) {
|
||||||
|
QTextCodec *codec = QTextCodec::codecForName("utf-8");
|
||||||
|
QTextCodec::setCodecForLocale(codec);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::setTranslator(const QString &qmFile)
|
||||||
|
{
|
||||||
|
QTranslator *translator = new QTranslator(qApp);
|
||||||
|
translator->load(qmFile);
|
||||||
|
qApp->installTranslator(translator);
|
||||||
|
}
|
||||||
|
|
||||||
|
int QUIHelper::showMessageBox(const QString &info, int type, int closeSec, bool exec)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (type == 0) {
|
||||||
|
showMessageBoxInfo(info, closeSec, exec);
|
||||||
|
} else if (type == 1) {
|
||||||
|
showMessageBoxError(info, closeSec, exec);
|
||||||
|
} else if (type == 2) {
|
||||||
|
result = showMessageBoxQuestion(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::showMessageBoxInfo(const QString &info, int closeSec, bool exec)
|
||||||
|
{
|
||||||
|
QMessageBox box(QMessageBox::Information, "提示", info);
|
||||||
|
box.setStandardButtons(QMessageBox::Yes);
|
||||||
|
box.setButtonText(QMessageBox::Yes, QString("确 定"));
|
||||||
|
box.exec();
|
||||||
|
//QMessageBox::information(0, "提示", info, QMessageBox::Yes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::showMessageBoxError(const QString &info, int closeSec, bool exec)
|
||||||
|
{
|
||||||
|
QMessageBox box(QMessageBox::Critical, "错误", info);
|
||||||
|
box.setStandardButtons(QMessageBox::Yes);
|
||||||
|
box.setButtonText(QMessageBox::Yes, QString("确 定"));
|
||||||
|
box.exec();
|
||||||
|
//QMessageBox::critical(0, "错误", info, QMessageBox::Yes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int QUIHelper::showMessageBoxQuestion(const QString &info)
|
||||||
|
{
|
||||||
|
QMessageBox box(QMessageBox::Question, "询问", info);
|
||||||
|
box.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||||
|
box.setButtonText(QMessageBox::Yes, QString("确 定"));
|
||||||
|
box.setButtonText(QMessageBox::No, QString("取 消"));
|
||||||
|
return box.exec();
|
||||||
|
//return QMessageBox::question(0, "询问", info, QMessageBox::Yes | QMessageBox::No);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QUIHelper::getXorEncryptDecrypt(const QString &value, char key)
|
||||||
|
{
|
||||||
|
//矫正范围外的数据
|
||||||
|
if (key < 0 || key >= 127) {
|
||||||
|
key = 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString result = value;
|
||||||
|
int count = result.count();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
result[i] = QChar(result.at(i).toLatin1() ^ key);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar QUIHelper::getOrCode(const QByteArray &data)
|
||||||
|
{
|
||||||
|
int len = data.length();
|
||||||
|
uchar result = 0;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
result ^= data.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar QUIHelper::getCheckCode(const QByteArray &data)
|
||||||
|
{
|
||||||
|
int len = data.length();
|
||||||
|
uchar temp = 0;
|
||||||
|
for (uchar i = 0; i < len; i++) {
|
||||||
|
temp += data.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp % 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::initTableView(QTableView *tableView, int rowHeight, bool headVisible, bool edit, bool stretchLast)
|
||||||
|
{
|
||||||
|
//取消自动换行
|
||||||
|
tableView->setWordWrap(false);
|
||||||
|
//超出文本不显示省略号
|
||||||
|
tableView->setTextElideMode(Qt::ElideNone);
|
||||||
|
//奇数偶数行颜色交替
|
||||||
|
tableView->setAlternatingRowColors(false);
|
||||||
|
//垂直表头是否可见
|
||||||
|
tableView->verticalHeader()->setVisible(headVisible);
|
||||||
|
//选中一行表头是否加粗
|
||||||
|
tableView->horizontalHeader()->setHighlightSections(false);
|
||||||
|
//最后一行拉伸填充
|
||||||
|
tableView->horizontalHeader()->setStretchLastSection(stretchLast);
|
||||||
|
//行标题最小宽度尺寸
|
||||||
|
tableView->horizontalHeader()->setMinimumSectionSize(0);
|
||||||
|
//行标题最小高度,等同于和默认行高一致
|
||||||
|
tableView->horizontalHeader()->setFixedHeight(rowHeight);
|
||||||
|
//默认行高
|
||||||
|
tableView->verticalHeader()->setDefaultSectionSize(rowHeight);
|
||||||
|
//选中时一行整体选中
|
||||||
|
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
//只允许选择单个
|
||||||
|
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
|
||||||
|
//表头不可单击
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
|
||||||
|
tableView->horizontalHeader()->setSectionsClickable(false);
|
||||||
|
#else
|
||||||
|
tableView->horizontalHeader()->setClickable(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//鼠标按下即进入编辑模式
|
||||||
|
if (edit) {
|
||||||
|
tableView->setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::DoubleClicked);
|
||||||
|
} else {
|
||||||
|
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QUIHelper::openFile(const QString &fileName, const QString &msg)
|
||||||
|
{
|
||||||
|
#ifdef __arm__
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (QUIHelper::showMessageBoxQuestion(msg + "成功!确定现在就打开吗?") == QMessageBox::Yes) {
|
||||||
|
QString url = QString("file:///%1").arg(fileName);
|
||||||
|
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QUIHelper::checkIniFile(const QString &iniFile)
|
||||||
|
{
|
||||||
|
//如果配置文件大小为0,则以初始值继续运行,并生成配置文件
|
||||||
|
QFile file(iniFile);
|
||||||
|
if (file.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果配置文件不完整,则以初始值继续运行,并生成配置文件
|
||||||
|
if (file.open(QFile::ReadOnly)) {
|
||||||
|
bool ok = true;
|
||||||
|
while (!file.atEnd()) {
|
||||||
|
QString line = file.readLine();
|
||||||
|
line.replace("\r", "");
|
||||||
|
line.replace("\n", "");
|
||||||
|
QStringList list = line.split("=");
|
||||||
|
|
||||||
|
if (list.count() == 2) {
|
||||||
|
if (list.at(1) == "") {
|
||||||
|
qDebug() << "ini node no value" << list.at(0);
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef QUIHELPER2_H
|
||||||
|
#define QUIHELPER2_H
|
||||||
|
|
||||||
|
#include "head.h"
|
||||||
|
|
||||||
|
class QUIHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取当前鼠标所在屏幕索引+尺寸
|
||||||
|
static int getScreenIndex();
|
||||||
|
static QRect getScreenRect(bool available = true);
|
||||||
|
|
||||||
|
//获取桌面宽度高度+居中显示
|
||||||
|
static int deskWidth();
|
||||||
|
static int deskHeight();
|
||||||
|
|
||||||
|
//居中显示窗体
|
||||||
|
//定义标志位指定是以桌面为参照还是主程序界面为参照
|
||||||
|
static QWidget *centerBaseForm;
|
||||||
|
static void setFormInCenter(QWidget *form);
|
||||||
|
|
||||||
|
//程序文件名称+当前所在路径
|
||||||
|
static QString appName();
|
||||||
|
static QString appPath();
|
||||||
|
|
||||||
|
//获取uuid+初始化随机数种子+新建目录+延时
|
||||||
|
static QString getUuid();
|
||||||
|
static void initRand();
|
||||||
|
static void newDir(const QString &dirName);
|
||||||
|
static void sleep(int msec);
|
||||||
|
|
||||||
|
//设置样式+字体+编码+居中+翻译
|
||||||
|
static void setStyle();
|
||||||
|
static void setFont(int fontSize = 12);
|
||||||
|
static void setCode(bool utf8 = true);
|
||||||
|
static void setTranslator(const QString &qmFile = ":/image/qt_zh_CN.qm");
|
||||||
|
|
||||||
|
//弹出框
|
||||||
|
static int showMessageBox(const QString &info, int type = 0, int closeSec = 0, bool exec = false);
|
||||||
|
//弹出消息框
|
||||||
|
static void showMessageBoxInfo(const QString &info, int closeSec = 0, bool exec = false);
|
||||||
|
//弹出错误框
|
||||||
|
static void showMessageBoxError(const QString &info, int closeSec = 0, bool exec = false);
|
||||||
|
//弹出询问框
|
||||||
|
static int showMessageBoxQuestion(const QString &info);
|
||||||
|
|
||||||
|
//异或加密-只支持字符,如果是中文需要将其转换base64编码
|
||||||
|
static QString getXorEncryptDecrypt(const QString &value, char key);
|
||||||
|
//异或校验
|
||||||
|
static uchar getOrCode(const QByteArray &data);
|
||||||
|
//计算校验码
|
||||||
|
static uchar getCheckCode(const QByteArray &data);
|
||||||
|
|
||||||
|
//初始化表格
|
||||||
|
static void initTableView(QTableView *tableView, int rowHeight = 25,
|
||||||
|
bool headVisible = false, bool edit = false,
|
||||||
|
bool stretchLast = true);
|
||||||
|
//打开文件带提示框
|
||||||
|
static void openFile(const QString &fileName, const QString &msg);
|
||||||
|
|
||||||
|
//检查ini配置文件
|
||||||
|
static bool checkIniFile(const QString &iniFile);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QUIHELPER2_H
|
|
@ -0,0 +1,9 @@
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/framelessdialog.h \
|
||||||
|
$$PWD/framelessmainwindow.h \
|
||||||
|
$$PWD/framelesswidget.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/framelessdialog.cpp \
|
||||||
|
$$PWD/framelessmainwindow.cpp \
|
||||||
|
$$PWD/framelesswidget.cpp
|
|
@ -0,0 +1,370 @@
|
||||||
|
#include "framelessdialog.h"
|
||||||
|
#include "qdatetime.h"
|
||||||
|
#include "qevent.h"
|
||||||
|
#include "qdebug.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include "windows.h"
|
||||||
|
#pragma comment (lib,"user32.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
|
||||||
|
|
||||||
|
FramelessDialog::FramelessDialog(QWidget *parent) : QDialog(parent)
|
||||||
|
{
|
||||||
|
padding = 8;
|
||||||
|
moveEnable = true;
|
||||||
|
resizeEnable = true;
|
||||||
|
|
||||||
|
mousePressed = false;
|
||||||
|
mousePoint = QPoint(0, 0);
|
||||||
|
mouseRect = QRect(0, 0, 0, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
pressedArea << false;
|
||||||
|
pressedRect << QRect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
isMin = false;
|
||||||
|
flags = this->windowFlags();
|
||||||
|
titleBar = 0;
|
||||||
|
|
||||||
|
//设置背景透明 官方在5.3以后才彻底修复 WA_TranslucentBackground+FramelessWindowHint 并存不绘制的BUG
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,3,0))
|
||||||
|
this->setAttribute(Qt::WA_TranslucentBackground);
|
||||||
|
#endif
|
||||||
|
//设置无边框属性
|
||||||
|
this->setWindowFlags(flags | Qt::FramelessWindowHint);
|
||||||
|
//安装事件过滤器识别拖动
|
||||||
|
this->installEventFilter(this);
|
||||||
|
|
||||||
|
//设置属性产生win窗体效果,移动到边缘半屏或者最大化等
|
||||||
|
//设置以后会产生标题栏需要在下面拦截消息重新去掉
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HWND hwnd = (HWND)this->winId();
|
||||||
|
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
|
||||||
|
::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessDialog::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
//解决有时候窗体重新显示的时候假死不刷新的BUG
|
||||||
|
setAttribute(Qt::WA_Mapped);
|
||||||
|
QDialog::showEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessDialog::doWindowStateChange(QEvent *event)
|
||||||
|
{
|
||||||
|
//非最大化才能移动和拖动大小
|
||||||
|
if (windowState() == Qt::WindowNoState) {
|
||||||
|
moveEnable = true;
|
||||||
|
resizeEnable = true;
|
||||||
|
} else {
|
||||||
|
moveEnable = false;
|
||||||
|
resizeEnable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//发出最大化最小化等改变事件,以便界面上更改对应的信息比如右上角图标和文字
|
||||||
|
emit windowStateChange(!moveEnable);
|
||||||
|
|
||||||
|
//解决mac系统上无边框最小化失效的BUG
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
if (windowState() & Qt::WindowMinimized) {
|
||||||
|
isMin = true;
|
||||||
|
} else {
|
||||||
|
if (isMin) {
|
||||||
|
//设置无边框属性
|
||||||
|
this->setWindowFlags(flags | Qt::FramelessWindowHint);
|
||||||
|
this->setVisible(true);
|
||||||
|
isMin = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessDialog::doResizeEvent(QEvent *event)
|
||||||
|
{
|
||||||
|
//非win系统的无边框拉伸,win系统上已经采用了nativeEvent来处理拉伸
|
||||||
|
//为何不统一用计算的方式因为在win上用这个方式往左拉伸会发抖妹的
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
if (event->type() == QEvent::Resize) {
|
||||||
|
//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
|
||||||
|
int width = this->width();
|
||||||
|
int height = this->height();
|
||||||
|
|
||||||
|
//左侧描点区域
|
||||||
|
pressedRect[0] = QRect(0, padding, padding, height - padding * 2);
|
||||||
|
//右侧描点区域
|
||||||
|
pressedRect[1] = QRect(width - padding, padding, padding, height - padding * 2);
|
||||||
|
//上侧描点区域
|
||||||
|
pressedRect[2] = QRect(padding, 0, width - padding * 2, padding);
|
||||||
|
//下侧描点区域
|
||||||
|
pressedRect[3] = QRect(padding, height - padding, width - padding * 2, padding);
|
||||||
|
|
||||||
|
//左上角描点区域
|
||||||
|
pressedRect[4] = QRect(0, 0, padding, padding);
|
||||||
|
//右上角描点区域
|
||||||
|
pressedRect[5] = QRect(width - padding, 0, padding, padding);
|
||||||
|
//左下角描点区域
|
||||||
|
pressedRect[6] = QRect(0, height - padding, padding, padding);
|
||||||
|
//右下角描点区域
|
||||||
|
pressedRect[7] = QRect(width - padding, height - padding, padding, padding);
|
||||||
|
} else if (event->type() == QEvent::HoverMove) {
|
||||||
|
//设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
|
||||||
|
QHoverEvent *hoverEvent = (QHoverEvent *)event;
|
||||||
|
QPoint point = hoverEvent->pos();
|
||||||
|
if (resizeEnable) {
|
||||||
|
if (pressedRect.at(0).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeHorCursor);
|
||||||
|
} else if (pressedRect.at(1).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeHorCursor);
|
||||||
|
} else if (pressedRect.at(2).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeVerCursor);
|
||||||
|
} else if (pressedRect.at(3).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeVerCursor);
|
||||||
|
} else if (pressedRect.at(4).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeFDiagCursor);
|
||||||
|
} else if (pressedRect.at(5).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeBDiagCursor);
|
||||||
|
} else if (pressedRect.at(6).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeBDiagCursor);
|
||||||
|
} else if (pressedRect.at(7).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeFDiagCursor);
|
||||||
|
} else {
|
||||||
|
this->setCursor(Qt::ArrowCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据当前鼠标位置,计算XY轴移动了多少
|
||||||
|
int offsetX = point.x() - mousePoint.x();
|
||||||
|
int offsetY = point.y() - mousePoint.y();
|
||||||
|
|
||||||
|
//根据按下处的位置判断是否是移动控件还是拉伸控件
|
||||||
|
if (moveEnable && mousePressed) {
|
||||||
|
this->move(this->x() + offsetX, this->y() + offsetY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resizeEnable) {
|
||||||
|
int rectX = mouseRect.x();
|
||||||
|
int rectY = mouseRect.y();
|
||||||
|
int rectW = mouseRect.width();
|
||||||
|
int rectH = mouseRect.height();
|
||||||
|
|
||||||
|
if (pressedArea.at(0)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(1)) {
|
||||||
|
this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
|
||||||
|
} else if (pressedArea.at(2)) {
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(3)) {
|
||||||
|
this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
|
||||||
|
} else if (pressedArea.at(4)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(5)) {
|
||||||
|
int resizeW = rectW + offsetX;
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(6)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
int resizeH = rectH + offsetY;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(7)) {
|
||||||
|
int resizeW = rectW + offsetX;
|
||||||
|
int resizeH = rectH + offsetY;
|
||||||
|
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||||
|
//记住鼠标按下的坐标+窗体区域
|
||||||
|
QMouseEvent *mouseEvent = (QMouseEvent *)event;
|
||||||
|
mousePoint = mouseEvent->pos();
|
||||||
|
mouseRect = this->geometry();
|
||||||
|
|
||||||
|
//判断按下的手柄的区域位置
|
||||||
|
if (pressedRect.at(0).contains(mousePoint)) {
|
||||||
|
pressedArea[0] = true;
|
||||||
|
} else if (pressedRect.at(1).contains(mousePoint)) {
|
||||||
|
pressedArea[1] = true;
|
||||||
|
} else if (pressedRect.at(2).contains(mousePoint)) {
|
||||||
|
pressedArea[2] = true;
|
||||||
|
} else if (pressedRect.at(3).contains(mousePoint)) {
|
||||||
|
pressedArea[3] = true;
|
||||||
|
} else if (pressedRect.at(4).contains(mousePoint)) {
|
||||||
|
pressedArea[4] = true;
|
||||||
|
} else if (pressedRect.at(5).contains(mousePoint)) {
|
||||||
|
pressedArea[5] = true;
|
||||||
|
} else if (pressedRect.at(6).contains(mousePoint)) {
|
||||||
|
pressedArea[6] = true;
|
||||||
|
} else if (pressedRect.at(7).contains(mousePoint)) {
|
||||||
|
pressedArea[7] = true;
|
||||||
|
} else {
|
||||||
|
mousePressed = true;
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::MouseMove) {
|
||||||
|
//改成用HoverMove识别
|
||||||
|
} else if (event->type() == QEvent::MouseButtonRelease) {
|
||||||
|
//恢复所有
|
||||||
|
this->setCursor(Qt::ArrowCursor);
|
||||||
|
mousePressed = false;
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
pressedArea[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessDialog::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
if (watched == this) {
|
||||||
|
if (event->type() == QEvent::WindowStateChange) {
|
||||||
|
doWindowStateChange(event);
|
||||||
|
} else {
|
||||||
|
doResizeEvent(event);
|
||||||
|
}
|
||||||
|
} else if (watched == titleBar) {
|
||||||
|
//双击标题栏发出双击信号给主界面
|
||||||
|
//下面的 *result = HTCAPTION; 标志位也会自动识别双击标题栏
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
if (event->type() == QEvent::MouseButtonDblClick) {
|
||||||
|
emit titleDblClick();
|
||||||
|
} else if (event->type() == QEvent::NonClientAreaMouseButtonDblClick) {
|
||||||
|
emit titleDblClick();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return QDialog::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
bool FramelessDialog::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
|
||||||
|
#else
|
||||||
|
bool FramelessDialog::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (eventType == "windows_generic_MSG") {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
MSG *msg = static_cast<MSG *>(message);
|
||||||
|
//qDebug() << TIMEMS << "nativeEvent" << msg->wParam << msg->message;
|
||||||
|
|
||||||
|
//不同的消息类型和参数进行不同的处理
|
||||||
|
if (msg->message == WM_NCCALCSIZE) {
|
||||||
|
*result = 0;
|
||||||
|
return true;
|
||||||
|
} else if (msg->message == WM_NCHITTEST) {
|
||||||
|
//计算鼠标对应的屏幕坐标
|
||||||
|
long x = LOWORD(msg->lParam);
|
||||||
|
long y = HIWORD(msg->lParam);
|
||||||
|
QPoint pos = mapFromGlobal(QPoint(x, y));
|
||||||
|
|
||||||
|
//判断当前鼠标位置在哪个区域
|
||||||
|
bool left = pos.x() < padding;
|
||||||
|
bool right = pos.x() > width() - padding;
|
||||||
|
bool top = pos.y() < padding;
|
||||||
|
bool bottom = pos.y() > height() - padding;
|
||||||
|
|
||||||
|
//鼠标移动到四个角,这个消息是当鼠标移动或者有鼠标键按下时候发出的
|
||||||
|
*result = 0;
|
||||||
|
if (resizeEnable) {
|
||||||
|
if (left && top) {
|
||||||
|
*result = HTTOPLEFT;
|
||||||
|
} else if (left && bottom) {
|
||||||
|
*result = HTBOTTOMLEFT;
|
||||||
|
} else if (right && top) {
|
||||||
|
*result = HTTOPRIGHT;
|
||||||
|
} else if (right && bottom) {
|
||||||
|
*result = HTBOTTOMRIGHT;
|
||||||
|
} else if (left) {
|
||||||
|
*result = HTLEFT;
|
||||||
|
} else if (right) {
|
||||||
|
*result = HTRIGHT;
|
||||||
|
} else if (top) {
|
||||||
|
*result = HTTOP;
|
||||||
|
} else if (bottom) {
|
||||||
|
*result = HTBOTTOM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//先处理掉拉伸
|
||||||
|
if (0 != *result) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//识别标题栏拖动产生半屏全屏效果
|
||||||
|
if (titleBar != 0 && titleBar->rect().contains(pos)) {
|
||||||
|
QWidget *child = titleBar->childAt(pos);
|
||||||
|
if (!child) {
|
||||||
|
*result = HTCAPTION;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST) {
|
||||||
|
//系统休眠的时候自动最小化可以规避程序可能出现的问题
|
||||||
|
this->showMinimized();
|
||||||
|
} else if (msg->wParam == PBT_APMRESUMEAUTOMATIC) {
|
||||||
|
//休眠唤醒后自动打开
|
||||||
|
this->showNormal();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else if (eventType == "NSEvent") {
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
#endif
|
||||||
|
} else if (eventType == "xcb_generic_event_t") {
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
bool FramelessDialog::winEvent(MSG *message, long *result)
|
||||||
|
{
|
||||||
|
return nativeEvent("windows_generic_MSG", message, result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FramelessDialog::setPadding(int padding)
|
||||||
|
{
|
||||||
|
this->padding = padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessDialog::setMoveEnable(bool moveEnable)
|
||||||
|
{
|
||||||
|
this->moveEnable = moveEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessDialog::setResizeEnable(bool resizeEnable)
|
||||||
|
{
|
||||||
|
this->resizeEnable = resizeEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessDialog::setTitleBar(QWidget *titleBar)
|
||||||
|
{
|
||||||
|
this->titleBar = titleBar;
|
||||||
|
this->titleBar->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef FRAMELESSDIALOG_H
|
||||||
|
#define FRAMELESSDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class FramelessDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FramelessDialog(QWidget *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//窗体显示的时候触发
|
||||||
|
void showEvent(QShowEvent *event);
|
||||||
|
|
||||||
|
//事件过滤器识别拖动拉伸等
|
||||||
|
void doWindowStateChange(QEvent *event);
|
||||||
|
void doResizeEvent(QEvent *event);
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event);
|
||||||
|
|
||||||
|
//拦截系统事件用于修复系统休眠后唤醒程序的BUG
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
|
||||||
|
#else
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Qt4的写法
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
bool winEvent(MSG *message, long *result);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
//边距+可移动+可拉伸
|
||||||
|
int padding;
|
||||||
|
bool moveEnable;
|
||||||
|
bool resizeEnable;
|
||||||
|
|
||||||
|
//标题栏控件
|
||||||
|
QWidget *titleBar;
|
||||||
|
|
||||||
|
//鼠标是否按下+按下坐标+按下时窗体区域
|
||||||
|
bool mousePressed;
|
||||||
|
QPoint mousePoint;
|
||||||
|
QRect mouseRect;
|
||||||
|
|
||||||
|
//鼠标是否按下某个区域+按下区域的大小
|
||||||
|
//依次为 左侧+右侧+上侧+下侧+左上侧+右上侧+左下侧+右下侧
|
||||||
|
QList<bool> pressedArea;
|
||||||
|
QList<QRect> pressedRect;
|
||||||
|
|
||||||
|
//记录是否最小化
|
||||||
|
bool isMin;
|
||||||
|
//存储窗体默认的属性
|
||||||
|
Qt::WindowFlags flags;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//设置边距+可拖动+可拉伸
|
||||||
|
void setPadding(int padding);
|
||||||
|
void setMoveEnable(bool moveEnable);
|
||||||
|
void setResizeEnable(bool resizeEnable);
|
||||||
|
|
||||||
|
//设置标题栏控件
|
||||||
|
void setTitleBar(QWidget *titleBar);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void titleDblClick();
|
||||||
|
void windowStateChange(bool max);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FRAMELESSDIALOG_H
|
|
@ -0,0 +1,368 @@
|
||||||
|
#include "framelessmainwindow.h"
|
||||||
|
#include "qdatetime.h"
|
||||||
|
#include "qevent.h"
|
||||||
|
#include "qdebug.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include "windows.h"
|
||||||
|
#pragma comment (lib,"user32.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
|
||||||
|
|
||||||
|
FramelessMainWindow::FramelessMainWindow(QWidget *parent) : QMainWindow(parent)
|
||||||
|
{
|
||||||
|
padding = 8;
|
||||||
|
moveEnable = true;
|
||||||
|
resizeEnable = true;
|
||||||
|
|
||||||
|
mousePressed = false;
|
||||||
|
mousePoint = QPoint(0, 0);
|
||||||
|
mouseRect = QRect(0, 0, 0, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
pressedArea << false;
|
||||||
|
pressedRect << QRect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
isMin = false;
|
||||||
|
flags = this->windowFlags();
|
||||||
|
titleBar = 0;
|
||||||
|
|
||||||
|
//设置背景透明 官方在5.3以后才彻底修复 WA_TranslucentBackground+FramelessWindowHint 并存不绘制的BUG
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,3,0))
|
||||||
|
this->setAttribute(Qt::WA_TranslucentBackground);
|
||||||
|
#endif
|
||||||
|
//设置无边框属性
|
||||||
|
this->setWindowFlags(flags | Qt::FramelessWindowHint);
|
||||||
|
//安装事件过滤器识别拖动
|
||||||
|
this->installEventFilter(this);
|
||||||
|
|
||||||
|
//设置属性产生win窗体效果,移动到边缘半屏或者最大化等
|
||||||
|
//设置以后会产生标题栏,需要在下面拦截消息WM_NCCALCSIZE重新去掉
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HWND hwnd = (HWND)this->winId();
|
||||||
|
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
|
||||||
|
::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
//解决有时候窗体重新显示的时候假死不刷新的BUG
|
||||||
|
setAttribute(Qt::WA_Mapped);
|
||||||
|
QMainWindow::showEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::doWindowStateChange(QEvent *event)
|
||||||
|
{
|
||||||
|
//非最大化才能移动和拖动大小
|
||||||
|
if (windowState() == Qt::WindowNoState) {
|
||||||
|
moveEnable = true;
|
||||||
|
resizeEnable = true;
|
||||||
|
} else {
|
||||||
|
moveEnable = false;
|
||||||
|
resizeEnable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//发出最大化最小化等改变事件,以便界面上更改对应的信息比如右上角图标和文字
|
||||||
|
emit windowStateChange(!moveEnable);
|
||||||
|
|
||||||
|
//解决mac系统上无边框最小化失效的BUG
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
if (windowState() & Qt::WindowMinimized) {
|
||||||
|
isMin = true;
|
||||||
|
} else {
|
||||||
|
if (isMin) {
|
||||||
|
//设置无边框属性
|
||||||
|
this->setWindowFlags(flags | Qt::FramelessWindowHint);
|
||||||
|
this->setVisible(true);
|
||||||
|
isMin = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::doResizeEvent(QEvent *event)
|
||||||
|
{
|
||||||
|
//非win系统的无边框拉伸,win系统上已经采用了nativeEvent来处理拉伸
|
||||||
|
//为何不统一用计算的方式因为在win上用这个方式往左拉伸会发抖妹的
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
if (event->type() == QEvent::Resize) {
|
||||||
|
//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
|
||||||
|
int width = this->width();
|
||||||
|
int height = this->height();
|
||||||
|
|
||||||
|
//左侧描点区域
|
||||||
|
pressedRect[0] = QRect(0, padding, padding, height - padding * 2);
|
||||||
|
//右侧描点区域
|
||||||
|
pressedRect[1] = QRect(width - padding, padding, padding, height - padding * 2);
|
||||||
|
//上侧描点区域
|
||||||
|
pressedRect[2] = QRect(padding, 0, width - padding * 2, padding);
|
||||||
|
//下侧描点区域
|
||||||
|
pressedRect[3] = QRect(padding, height - padding, width - padding * 2, padding);
|
||||||
|
|
||||||
|
//左上角描点区域
|
||||||
|
pressedRect[4] = QRect(0, 0, padding, padding);
|
||||||
|
//右上角描点区域
|
||||||
|
pressedRect[5] = QRect(width - padding, 0, padding, padding);
|
||||||
|
//左下角描点区域
|
||||||
|
pressedRect[6] = QRect(0, height - padding, padding, padding);
|
||||||
|
//右下角描点区域
|
||||||
|
pressedRect[7] = QRect(width - padding, height - padding, padding, padding);
|
||||||
|
} else if (event->type() == QEvent::HoverMove) {
|
||||||
|
//设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
|
||||||
|
QHoverEvent *hoverEvent = (QHoverEvent *)event;
|
||||||
|
QPoint point = hoverEvent->pos();
|
||||||
|
if (resizeEnable) {
|
||||||
|
if (pressedRect.at(0).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeHorCursor);
|
||||||
|
} else if (pressedRect.at(1).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeHorCursor);
|
||||||
|
} else if (pressedRect.at(2).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeVerCursor);
|
||||||
|
} else if (pressedRect.at(3).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeVerCursor);
|
||||||
|
} else if (pressedRect.at(4).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeFDiagCursor);
|
||||||
|
} else if (pressedRect.at(5).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeBDiagCursor);
|
||||||
|
} else if (pressedRect.at(6).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeBDiagCursor);
|
||||||
|
} else if (pressedRect.at(7).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeFDiagCursor);
|
||||||
|
} else {
|
||||||
|
this->setCursor(Qt::ArrowCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据当前鼠标位置,计算XY轴移动了多少
|
||||||
|
int offsetX = point.x() - mousePoint.x();
|
||||||
|
int offsetY = point.y() - mousePoint.y();
|
||||||
|
|
||||||
|
//根据按下处的位置判断是否是移动控件还是拉伸控件
|
||||||
|
if (moveEnable && mousePressed) {
|
||||||
|
this->move(this->x() + offsetX, this->y() + offsetY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resizeEnable) {
|
||||||
|
int rectX = mouseRect.x();
|
||||||
|
int rectY = mouseRect.y();
|
||||||
|
int rectW = mouseRect.width();
|
||||||
|
int rectH = mouseRect.height();
|
||||||
|
|
||||||
|
if (pressedArea.at(0)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(1)) {
|
||||||
|
this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
|
||||||
|
} else if (pressedArea.at(2)) {
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(3)) {
|
||||||
|
this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
|
||||||
|
} else if (pressedArea.at(4)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(5)) {
|
||||||
|
int resizeW = rectW + offsetX;
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(6)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
int resizeH = rectH + offsetY;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(7)) {
|
||||||
|
int resizeW = rectW + offsetX;
|
||||||
|
int resizeH = rectH + offsetY;
|
||||||
|
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||||
|
//记住鼠标按下的坐标+窗体区域
|
||||||
|
QMouseEvent *mouseEvent = (QMouseEvent *)event;
|
||||||
|
mousePoint = mouseEvent->pos();
|
||||||
|
mouseRect = this->geometry();
|
||||||
|
|
||||||
|
//判断按下的手柄的区域位置
|
||||||
|
if (pressedRect.at(0).contains(mousePoint)) {
|
||||||
|
pressedArea[0] = true;
|
||||||
|
} else if (pressedRect.at(1).contains(mousePoint)) {
|
||||||
|
pressedArea[1] = true;
|
||||||
|
} else if (pressedRect.at(2).contains(mousePoint)) {
|
||||||
|
pressedArea[2] = true;
|
||||||
|
} else if (pressedRect.at(3).contains(mousePoint)) {
|
||||||
|
pressedArea[3] = true;
|
||||||
|
} else if (pressedRect.at(4).contains(mousePoint)) {
|
||||||
|
pressedArea[4] = true;
|
||||||
|
} else if (pressedRect.at(5).contains(mousePoint)) {
|
||||||
|
pressedArea[5] = true;
|
||||||
|
} else if (pressedRect.at(6).contains(mousePoint)) {
|
||||||
|
pressedArea[6] = true;
|
||||||
|
} else if (pressedRect.at(7).contains(mousePoint)) {
|
||||||
|
pressedArea[7] = true;
|
||||||
|
} else {
|
||||||
|
mousePressed = true;
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::MouseMove) {
|
||||||
|
//改成用HoverMove识别
|
||||||
|
} else if (event->type() == QEvent::MouseButtonRelease) {
|
||||||
|
//恢复所有
|
||||||
|
this->setCursor(Qt::ArrowCursor);
|
||||||
|
mousePressed = false;
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
pressedArea[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessMainWindow::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
if (watched == this) {
|
||||||
|
if (event->type() == QEvent::WindowStateChange) {
|
||||||
|
doWindowStateChange(event);
|
||||||
|
} else {
|
||||||
|
doResizeEvent(event);
|
||||||
|
}
|
||||||
|
} else if (watched == titleBar) {
|
||||||
|
//双击标题栏发出双击信号给主界面
|
||||||
|
//下面的 *result = HTCAPTION; 标志位也会自动识别双击标题栏
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
if (event->type() == QEvent::MouseButtonDblClick) {
|
||||||
|
emit titleDblClick();
|
||||||
|
} else if (event->type() == QEvent::NonClientAreaMouseButtonDblClick) {
|
||||||
|
emit titleDblClick();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return QMainWindow::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
bool FramelessMainWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
|
||||||
|
#else
|
||||||
|
bool FramelessMainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (eventType == "windows_generic_MSG") {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
MSG *msg = static_cast<MSG *>(message);
|
||||||
|
//qDebug() << TIMEMS << "nativeEvent" << msg->wParam << msg->message;
|
||||||
|
|
||||||
|
//不同的消息类型和参数进行不同的处理
|
||||||
|
if (msg->message == WM_NCCALCSIZE) {
|
||||||
|
*result = 0;
|
||||||
|
return true;
|
||||||
|
} else if (msg->message == WM_NCHITTEST) {
|
||||||
|
//计算鼠标对应的屏幕坐标
|
||||||
|
long x = LOWORD(msg->lParam);
|
||||||
|
long y = HIWORD(msg->lParam);
|
||||||
|
QPoint pos = mapFromGlobal(QPoint(x, y));
|
||||||
|
|
||||||
|
//判断当前鼠标位置在哪个区域
|
||||||
|
bool left = pos.x() < padding;
|
||||||
|
bool right = pos.x() > width() - padding;
|
||||||
|
bool top = pos.y() < padding;
|
||||||
|
bool bottom = pos.y() > height() - padding;
|
||||||
|
|
||||||
|
//鼠标移动到四个角,这个消息是当鼠标移动或者有鼠标键按下时候发出的
|
||||||
|
*result = 0;
|
||||||
|
if (resizeEnable) {
|
||||||
|
if (left && top) {
|
||||||
|
*result = HTTOPLEFT;
|
||||||
|
} else if (left && bottom) {
|
||||||
|
*result = HTBOTTOMLEFT;
|
||||||
|
} else if (right && top) {
|
||||||
|
*result = HTTOPRIGHT;
|
||||||
|
} else if (right && bottom) {
|
||||||
|
*result = HTBOTTOMRIGHT;
|
||||||
|
} else if (left) {
|
||||||
|
*result = HTLEFT;
|
||||||
|
} else if (right) {
|
||||||
|
*result = HTRIGHT;
|
||||||
|
} else if (top) {
|
||||||
|
*result = HTTOP;
|
||||||
|
} else if (bottom) {
|
||||||
|
*result = HTBOTTOM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//先处理掉拉伸
|
||||||
|
if (0 != *result) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//识别标题栏拖动产生半屏全屏效果
|
||||||
|
if (titleBar != 0 && titleBar->rect().contains(pos)) {
|
||||||
|
QWidget *child = titleBar->childAt(pos);
|
||||||
|
if (!child) {
|
||||||
|
*result = HTCAPTION;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST) {
|
||||||
|
//系统休眠的时候自动最小化可以规避程序可能出现的问题
|
||||||
|
this->showMinimized();
|
||||||
|
} else if (msg->wParam == PBT_APMRESUMEAUTOMATIC) {
|
||||||
|
//休眠唤醒后自动打开
|
||||||
|
this->showNormal();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else if (eventType == "NSEvent") {
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
#endif
|
||||||
|
} else if (eventType == "xcb_generic_event_t") {
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
bool FramelessMainWindow::winEvent(MSG *message, long *result)
|
||||||
|
{
|
||||||
|
return nativeEvent("windows_generic_MSG", message, result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FramelessMainWindow::setPadding(int padding)
|
||||||
|
{
|
||||||
|
this->padding = padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::setMoveEnable(bool moveEnable)
|
||||||
|
{
|
||||||
|
this->moveEnable = moveEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::setResizeEnable(bool resizeEnable)
|
||||||
|
{
|
||||||
|
this->resizeEnable = resizeEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessMainWindow::setTitleBar(QWidget *titleBar)
|
||||||
|
{
|
||||||
|
this->titleBar = titleBar;
|
||||||
|
this->titleBar->installEventFilter(this);
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef FRAMELESSMAINWINDOW_H
|
||||||
|
#define FRAMELESSMAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
|
class FramelessMainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FramelessMainWindow(QWidget *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//窗体显示的时候触发
|
||||||
|
void showEvent(QShowEvent *event);
|
||||||
|
|
||||||
|
//事件过滤器识别拖动拉伸等
|
||||||
|
void doWindowStateChange(QEvent *event);
|
||||||
|
void doResizeEvent(QEvent *event);
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event);
|
||||||
|
|
||||||
|
//拦截系统事件用于修复系统休眠后唤醒程序的BUG
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
|
||||||
|
#else
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Qt4的写法
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
bool winEvent(MSG *message, long *result);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
//边距+可移动+可拉伸
|
||||||
|
int padding;
|
||||||
|
bool moveEnable;
|
||||||
|
bool resizeEnable;
|
||||||
|
|
||||||
|
//标题栏控件
|
||||||
|
QWidget *titleBar;
|
||||||
|
|
||||||
|
//鼠标是否按下+按下坐标+按下时窗体区域
|
||||||
|
bool mousePressed;
|
||||||
|
QPoint mousePoint;
|
||||||
|
QRect mouseRect;
|
||||||
|
|
||||||
|
//鼠标是否按下某个区域+按下区域的大小
|
||||||
|
//依次为 左侧+右侧+上侧+下侧+左上侧+右上侧+左下侧+右下侧
|
||||||
|
QList<bool> pressedArea;
|
||||||
|
QList<QRect> pressedRect;
|
||||||
|
|
||||||
|
//记录是否最小化
|
||||||
|
bool isMin;
|
||||||
|
//存储窗体默认的属性
|
||||||
|
Qt::WindowFlags flags;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//设置边距+可拖动+可拉伸
|
||||||
|
void setPadding(int padding);
|
||||||
|
void setMoveEnable(bool moveEnable);
|
||||||
|
void setResizeEnable(bool resizeEnable);
|
||||||
|
|
||||||
|
//设置标题栏控件
|
||||||
|
void setTitleBar(QWidget *titleBar);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void titleDblClick();
|
||||||
|
void windowStateChange(bool max);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FRAMELESSMAINWINDOW_H
|
|
@ -0,0 +1,370 @@
|
||||||
|
#include "framelesswidget.h"
|
||||||
|
#include "qdatetime.h"
|
||||||
|
#include "qevent.h"
|
||||||
|
#include "qdebug.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include "windows.h"
|
||||||
|
#pragma comment (lib,"user32.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
|
||||||
|
|
||||||
|
FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent)
|
||||||
|
{
|
||||||
|
padding = 8;
|
||||||
|
moveEnable = true;
|
||||||
|
resizeEnable = true;
|
||||||
|
|
||||||
|
mousePressed = false;
|
||||||
|
mousePoint = QPoint(0, 0);
|
||||||
|
mouseRect = QRect(0, 0, 0, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
pressedArea << false;
|
||||||
|
pressedRect << QRect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
isMin = false;
|
||||||
|
flags = this->windowFlags();
|
||||||
|
titleBar = 0;
|
||||||
|
|
||||||
|
//设置背景透明 官方在5.3以后才彻底修复 WA_TranslucentBackground+FramelessWindowHint 并存不绘制的BUG
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,3,0))
|
||||||
|
this->setAttribute(Qt::WA_TranslucentBackground);
|
||||||
|
#endif
|
||||||
|
//设置无边框属性
|
||||||
|
this->setWindowFlags(flags | Qt::FramelessWindowHint);
|
||||||
|
//安装事件过滤器识别拖动
|
||||||
|
this->installEventFilter(this);
|
||||||
|
|
||||||
|
//设置属性产生win窗体效果,移动到边缘半屏或者最大化等
|
||||||
|
//设置以后会产生标题栏需要在下面拦截消息重新去掉
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HWND hwnd = (HWND)this->winId();
|
||||||
|
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
|
||||||
|
::SetWindowLong(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
//解决有时候窗体重新显示的时候假死不刷新的BUG
|
||||||
|
setAttribute(Qt::WA_Mapped);
|
||||||
|
QWidget::showEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::doWindowStateChange(QEvent *event)
|
||||||
|
{
|
||||||
|
//非最大化才能移动和拖动大小
|
||||||
|
if (windowState() == Qt::WindowNoState) {
|
||||||
|
moveEnable = true;
|
||||||
|
resizeEnable = true;
|
||||||
|
} else {
|
||||||
|
moveEnable = false;
|
||||||
|
resizeEnable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//发出最大化最小化等改变事件,以便界面上更改对应的信息比如右上角图标和文字
|
||||||
|
emit windowStateChange(!moveEnable);
|
||||||
|
|
||||||
|
//解决mac系统上无边框最小化失效的BUG
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
if (windowState() & Qt::WindowMinimized) {
|
||||||
|
isMin = true;
|
||||||
|
} else {
|
||||||
|
if (isMin) {
|
||||||
|
//设置无边框属性
|
||||||
|
this->setWindowFlags(flags | Qt::FramelessWindowHint);
|
||||||
|
this->setVisible(true);
|
||||||
|
isMin = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::doResizeEvent(QEvent *event)
|
||||||
|
{
|
||||||
|
//非win系统的无边框拉伸,win系统上已经采用了nativeEvent来处理拉伸
|
||||||
|
//为何不统一用计算的方式因为在win上用这个方式往左拉伸会发抖妹的
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
if (event->type() == QEvent::Resize) {
|
||||||
|
//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
|
||||||
|
int width = this->width();
|
||||||
|
int height = this->height();
|
||||||
|
|
||||||
|
//左侧描点区域
|
||||||
|
pressedRect[0] = QRect(0, padding, padding, height - padding * 2);
|
||||||
|
//右侧描点区域
|
||||||
|
pressedRect[1] = QRect(width - padding, padding, padding, height - padding * 2);
|
||||||
|
//上侧描点区域
|
||||||
|
pressedRect[2] = QRect(padding, 0, width - padding * 2, padding);
|
||||||
|
//下侧描点区域
|
||||||
|
pressedRect[3] = QRect(padding, height - padding, width - padding * 2, padding);
|
||||||
|
|
||||||
|
//左上角描点区域
|
||||||
|
pressedRect[4] = QRect(0, 0, padding, padding);
|
||||||
|
//右上角描点区域
|
||||||
|
pressedRect[5] = QRect(width - padding, 0, padding, padding);
|
||||||
|
//左下角描点区域
|
||||||
|
pressedRect[6] = QRect(0, height - padding, padding, padding);
|
||||||
|
//右下角描点区域
|
||||||
|
pressedRect[7] = QRect(width - padding, height - padding, padding, padding);
|
||||||
|
} else if (event->type() == QEvent::HoverMove) {
|
||||||
|
//设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
|
||||||
|
QHoverEvent *hoverEvent = (QHoverEvent *)event;
|
||||||
|
QPoint point = hoverEvent->pos();
|
||||||
|
if (resizeEnable) {
|
||||||
|
if (pressedRect.at(0).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeHorCursor);
|
||||||
|
} else if (pressedRect.at(1).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeHorCursor);
|
||||||
|
} else if (pressedRect.at(2).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeVerCursor);
|
||||||
|
} else if (pressedRect.at(3).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeVerCursor);
|
||||||
|
} else if (pressedRect.at(4).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeFDiagCursor);
|
||||||
|
} else if (pressedRect.at(5).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeBDiagCursor);
|
||||||
|
} else if (pressedRect.at(6).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeBDiagCursor);
|
||||||
|
} else if (pressedRect.at(7).contains(point)) {
|
||||||
|
this->setCursor(Qt::SizeFDiagCursor);
|
||||||
|
} else {
|
||||||
|
this->setCursor(Qt::ArrowCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据当前鼠标位置,计算XY轴移动了多少
|
||||||
|
int offsetX = point.x() - mousePoint.x();
|
||||||
|
int offsetY = point.y() - mousePoint.y();
|
||||||
|
|
||||||
|
//根据按下处的位置判断是否是移动控件还是拉伸控件
|
||||||
|
if (moveEnable && mousePressed) {
|
||||||
|
this->move(this->x() + offsetX, this->y() + offsetY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resizeEnable) {
|
||||||
|
int rectX = mouseRect.x();
|
||||||
|
int rectY = mouseRect.y();
|
||||||
|
int rectW = mouseRect.width();
|
||||||
|
int rectH = mouseRect.height();
|
||||||
|
|
||||||
|
if (pressedArea.at(0)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(1)) {
|
||||||
|
this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
|
||||||
|
} else if (pressedArea.at(2)) {
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(3)) {
|
||||||
|
this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
|
||||||
|
} else if (pressedArea.at(4)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(5)) {
|
||||||
|
int resizeW = rectW + offsetX;
|
||||||
|
int resizeH = this->height() - offsetY;
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(6)) {
|
||||||
|
int resizeW = this->width() - offsetX;
|
||||||
|
int resizeH = rectH + offsetY;
|
||||||
|
if (this->minimumWidth() <= resizeW) {
|
||||||
|
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
if (this->minimumHeight() <= resizeH) {
|
||||||
|
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
} else if (pressedArea.at(7)) {
|
||||||
|
int resizeW = rectW + offsetX;
|
||||||
|
int resizeH = rectH + offsetY;
|
||||||
|
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||||
|
//记住鼠标按下的坐标+窗体区域
|
||||||
|
QMouseEvent *mouseEvent = (QMouseEvent *)event;
|
||||||
|
mousePoint = mouseEvent->pos();
|
||||||
|
mouseRect = this->geometry();
|
||||||
|
|
||||||
|
//判断按下的手柄的区域位置
|
||||||
|
if (pressedRect.at(0).contains(mousePoint)) {
|
||||||
|
pressedArea[0] = true;
|
||||||
|
} else if (pressedRect.at(1).contains(mousePoint)) {
|
||||||
|
pressedArea[1] = true;
|
||||||
|
} else if (pressedRect.at(2).contains(mousePoint)) {
|
||||||
|
pressedArea[2] = true;
|
||||||
|
} else if (pressedRect.at(3).contains(mousePoint)) {
|
||||||
|
pressedArea[3] = true;
|
||||||
|
} else if (pressedRect.at(4).contains(mousePoint)) {
|
||||||
|
pressedArea[4] = true;
|
||||||
|
} else if (pressedRect.at(5).contains(mousePoint)) {
|
||||||
|
pressedArea[5] = true;
|
||||||
|
} else if (pressedRect.at(6).contains(mousePoint)) {
|
||||||
|
pressedArea[6] = true;
|
||||||
|
} else if (pressedRect.at(7).contains(mousePoint)) {
|
||||||
|
pressedArea[7] = true;
|
||||||
|
} else {
|
||||||
|
mousePressed = true;
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::MouseMove) {
|
||||||
|
//改成用HoverMove识别
|
||||||
|
} else if (event->type() == QEvent::MouseButtonRelease) {
|
||||||
|
//恢复所有
|
||||||
|
this->setCursor(Qt::ArrowCursor);
|
||||||
|
mousePressed = false;
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
pressedArea[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramelessWidget::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
if (watched == this) {
|
||||||
|
if (event->type() == QEvent::WindowStateChange) {
|
||||||
|
doWindowStateChange(event);
|
||||||
|
} else {
|
||||||
|
doResizeEvent(event);
|
||||||
|
}
|
||||||
|
} else if (watched == titleBar) {
|
||||||
|
//双击标题栏发出双击信号给主界面
|
||||||
|
//下面的 *result = HTCAPTION; 标志位也会自动识别双击标题栏
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
if (event->type() == QEvent::MouseButtonDblClick) {
|
||||||
|
emit titleDblClick();
|
||||||
|
} else if (event->type() == QEvent::NonClientAreaMouseButtonDblClick) {
|
||||||
|
emit titleDblClick();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return QWidget::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
bool FramelessWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
|
||||||
|
#else
|
||||||
|
bool FramelessWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (eventType == "windows_generic_MSG") {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
MSG *msg = static_cast<MSG *>(message);
|
||||||
|
//qDebug() << TIMEMS << "nativeEvent" << msg->wParam << msg->message;
|
||||||
|
|
||||||
|
//不同的消息类型和参数进行不同的处理
|
||||||
|
if (msg->message == WM_NCCALCSIZE) {
|
||||||
|
*result = 0;
|
||||||
|
return true;
|
||||||
|
} else if (msg->message == WM_NCHITTEST) {
|
||||||
|
//计算鼠标对应的屏幕坐标
|
||||||
|
long x = LOWORD(msg->lParam);
|
||||||
|
long y = HIWORD(msg->lParam);
|
||||||
|
QPoint pos = mapFromGlobal(QPoint(x, y));
|
||||||
|
|
||||||
|
//判断当前鼠标位置在哪个区域
|
||||||
|
bool left = pos.x() < padding;
|
||||||
|
bool right = pos.x() > width() - padding;
|
||||||
|
bool top = pos.y() < padding;
|
||||||
|
bool bottom = pos.y() > height() - padding;
|
||||||
|
|
||||||
|
//鼠标移动到四个角,这个消息是当鼠标移动或者有鼠标键按下时候发出的
|
||||||
|
*result = 0;
|
||||||
|
if (resizeEnable) {
|
||||||
|
if (left && top) {
|
||||||
|
*result = HTTOPLEFT;
|
||||||
|
} else if (left && bottom) {
|
||||||
|
*result = HTBOTTOMLEFT;
|
||||||
|
} else if (right && top) {
|
||||||
|
*result = HTTOPRIGHT;
|
||||||
|
} else if (right && bottom) {
|
||||||
|
*result = HTBOTTOMRIGHT;
|
||||||
|
} else if (left) {
|
||||||
|
*result = HTLEFT;
|
||||||
|
} else if (right) {
|
||||||
|
*result = HTRIGHT;
|
||||||
|
} else if (top) {
|
||||||
|
*result = HTTOP;
|
||||||
|
} else if (bottom) {
|
||||||
|
*result = HTBOTTOM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//先处理掉拉伸
|
||||||
|
if (0 != *result) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//识别标题栏拖动产生半屏全屏效果
|
||||||
|
if (titleBar != 0 && titleBar->rect().contains(pos)) {
|
||||||
|
QWidget *child = titleBar->childAt(pos);
|
||||||
|
if (!child) {
|
||||||
|
*result = HTCAPTION;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST) {
|
||||||
|
//系统休眠的时候自动最小化可以规避程序可能出现的问题
|
||||||
|
this->showMinimized();
|
||||||
|
} else if (msg->wParam == PBT_APMRESUMEAUTOMATIC) {
|
||||||
|
//休眠唤醒后自动打开
|
||||||
|
this->showNormal();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else if (eventType == "NSEvent") {
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
#endif
|
||||||
|
} else if (eventType == "xcb_generic_event_t") {
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
bool FramelessWidget::winEvent(MSG *message, long *result)
|
||||||
|
{
|
||||||
|
return nativeEvent("windows_generic_MSG", message, result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FramelessWidget::setPadding(int padding)
|
||||||
|
{
|
||||||
|
this->padding = padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::setMoveEnable(bool moveEnable)
|
||||||
|
{
|
||||||
|
this->moveEnable = moveEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::setResizeEnable(bool resizeEnable)
|
||||||
|
{
|
||||||
|
this->resizeEnable = resizeEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramelessWidget::setTitleBar(QWidget *titleBar)
|
||||||
|
{
|
||||||
|
this->titleBar = titleBar;
|
||||||
|
this->titleBar->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef FRAMELESSWIDGET_H
|
||||||
|
#define FRAMELESSWIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class FramelessWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FramelessWidget(QWidget *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//窗体显示的时候触发
|
||||||
|
void showEvent(QShowEvent *event);
|
||||||
|
|
||||||
|
//事件过滤器识别拖动拉伸等
|
||||||
|
void doWindowStateChange(QEvent *event);
|
||||||
|
void doResizeEvent(QEvent *event);
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event);
|
||||||
|
|
||||||
|
//拦截系统事件用于修复系统休眠后唤醒程序的BUG
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
|
||||||
|
#else
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Qt4的写法
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
bool winEvent(MSG *message, long *result);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
//边距+可移动+可拉伸
|
||||||
|
int padding;
|
||||||
|
bool moveEnable;
|
||||||
|
bool resizeEnable;
|
||||||
|
|
||||||
|
//标题栏控件
|
||||||
|
QWidget *titleBar;
|
||||||
|
|
||||||
|
//鼠标是否按下+按下坐标+按下时窗体区域
|
||||||
|
bool mousePressed;
|
||||||
|
QPoint mousePoint;
|
||||||
|
QRect mouseRect;
|
||||||
|
|
||||||
|
//鼠标是否按下某个区域+按下区域的大小
|
||||||
|
//依次为 左侧+右侧+上侧+下侧+左上侧+右上侧+左下侧+右下侧
|
||||||
|
QList<bool> pressedArea;
|
||||||
|
QList<QRect> pressedRect;
|
||||||
|
|
||||||
|
//记录是否最小化
|
||||||
|
bool isMin;
|
||||||
|
//存储窗体默认的属性
|
||||||
|
Qt::WindowFlags flags;
|
||||||
|
|
||||||
|
public:
|
||||||
|
//设置边距+可拖动+可拉伸
|
||||||
|
void setPadding(int padding);
|
||||||
|
void setMoveEnable(bool moveEnable);
|
||||||
|
void setResizeEnable(bool resizeEnable);
|
||||||
|
|
||||||
|
//设置标题栏控件
|
||||||
|
void setTitleBar(QWidget *titleBar);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void titleDblClick();
|
||||||
|
void windowStateChange(bool max);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FRAMELESSWIDGET_H
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include "dialog.h"
|
||||||
|
#include "ui_dialog.h"
|
||||||
|
#include "head.h"
|
||||||
|
|
||||||
|
Dialog::Dialog(QWidget *parent) : FramelessDialog(parent), ui(new Ui::Dialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
this->initForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog::~Dialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::initForm()
|
||||||
|
{
|
||||||
|
//设置标题栏控件
|
||||||
|
ui->labTitle->setText("无边框窗体示例-支持win、linux、mac等系统 (QQ: 517216493 WX: feiyangqingyun)");
|
||||||
|
this->setWindowTitle(ui->labTitle->text());
|
||||||
|
this->setTitleBar(ui->labTitle);
|
||||||
|
|
||||||
|
//关联信号
|
||||||
|
connect(this, SIGNAL(titleDblClick()), this, SLOT(titleDblClick()));
|
||||||
|
connect(this, SIGNAL(windowStateChange(bool)), this, SLOT(windowStateChange(bool)));
|
||||||
|
|
||||||
|
//设置样式表
|
||||||
|
QStringList list;
|
||||||
|
list << "#titleBar{background:#BBBBBB;}";
|
||||||
|
list << "#titleBar{border-top-left-radius:8px;border-top-right-radius:8px;}";
|
||||||
|
list << "#widgetMain{border:2px solid #BBBBBB;background:#FFFFFF;}";
|
||||||
|
//list << "#widgetMain{border-bottom-left-radius:8px;border-bottom-right-radius:8px;}";
|
||||||
|
this->setStyleSheet(list.join(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::titleDblClick()
|
||||||
|
{
|
||||||
|
on_btnMenu_Max_clicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::windowStateChange(bool max)
|
||||||
|
{
|
||||||
|
ui->btnMenu_Max->setText(max ? "还原" : "最大");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::on_btnMenu_Min_clicked()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
this->setWindowFlags(this->windowFlags() & ~Qt::FramelessWindowHint);
|
||||||
|
#endif
|
||||||
|
this->showMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::on_btnMenu_Max_clicked()
|
||||||
|
{
|
||||||
|
if (this->isMaximized()) {
|
||||||
|
this->showNormal();
|
||||||
|
ui->btnMenu_Max->setText("最大");
|
||||||
|
} else {
|
||||||
|
this->showMaximized();
|
||||||
|
ui->btnMenu_Max->setText("还原");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::on_btnMenu_Close_clicked()
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef DIALOG_H
|
||||||
|
#define DIALOG_H
|
||||||
|
|
||||||
|
#include "framelessdialog.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class Dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dialog : public FramelessDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Dialog(QWidget *parent = 0);
|
||||||
|
~Dialog();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::Dialog *ui;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initForm();
|
||||||
|
void titleDblClick();
|
||||||
|
void windowStateChange(bool max);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_btnMenu_Min_clicked();
|
||||||
|
void on_btnMenu_Max_clicked();
|
||||||
|
void on_btnMenu_Close_clicked();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DIALOG_H
|
|
@ -0,0 +1,215 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Dialog</class>
|
||||||
|
<widget class="QDialog" name="Dialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="titleBar" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labTitle">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widgetMenu" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>28</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Min">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>ArrowCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>最小化</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>最小</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Max">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>最大</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Close">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>ArrowCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>关闭</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>关闭</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widgetMain" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,14 @@
|
||||||
|
FORMS += \
|
||||||
|
$$PWD/dialog.ui \
|
||||||
|
$$PWD/mainwindow.ui \
|
||||||
|
$$PWD/widget.ui
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/dialog.h \
|
||||||
|
$$PWD/mainwindow.h \
|
||||||
|
$$PWD/widget.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/dialog.cpp \
|
||||||
|
$$PWD/mainwindow.cpp \
|
||||||
|
$$PWD/widget.cpp
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
#include "head.h"
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) : FramelessMainWindow(parent), ui(new Ui::MainWindow)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
this->initForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::initForm()
|
||||||
|
{
|
||||||
|
//设置标题栏控件
|
||||||
|
ui->labTitle->setText("无边框窗体示例-支持win、linux、mac等系统 (QQ: 517216493 WX: feiyangqingyun)");
|
||||||
|
this->setWindowTitle(ui->labTitle->text());
|
||||||
|
this->setTitleBar(ui->labTitle);
|
||||||
|
|
||||||
|
//关联信号
|
||||||
|
connect(this, SIGNAL(titleDblClick()), this, SLOT(titleDblClick()));
|
||||||
|
connect(this, SIGNAL(windowStateChange(bool)), this, SLOT(windowStateChange(bool)));
|
||||||
|
|
||||||
|
//设置样式表
|
||||||
|
QStringList list;
|
||||||
|
list << "#titleBar{background:#BBBBBB;}";
|
||||||
|
list << "#titleBar{border-top-left-radius:8px;border-top-right-radius:8px;}";
|
||||||
|
list << "#widgetMain{border:2px solid #BBBBBB;background:#FFFFFF;}";
|
||||||
|
//list << "#widgetMain{border-bottom-left-radius:8px;border-bottom-right-radius:8px;}";
|
||||||
|
this->setStyleSheet(list.join(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::titleDblClick()
|
||||||
|
{
|
||||||
|
on_btnMenu_Max_clicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::windowStateChange(bool max)
|
||||||
|
{
|
||||||
|
ui->btnMenu_Max->setText(max ? "还原" : "最大");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_btnMenu_Min_clicked()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
this->setWindowFlags(this->windowFlags() & ~Qt::FramelessWindowHint);
|
||||||
|
#endif
|
||||||
|
this->showMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_btnMenu_Max_clicked()
|
||||||
|
{
|
||||||
|
if (this->isMaximized()) {
|
||||||
|
this->showNormal();
|
||||||
|
ui->btnMenu_Max->setText("最大");
|
||||||
|
} else {
|
||||||
|
this->showMaximized();
|
||||||
|
ui->btnMenu_Max->setText("还原");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_btnMenu_Close_clicked()
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include "framelessmainwindow.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow : public FramelessMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initForm();
|
||||||
|
void titleDblClick();
|
||||||
|
void windowStateChange(bool max);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_btnMenu_Min_clicked();
|
||||||
|
void on_btnMenu_Max_clicked();
|
||||||
|
void on_btnMenu_Close_clicked();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINWINDOW_H
|
|
@ -0,0 +1,217 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="titleBar" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labTitle">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widgetMenu" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>28</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Min">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>ArrowCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>最小化</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>最小</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Max">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>最大</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Close">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>ArrowCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>关闭</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>关闭</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widgetMain" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include "widget.h"
|
||||||
|
#include "ui_widget.h"
|
||||||
|
#include "head.h"
|
||||||
|
|
||||||
|
Widget::Widget(QWidget *parent) : FramelessWidget(parent), ui(new Ui::Widget)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
this->initForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget::~Widget()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::initForm()
|
||||||
|
{
|
||||||
|
//设置标题栏控件
|
||||||
|
ui->labTitle->setText("无边框窗体示例-支持win、linux、mac等系统 (QQ: 517216493 WX: feiyangqingyun)");
|
||||||
|
this->setWindowTitle(ui->labTitle->text());
|
||||||
|
this->setTitleBar(ui->labTitle);
|
||||||
|
|
||||||
|
//关联信号
|
||||||
|
connect(this, SIGNAL(titleDblClick()), this, SLOT(titleDblClick()));
|
||||||
|
connect(this, SIGNAL(windowStateChange(bool)), this, SLOT(windowStateChange(bool)));
|
||||||
|
|
||||||
|
//设置样式表
|
||||||
|
QStringList list;
|
||||||
|
list << "#titleBar{background:#BBBBBB;}";
|
||||||
|
list << "#titleBar{border-top-left-radius:8px;border-top-right-radius:8px;}";
|
||||||
|
list << "#widgetMain{border:2px solid #BBBBBB;background:#FFFFFF;}";
|
||||||
|
//list << "#widgetMain{border-bottom-left-radius:8px;border-bottom-right-radius:8px;}";
|
||||||
|
this->setStyleSheet(list.join(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::titleDblClick()
|
||||||
|
{
|
||||||
|
on_btnMenu_Max_clicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::windowStateChange(bool max)
|
||||||
|
{
|
||||||
|
ui->btnMenu_Max->setText(max ? "还原" : "最大");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::on_btnMenu_Min_clicked()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
this->setWindowFlags(this->windowFlags() & ~Qt::FramelessWindowHint);
|
||||||
|
#endif
|
||||||
|
this->showMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::on_btnMenu_Max_clicked()
|
||||||
|
{
|
||||||
|
if (this->isMaximized()) {
|
||||||
|
this->showNormal();
|
||||||
|
ui->btnMenu_Max->setText("最大");
|
||||||
|
} else {
|
||||||
|
this->showMaximized();
|
||||||
|
ui->btnMenu_Max->setText("还原");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::on_btnMenu_Close_clicked()
|
||||||
|
{
|
||||||
|
this->close();
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef WIDGET_H
|
||||||
|
#define WIDGET_H
|
||||||
|
|
||||||
|
#include "framelesswidget.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class Widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Widget : public FramelessWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Widget(QWidget *parent = 0);
|
||||||
|
~Widget();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::Widget *ui;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initForm();
|
||||||
|
void titleDblClick();
|
||||||
|
void windowStateChange(bool max);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_btnMenu_Min_clicked();
|
||||||
|
void on_btnMenu_Max_clicked();
|
||||||
|
void on_btnMenu_Close_clicked();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WIDGET_H
|
|
@ -0,0 +1,215 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Widget</class>
|
||||||
|
<widget class="QWidget" name="Widget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="titleBar" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labTitle">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widgetMenu" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>28</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Min">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>ArrowCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>最小化</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>最小</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Max">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>最大</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnMenu_Close">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>ArrowCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>关闭</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>关闭</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widgetMain" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,21 @@
|
||||||
|
QT += core gui
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
|
||||||
|
|
||||||
|
TARGET = frameless
|
||||||
|
TEMPLATE = app
|
||||||
|
DESTDIR = $$PWD/../bin
|
||||||
|
|
||||||
|
CONFIG += warn_off
|
||||||
|
HEADERS += head.h
|
||||||
|
SOURCES += main.cpp
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
INCLUDEPATH += $$PWD/form
|
||||||
|
include ($$PWD/form/form.pri)
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../core_frameless
|
||||||
|
include ($$PWD/../core_frameless/core_frameless.pri)
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../core_common
|
||||||
|
include ($$PWD/../core_common/core_common.pri)
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QtGui>
|
||||||
|
|
||||||
|
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
|
||||||
|
#include <QtWidgets>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
#include <QtCore5Compat>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
|
||||||
|
#define DATETIME qPrintable(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"))
|
||||||
|
#pragma execution_character_set("utf-8")
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "quihelper.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "widget.h"
|
||||||
|
#include "dialog.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
|
||||||
|
#endif
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
|
QUIHelper::setStyle();
|
||||||
|
QUIHelper::setFont(15);
|
||||||
|
QUIHelper::setCode();
|
||||||
|
|
||||||
|
MainWindow w;
|
||||||
|
//Widget w;
|
||||||
|
//Dialog w;
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
|
||||||
|
w.resize(800, 600);
|
||||||
|
#else
|
||||||
|
w.resize(800, 550);
|
||||||
|
#endif
|
||||||
|
QUIHelper::setFormInCenter(&w);
|
||||||
|
w.show();
|
||||||
|
return a.exec();
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
### 一 前言
|
||||||
|
不知道各位程序员有没有遇到过这样一种困惑,好不容易在开源网站找到了类似的想要的项目代码,结果down下来一编译,我勒个去,几百个错误,根本没法用,熟悉的人还好可以直接阅读代码进行修改(有些只要做小改动就能正常编译,有些可能需要大刀阔斧),可是对于绝大部分的初学者来说绝对是噩梦,连把代码看下去的勇气都没有,我们没有任何权利和理由去责怪开原作者,只是期望各位能够在项目开源的同时,将开源项目完善好、测试好,最起码要把项目中依赖的遗漏的文件一起打包好,或者作出必要的说明,比如对应的开发编译版本要求,以来的文件去哪里下载。很多优秀的项目就毁在这个地方,没人完善和维护(可能因为没有耐心,也没有持续的收入来源,所以干的没劲,作者甚至转行送外卖了)。只有解决了这个痛点才能使得对应的开源项目持续发光发热。
|
||||||
|
|
||||||
|
本人自从学习Qt开发以来,开源过至少上百个项目(大部分早期开源的目前不在开源主页,有空会全部整理好重新发布),我要是说在国内Qt界开源的项目数量和质量排第十的话,没人敢说排第一、第二、第三...到第九。关于无边框界面方案,网上也有不少的优秀的开源的例子,99%都存在以下几个问题,针对以上问题,解决这些痛点,借助自己刚好有多个操作系统、几十个Qt版本的开发测试环境,特意完善了这个无边框类。
|
||||||
|
|
||||||
|
- 无法正常编译,缺少文件,作者真粗心,自己都没测试过。
|
||||||
|
- 只限定了部分特定的版本才能编译。
|
||||||
|
- 只解决了单个问题,比如无边框拖动,没有系统特性拉到左侧右侧半屏、顶部最大化。
|
||||||
|
- 代码赶鸭子上架,复制粘贴的一坨坨,毫无章法。
|
||||||
|
- 代码就是给作者自己用的,放上去就是给个参考,管他那么多。
|
||||||
|
- 往左侧拉动抖动的厉害。
|
||||||
|
- mac系统上不能最小化。
|
||||||
|
- 不能同时支持win、linux、mac三种主流操作系统。
|
||||||
|
|
||||||
|
### 二 功能特点
|
||||||
|
1. 同时支持Qt4-Qt6,亲测Qt4.7到Qt6.2以及后续版本。
|
||||||
|
2. 同时支持mingw、msvc、gcc等。
|
||||||
|
3. 同时支持windows、linux、mac。
|
||||||
|
4. 同时支持QMainWindow、QWidget、QDialog。
|
||||||
|
5. 使用方法极其简单,只需要将继承类修改即可。
|
||||||
|
6. 自动识别双击标题栏响应。
|
||||||
|
7. 无边框拉伸在windows下不抖动。
|
||||||
|
8. 在windows下具有移动到边缘半屏、移动到顶部全屏特性。
|
||||||
|
9. 解决mac系统上无边框最小化最大化失效的BUG。
|
||||||
|
10. 解决系统休眠后再次启动程序懵逼的BUG。
|
||||||
|
11. 解决有时候窗体重新显示的时候假死不刷新的BUG。
|
||||||
|
12. 轻量级,1个代码文件,核心代码行数不到300行。
|
||||||
|
13. 注释详细,示例完美,非常适合阅读和学习。
|
||||||
|
14. 开源开箱即用,保证任意Qt版本可正常编译运行,无需任何调整。
|
||||||
|
|
||||||
|
### 三 效果图
|
||||||
|
#### 1 windows
|
||||||
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/frameless/snap/win.gif)
|
||||||
|
|
||||||
|
#### 2 ubuntu
|
||||||
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/frameless/snap/ubuntu.gif)
|
||||||
|
|
||||||
|
#### 3 uos
|
||||||
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/frameless/snap/uos.gif)
|
||||||
|
|
||||||
|
#### 4 kylin
|
||||||
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/frameless/snap/kylin.gif)
|
||||||
|
|
||||||
|
#### 5 mac
|
||||||
|
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/frameless/snap/mac.gif)
|
||||||
|
|
||||||
|
### 四 特别说明
|
||||||
|
1. 点赞、评论、留言、转发、发代码。
|
||||||
|
2. 国内站点:[https://gitee.com/feiyangqingyun/QWidgetDemo](https://gitee.com/feiyangqingyun/QWidgetDemo)
|
||||||
|
3. 国际站点:[https://github.com/feiyangqingyun/QWidgetDemo](https://github.com/feiyangqingyun/QWidgetDemo)
|
Binary file not shown.
After Width: | Height: | Size: 460 KiB |
Binary file not shown.
After Width: | Height: | Size: 720 KiB |
Binary file not shown.
After Width: | Height: | Size: 841 KiB |
Binary file not shown.
After Width: | Height: | Size: 323 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
Loading…
Reference in New Issue