概述
Qt中已经为我们封装了很好用的窗口风格,但在实际开发过程当中,要么需求要么UI抛过来的界面要求总是平添许多工作量。今天得空便来记录下我在项目中实现的一个需求:扁平化界面风格。虽然可能还会在未来的使用过程中暴露出一些问题,但目前还是可以满足基本使用需求的。
进入正题,首先我们必须创建一个基于QDialog的带界面的类,然后对Qt生成的窗体进行改造,再在代码中应用信号槽机制实现类似于原生窗体的事件交互。下面是实现代码:
YMDialog.h
#ifndef YMDIALOG_H
#define YMDIALOG_H
#include <QtWidgets/QDialog>
#include <QMouseEvent>
#include <QPoint>
#include "ui_YMDialog.h"
#define PADDING 2
enum Direction { UP=0, DOWN=1, LEFT, RIGHT, LEFTTOP, LEFTBOTTOM, RIGHTBOTTOM, RIGHTTOP, NONE };
//无边框窗口
class YMDialog : public QDialog
{
Q_OBJECT
public:
YMDialog(QWidget *parent = 0);
~YMDialog();
void mousePressEvent(QMouseEvent * e);
void mouseReleaseEvent(QMouseEvent * e);
void mouseMoveEvent(QMouseEvent * e);
void region(const QPoint &cursorGlobalPoint);
public slots:
void minButtonSlot();
void maxButtonSlot();
void closeButtonSlot();
private:
Ui::YMDialogClass ui;
QPoint move_point; //移动的距离
bool mouse_press; //鼠标按下
bool isNormal;
QSize nomalSize;
QSize maxSize;
QPoint nomalPoint;
QPoint maxPoint;
bool isLeftPressDown; // 判断左键是否按下
QPoint dragPosition; // 窗口移动拖动时需要记住的点
Direction dir; // 窗口大小改变时,记录改变方向
};
#endif // YMDIALOG_H
YMDialog.cpp
#include "YMDialog.h"
#include <QToolButton>
#include <QLabel>
#include <QAction>
#include <QDesktopWidget>
YMDialog::YMDialog(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
nomalSize.setWidth(600);
nomalSize.setHeight(400);
isNormal = true;
QDesktopWidget* detk = QApplication::desktop();
nomalPoint.setX((detk->width() - this->width())/2);
nomalPoint.setY((detk->height() - this->height())/2);
maxSize.setWidth(detk->width());
maxSize.setHeight(detk->height());
maxPoint.setX(detk->availableGeometry().x());
maxPoint.setY(detk->availableGeometry().y());
dir = NONE;
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
setMouseTracking(true);
ui.widget->setMouseTracking(true);
//自定义背景1
//QLabel * background = new QLabel(this);
//background->setStyleSheet("background-color:rgb(120, 120, 255)");
//background->setGeometry(0,0,this->width(),this->height());
//background->setMouseTracking(true);
//background->setPixmap(QPixmap(":/YMDialog/Resources/background.png"));
//background->setGeometry(0,0,this->width(),this->height());
//设置图片充满整个label
//background->setScaledContents(true);
//获取最大化、最小化、关闭按钮图标
QPixmap minPix = style()->standardPixmap(QStyle::SP_TitleBarMinButton);
QPixmap maxPix = style()->standardPixmap(QStyle::SP_TitleBarMaxButton);
QPixmap closePix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton);
//为按钮设置图标
ui.minbtn->setIcon(minPix);
ui.maxbtn->setIcon(maxPix);
ui.closebtn->setIcon(closePix);
int width = this->width(); //获取界面的宽度
//设置按钮在窗口上的位置
ui.minbtn->setGeometry(width-67,5,20,20);
ui.maxbtn->setGeometry(width-46,5,20,20);
ui.closebtn->setGeometry(width-25,5,20,20);
//设置按钮的提示信息
ui.minbtn->setToolTip(QStringLiteral("最小化"));
ui.maxbtn->setToolTip(QStringLiteral("最大化"));
ui.closebtn->setToolTip(QStringLiteral("关闭"));
//设置按钮样式
//ui.minbtn->setStyleSheet("background-color:transparent");
//ui.maxbtn->setStyleSheet("background-color:transparent");
//ui.closebtn->setStyleSheet("background-color:transparent");
ui.minbtn->setStyleSheet("QToolButton{background-color:transparent;}"
"QToolButton:hover{border: 0px;background-color: rgb(141, 141, 141);}"
"QToolButton:pressed{background-color: rgb(86, 86, 86);}");
ui.maxbtn->setStyleSheet("QToolButton{background-color:transparent;}"
"QToolButton:hover{border: 0px;background-color: rgb(141, 141, 141);}"
"QToolButton:pressed{background-color: rgb(86, 86, 86);}");
ui.closebtn->setStyleSheet("QToolButton{background-color:transparent;}"
"QToolButton:hover{border: 0px;background-color: rgb(141, 141, 141);}"
"QToolButton:pressed{background-color: rgb(86, 86, 86);}");
//this->setStyleSheet("background-color: rgb(95, 143, 143);");
connect(ui.minbtn,SIGNAL(clicked()),this, SLOT(minButtonSlot()));
connect(ui.maxbtn,SIGNAL(clicked()),this, SLOT(maxButtonSlot()));
connect(ui.closebtn,SIGNAL(clicked()),this, SLOT(closeButtonSlot()));
mouse_press = false;
//QFile file(":/YMDialog/qss/coffee.qss");
//file.open(QFile::ReadOnly);
//QString styleSheet = QString::fromLatin1(file.readAll());
//qApp->setStyleSheet(styleSheet);
}
YMDialog::~YMDialog()
{
}
void YMDialog::mousePressEvent( QMouseEvent * e )
{
if (e->button() == Qt::LeftButton)
{
mouse_press = true;
move_point = e->pos();
if(dir != NONE)
{
this->mouseGrabber();
} else
{
dragPosition = e->globalPos() - this->frameGeometry().topLeft();
}
}
}
void YMDialog::mouseReleaseEvent( QMouseEvent * e )
{
mouse_press = false;
if(dir != NONE)
{
this->releaseMouse();
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
void YMDialog::mouseMoveEvent( QMouseEvent * e )
{
QPoint gloPoint = e->globalPos();
QRect rect = this->rect();
QPoint tl = mapToGlobal(rect.topLeft());
QPoint rb = mapToGlobal(rect.bottomRight());
if(!mouse_press)
{
this->region(gloPoint);
} else
{
if(dir != NONE)
{
QRect rMove(tl, rb);
switch(dir)
{
case LEFT:
if(rb.x() - gloPoint.x() <= this->minimumWidth())
rMove.setX(tl.x());
else
rMove.setX(gloPoint.x());
break;
case RIGHT:
rMove.setWidth(gloPoint.x() - tl.x());
break;
case UP:
if(rb.y() - gloPoint.y() <= this->minimumHeight())
rMove.setY(tl.y());
else
rMove.setY(gloPoint.y());
break;
case DOWN:
rMove.setHeight(gloPoint.y() - tl.y());
break;
case LEFTTOP:
if(rb.x() - gloPoint.x() <= this->minimumWidth())
rMove.setX(tl.x());
else
rMove.setX(gloPoint.x());
if(rb.y() - gloPoint.y() <= this->minimumHeight())
rMove.setY(tl.y());
else
rMove.setY(gloPoint.y());
break;
case RIGHTTOP:
rMove.setWidth(gloPoint.x() - tl.x());
rMove.setY(gloPoint.y());
break;
case LEFTBOTTOM:
rMove.setX(gloPoint.x());
rMove.setHeight(gloPoint.y() - tl.y());
break;
case RIGHTBOTTOM:
rMove.setWidth(gloPoint.x() - tl.x());
rMove.setHeight(gloPoint.y() - tl.y());
break;
default:
break;
}
this->setGeometry(rMove);
} else
{
QPoint move_pos = e->globalPos();
this->move(move_pos - move_point);
}
}
QDialog::mouseMoveEvent(e);
}
void YMDialog::minButtonSlot()
{
this->showMinimized();
}
void YMDialog::maxButtonSlot()
{
if(isNormal)
{
//this->showMaximized();
this->setGeometry(maxPoint.x(),maxPoint.y(),maxSize.width(),maxSize.height());
isNormal = false;
}
else
{
this->setGeometry(nomalPoint.x(),nomalPoint.y(),nomalSize.width(),nomalSize.height());
isNormal = true;
}
}
void YMDialog::closeButtonSlot()
{
this->close();
}
void YMDialog::region(const QPoint &cursorGlobalPoint)
{
// 获取窗体在屏幕上的位置区域,tl为topleft点,rb为rightbottom点
QRect rect = this->rect();
QPoint tl = mapToGlobal(rect.topLeft());
QPoint rb = mapToGlobal(rect.bottomRight());
int x = cursorGlobalPoint.x();
int y = cursorGlobalPoint.y();
if(tl.x() + PADDING >= x && tl.x() <= x && tl.y() + PADDING >= y && tl.y() <= y)
{
// 左上角
dir = LEFTTOP;
this->setCursor(QCursor(Qt::SizeFDiagCursor)); // 设置鼠标形状
} else if(x >= rb.x() - PADDING && x <= rb.x() && y >= rb.y() - PADDING && y <= rb.y())
{
// 右下角
dir = RIGHTBOTTOM;
this->setCursor(QCursor(Qt::SizeFDiagCursor));
} else if(x <= tl.x() + PADDING && x >= tl.x() && y >= rb.y() - PADDING && y <= rb.y())
{
//左下角
dir = LEFTBOTTOM;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
} else if(x <= rb.x() && x >= rb.x() - PADDING && y >= tl.y() && y <= tl.y() + PADDING)
{
// 右上角
dir = RIGHTTOP;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
} else if(x <= tl.x() + PADDING && x >= tl.x())
{
// 左边
dir = LEFT;
this->setCursor(QCursor(Qt::SizeHorCursor));
} else if( x <= rb.x() && x >= rb.x() - PADDING)
{
// 右边
dir = RIGHT;
this->setCursor(QCursor(Qt::SizeHorCursor));
}else if(y >= tl.y() && y <= tl.y() + PADDING)
{
// 上边
dir = UP;
this->setCursor(QCursor(Qt::SizeVerCursor));
} else if(y <= rb.y() && y >= rb.y() - PADDING)
{
// 下边
dir = DOWN;
this->setCursor(QCursor(Qt::SizeVerCursor));
}else
{
// 默认
dir = NONE;
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
界面ui文件
/********************************************************************************
** Form generated from reading UI file 'YMDialog.ui'
**
** Created by: Qt User Interface Compiler version 5.5.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_YMDIALOG_H
#define UI_YMDIALOG_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QToolButton>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_YMDialogClass
{
public:
QVBoxLayout *verticalLayout;
QWidget *widget_2;
QHBoxLayout *horizontalLayout_2;
QSpacerItem *horizontalSpacer;
QToolButton *minbtn;
QToolButton *maxbtn;
QToolButton *closebtn;
QWidget *widget;
void setupUi(QDialog *YMDialogClass)
{
if (YMDialogClass->objectName().isEmpty())
YMDialogClass->setObjectName(QStringLiteral("YMDialogClass"));
YMDialogClass->resize(390, 600);
YMDialogClass->setStyleSheet(QStringLiteral(""));
verticalLayout = new QVBoxLayout(YMDialogClass);
verticalLayout->setSpacing(0);
verticalLayout->setContentsMargins(11, 11, 11, 11);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
verticalLayout->setContentsMargins(0, 0, 0, 0);
widget_2 = new QWidget(YMDialogClass);
widget_2->setObjectName(QStringLiteral("widget_2"));
widget_2->setMaximumSize(QSize(16777215, 25));
widget_2->setStyleSheet(QStringLiteral("background-color: rgb(255, 255, 255);"));
horizontalLayout_2 = new QHBoxLayout(widget_2);
horizontalLayout_2->setSpacing(0);
horizontalLayout_2->setContentsMargins(11, 11, 11, 11);
horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
horizontalLayout_2->setContentsMargins(0, 0, 0, 0);
horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer);
minbtn = new QToolButton(widget_2);
minbtn->setObjectName(QStringLiteral("minbtn"));
horizontalLayout_2->addWidget(minbtn);
maxbtn = new QToolButton(widget_2);
maxbtn->setObjectName(QStringLiteral("maxbtn"));
horizontalLayout_2->addWidget(maxbtn);
closebtn = new QToolButton(widget_2);
closebtn->setObjectName(QStringLiteral("closebtn"));
horizontalLayout_2->addWidget(closebtn);
verticalLayout->addWidget(widget_2);
widget = new QWidget(YMDialogClass);
widget->setObjectName(QStringLiteral("widget"));
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(widget->sizePolicy().hasHeightForWidth());
widget->setSizePolicy(sizePolicy);
widget->setStyleSheet(QStringLiteral("background-color: rgb(255, 255, 255);"));
verticalLayout->addWidget(widget);
retranslateUi(YMDialogClass);
QMetaObject::connectSlotsByName(YMDialogClass);
} // setupUi
void retranslateUi(QDialog *YMDialogClass)
{
YMDialogClass->setWindowTitle(QApplication::translate("YMDialogClass", "YMDialog", 0));
minbtn->setText(QString());
maxbtn->setText(QString());
closebtn->setText(QString());
} // retranslateUi
};
namespace Ui {
class YMDialogClass: public Ui_YMDialogClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_YMDIALOG_H
注意:承载实际功能区最底层的widget需要设置setMouseTracking(true),否则将跟踪不到鼠标的拖动事件。
最后
以上就是开朗美女为你收集整理的Qt实现自定义窗体的全部内容,希望文章能够帮你解决Qt实现自定义窗体所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复