QT随记
记录随手写的QT代码
一个基于纯代码的Windows风格窗体实现
前言
一直觉得Qt自带的窗体留给我们自定义的空间太小了,所以参考了网上大神代码的基础上改了现在这个用纯代码写的窗体。基本实现了该有的基础功能吧,接下来剩下的就可以根据需求自由发挥了。直接贴代码了,很简单,也就没写啥注释。
.h文件
#ifndef CUSTOMW_H
#define CUSTOMW_H
#include <QWidget>
#include <QMouseEvent>
#include <QApplication>
#include <QPainter>
#include <QTime>
#include <QPushButton>
enum {
Minimized = 1 ,
Maximized = 2 ,
closed = 3
};
enum {
TOPLEFT = 11,
TOP = 12,
TOPRIGHT = 13,
LEFT = 21,
CENTER = 22,
RIGHT = 23,
BUTTOMLEFT = 31,
BUTTOM = 32,
BUTTOMRIGHT = 33,
ToMinimize = 1,
ToMaximize = 2,
Closed = 3
};
#define FRAMESHAPE 10
class customW : public QWidget
{
Q_OBJECT
public:
explicit customW(QWidget *parent = nullptr);
protected:
// 双击标题栏进行界面的最大化/还原
virtual void mouseDoubleClickEvent(QMouseEvent *event);
// 进行鼠界面的拖动
virtual void mousePressEvent(QMouseEvent *event);
// 设置界面标题与图标
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
private:
void paintEvent(QPaintEvent *e);
int CalCursorCol(QPoint pt); //计算鼠标X的位置
int CalCursorPos(QPoint pt, int colPos); //计算鼠标的位置
void setCursorShape(int CalPos); //设置鼠标对应位置的形状
public:
void OnClicked( int index);
void setDoubleclickflag(bool value);
void setMoveflag(bool value);
void setResizeflag(bool value);
void setStatusbarflag(bool value);
void setTitletext(const QString &value);
private:
int m_iCalCursorPos;
bool m_bLeftPress;
bool m_rightPress;
QRect m_rtPreGeometry;
QPoint m_currentPosition;
QPoint m_ptViewMousePos;
bool statusbarflag; //是否显示状态栏
bool doubleclickflag; //是否允许双击标题栏最大化最小化
bool moveflag ; //是否允许移动
bool resizeflag; //是否允许修改尺寸
QString titletext; //标题
int MinBtnState;
int MaxBtnState;
int CloseBtnState;
QRect MinRect;
QRect MaxRect;
QRect CloseRect;
signals:
void mousePress(QMouseEvent *event);
void widgetResizeChange();
};
#endif // CUSTOMW_H
.cpp文件
#include "customw.h"
#include <QDebug>
customW::customW(QWidget *parent) : QWidget(parent),
statusbarflag(true),
doubleclickflag(true),
resizeflag(true),
moveflag(true),
CloseBtnState(0)
{
setWindowFlags(windowFlags()|Qt::FramelessWindowHint);
setWindowState(Qt::WindowNoState );
setFocusPolicy(Qt::NoFocus);
this->setMouseTracking(true);
m_rightPress = false;
m_bLeftPress = false;
}
void customW::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_UNUSED(event);
if(event->y() < 30 && doubleclickflag)
{
OnClicked(Maximized);
}
}
void customW::mousePressEvent(QMouseEvent *event)
{
判断鼠标所在Rect
if(MinRect.contains(event->pos()))
{
MinBtnState = 2 ;
update();
return;
}
if(MaxRect.contains(event->pos()))
{
MaxBtnState = 2 ;
update();
return;
}
if(CloseRect.contains(event->pos()))
{
CloseBtnState = 2 ;
update();
return;
}
m_iCalCursorPos = CalCursorPos(event->pos(),CalCursorCol(event->pos()));//鼠标在窗口的相近位置整数型
if (event->button() == Qt::LeftButton &&!this->isMaximized() )
{
if(m_iCalCursorPos != CENTER && resizeflag)//CENTER=22
{
m_bLeftPress = true;
}
else if(moveflag)
{
m_rightPress = true;
setCursor(Qt::SizeAllCursor);
}
}
m_rtPreGeometry = geometry();//窗口几何矩形
m_currentPosition = this->pos();
m_ptViewMousePos = event->globalPos();//鼠标按下时的全局点
emit mousePress(event);
}
void customW::mouseMoveEvent(QMouseEvent *event)
{
计算Rect位置
MinRect.setRect(width()-210,0,70,30);
MaxRect.setRect(width()-140,0,70,30);
CloseRect.setRect(width()-70,0,70,30);
判断鼠标所在Rect
if(CloseBtnState == 2 || MinBtnState == 2 || MaxBtnState == 2)
return;
if(MinRect.contains(event->pos()) )
MinBtnState = 1 ;
else
MinBtnState = 0 ;
if(MaxRect.contains(event->pos()))
MaxBtnState = 1 ;
else
MaxBtnState = 0 ;
if(CloseRect.contains(event->pos()))
CloseBtnState = 1 ;
else
CloseBtnState = 0 ;
update();
if(CloseBtnState == 1 || MinBtnState == 1 || MaxBtnState == 1)
return;
//窗体不是最大的话就改变鼠标的形状
if(Qt::WindowMaximized != windowState())
{
setCursorShape(CalCursorPos(event->pos(),CalCursorCol(event->pos())));
}
//获取当前的点,这个点是全局的
QPoint ptCurrentPos = QCursor::pos();
//计算出移动的位置,当前点 - 鼠标左键按下的点
QPoint ptMoveSize = ptCurrentPos - m_ptViewMousePos;
QRect rtTempGeometry = m_rtPreGeometry;//窗口矩形
if(m_bLeftPress)
{
switch(m_iCalCursorPos)
{
case TOPLEFT:
rtTempGeometry.setTopLeft(m_rtPreGeometry.topLeft()+ptMoveSize);
break;
case TOP:
rtTempGeometry.setTop(m_rtPreGeometry.top()+ptMoveSize.y());
break;
case TOPRIGHT:
rtTempGeometry.setTopRight(m_rtPreGeometry.topRight()+ptMoveSize);
break;
case LEFT:
rtTempGeometry.setLeft(m_rtPreGeometry.left()+ptMoveSize.x());
break;
case RIGHT:
rtTempGeometry.setRight(m_rtPreGeometry.right()+ptMoveSize.x());
break;
case BUTTOMLEFT:
rtTempGeometry.setBottomLeft(m_rtPreGeometry.bottomLeft()+ptMoveSize);
break;
case BUTTOM:
rtTempGeometry.setBottom(m_rtPreGeometry.bottom()+ptMoveSize.y());
break;
case BUTTOMRIGHT:
rtTempGeometry.setBottomRight(m_rtPreGeometry.bottomRight()+ptMoveSize);
break;
default:
break;
}
//移动窗体,如果比最小窗体大,就移动
if(rtTempGeometry.width() >= 200 && rtTempGeometry.height() >= 300)
setGeometry(rtTempGeometry);
}
else if(m_rightPress)
{
setCursor(Qt::SizeAllCursor);
this->move(m_currentPosition + ptMoveSize);
}
}
void customW::mouseReleaseEvent(QMouseEvent *event)
{
if(MinRect.contains(event->pos()) )
MinBtnState = 1 ;
else
MinBtnState = 0 ;
if(MaxRect.contains(event->pos()))
MaxBtnState = 1 ;
else
MaxBtnState = 0 ;
if(CloseRect.contains(event->pos()))
CloseBtnState = 1 ;
else
CloseBtnState = 0 ;
if(MinBtnState == 1)
OnClicked(Minimized);
if(MaxBtnState == 1)
OnClicked(Maximized);
if(CloseBtnState == 1)
OnClicked(closed);
update();
Q_UNUSED(event)
m_bLeftPress = false;
m_rightPress = false;
setCursor(Qt::ArrowCursor);
QApplication::restoreOverrideCursor();
}
void customW::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e)
QPainter painter(this);
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(231, 234, 237));
painter.drawRect(0,0, width(),30);
painter.restore();
painter.save();
painter.setPen(Qt::NoPen);
///画背景
if(MinBtnState == 0) //最小化按键初始状态
{
painter.setBrush(QColor(231, 234, 237));
}
else if(MinBtnState == 1) //最小化悬浮状态
{
painter.setBrush(QColor(209, 209, 209));
}
else if(MinBtnState == 2) //最小化按键按下状态
{
painter.setBrush(QColor(150, 150, 150));
}
painter.drawRect(MinRect);
if(MaxBtnState == 0) //最大化按键初始状态
{
painter.setBrush(QColor(231, 234, 237));
}
else if(MaxBtnState == 1) //最大化悬浮状态
{
painter.setBrush(QColor(209, 209, 209));
}
else if(MaxBtnState == 2) //最大化按键按下状态
{
painter.setBrush(QColor(150, 150, 150));
}
painter.drawRect(MaxRect);
if(CloseBtnState == 0) //关闭按键初始状态
{
painter.setBrush(QColor(231, 234, 237));
}
else if(CloseBtnState == 1) //关闭悬浮状态
{
painter.setBrush(QColor(255, 0, 0));
}
else if(CloseBtnState == 2) //关闭按键按下状态
{
painter.setBrush(QColor(255, 137, 137));
}
painter.drawRect(CloseRect);
painter.restore();
//
///画符号
painter.save();
painter.setPen(QPen{QColor(20,20,20),4});
painter.drawLine(width()-181,15,width()-168,15); ///最下化
painter.setPen(QPen{QColor(20,20,20),2});
if(this->window()->isFullScreen())
{
QPointF pointB[5] =
{
QPointF(width()-108,12),
QPointF(width()-108,9),
QPointF(width()-93,9),
QPointF(width()-93,20),
QPointF(width()-99,20),
};
painter.drawLine(pointB[0],pointB[1]);
painter.drawLine(pointB[1],pointB[2]);
painter.drawLine(pointB[2],pointB[3]);
painter.drawLine(pointB[3],pointB[4]);
QPointF pointF[4] =
{
QPointF(width()-114,13),
QPointF(width()-99,13),
QPointF(width()-99,24),
QPointF(width()-114,24),
};
painter.drawConvexPolygon(pointF,4);
}
else
{
QPointF pointG[4] =
{
QPointF(width()-116,7),
QPointF(width()-95,7),
QPointF(width()-95,23),
QPointF(width()-116,23),
};
painter.drawConvexPolygon(pointG,4);
}
if(CloseBtnState == 0) ///关闭
{
painter.setPen(QPen{QColor(20,20,20),4});
}
else
{
painter.setPen(QPen{QColor(255,255,255),4});
}
painter.drawLine(width()-41,9,width()-28,22);
painter.drawLine(width()-41,22,width()-28,9);
painter.restore();
写标题
painter.save();
QFont font{this->font().family()};
font.setBold(true);
font.setPixelSize(20);
painter.setFont(font);
painter.drawText(QRect{30,0,500,30},Qt::AlignLeft|Qt::AlignVCenter,titletext);
painter.restore();
}
int customW::CalCursorCol(QPoint pt)
{
return (pt.x() < FRAMESHAPE ?
1 : ((pt.x() > this->width() - FRAMESHAPE) ? 3 : 2));//返回整数型位置个位
}
int customW::CalCursorPos(QPoint pt, int colPos)
{
return ((pt.y() < FRAMESHAPE ?
10 : ((pt.y() > this->height() - FRAMESHAPE) ? 30 : 20)) + colPos);//返回整数型位置十位和个位
}
void customW::setCursorShape(int CalPos)
{
Qt::CursorShape cursor;
switch(CalPos)
{
case TOPLEFT:
case BUTTOMRIGHT:
cursor = Qt::SizeFDiagCursor;
break;
case TOPRIGHT:
case BUTTOMLEFT:
cursor = Qt::SizeBDiagCursor;
break;
case TOP:
case BUTTOM:
cursor = Qt::SizeVerCursor;
break;
case LEFT:
case RIGHT:
cursor = Qt::SizeHorCursor;
break;
default:
cursor = Qt::ArrowCursor;
break;
}
setCursor(cursor);
}
void customW::OnClicked( int index)
{
QWidget *pWindow = this->window();
if (pWindow->isTopLevel())
{
if (index == Minimized)
{
pWindow->showMinimized();
}
else if (index == Maximized)
{
pWindow->isFullScreen() ? pWindow->showNormal() : pWindow->showFullScreen();
}
else if (index == closed)
{
pWindow->close();
}
}
MinBtnState = 0;
MaxBtnState = 0;
CloseBtnState = 0;
}
void customW::setDoubleclickflag(bool value)
{
doubleclickflag = value;
}
void customW::setMoveflag(bool value)
{
moveflag = value;
}
void customW::setResizeflag(bool value)
{
resizeflag = value;
}
void customW::setTitletext(const QString &value)
{
titletext = value;
update();
}
void customW::setStatusbarflag(bool value)
{
statusbarflag = value;
update();
}
使用
添加头文件,直接继承这个类就可以了
就像这样
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "customw.h"
namespace Ui {
class Widget;
}
class Widget : public customW
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
或者在UI文件里提升!!!!
总结
写的第一篇博客,总结就是没有总结!哈哈
哦对了,网上参考的代码好久之前看到的了,实在是没找到出处,原作看到请见谅呀!!!!