QT自定义窗口

在这里自定义窗口是通过继承于QFrame,内部分为上下两部分,上半部分就是标题栏,下面是窗口的具体内容。上下两部分通过布局固定位置。最后窗口的各种鼠标拖动,缩放,等操作通过添加鼠标事件来完成一个窗口的常规功能。当然,这个标题栏可以通过布局的改变把它放到任意地方。

下面是实现的代码:
#pragma once
#ifndef CUSTOMWIDGET_H_
#define CUSTOMWIDGET_H_

#include <QtWidgets/QFrame>

class QToolButton;
class CustomWidget : public QFrame
{

Q_OBJECT

public:

explicit CustomWidget();
~CustomWidget();
void setContentWidget(QWidget *contentWidget);
void setTitleInfo(const QString &titleString, const QPixmap &windowIcon);

public slots:

void slotShowSmall();
void slotShowMaxRestore();
void onMoveWindow();

signals:

void moveWindow();

protected:

void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
bool nativeEvent(const QByteArray & eventType, void * message, long * result);
void paintEvent(QPaintEvent *);

private:

bool isMax;
bool isPress;
QPoint startPos;
QPoint clickPos;
QWidget *m_pTitleWidget;//顶栏窗体
QWidget *m_pContentWidget;//内容窗体
QPixmap maxPixmap;
QPixmap restorePixmap;
QToolButton *m_pMaxButton;

};

#endif //!CUSTOMWIDGET_H_

customWidget.cpp:

#include "stdafx.h"
#include "customwidget.h"
#include <QtWidgets/QLabel>
#include <QtWidgets/QToolButton>
#include <QtWidgets/QHBoxLayout>
#include <QtCore/QEvent>
#include <Window.h>

static const int TITLE_HEIGHT = 40;//标题栏高度
static const int FRAME_BORDER = 2;//边框宽度
CustomWidget::CustomWidget()
: m_pContentWidget(0)
//, m_llLocalWinId(0)
//, m_llRemoteWinId(0)

{

this->setWindowFlags(Qt::FramelessWindowHint);
this->setAttribute(Qt::WA_TranslucentBackground);
this->setMouseTracking(true);

isMax = false;
isPress = false;
m_pTitleWidget = new QWidget();

}

CustomWidget::~CustomWidget()
{
}

void CustomWidget::setContentWidget(QWidget *contentWidget)
{

if (contentWidget)
{
    m_pContentWidget = contentWidget;
    m_pContentWidget->move(m_pTitleWidget->rect().bottomLeft());
    m_pContentWidget->show();
    resize(m_pTitleWidget->width(), m_pTitleWidget->height() + m_pContentWidget->height());
}

}

void CustomWidget::setTitleInfo(const QString &titleString, const QPixmap &windowIcon)
{

QLabel *logoLabel = new QLabel();
logoLabel->setPixmap(windowIcon);
logoLabel->setFixedSize(16, 16);
logoLabel->setScaledContents(true);

QLabel *titleLabel = new QLabel();
titleLabel->setText(titleString);
QFont titleFont = titleLabel->font();
titleFont.setBold(true);
titleLabel->setFont(titleFont);
titleLabel->setObjectName("whiteLabel");
titleLabel->setStyleSheet("color:white;");

QToolButton *minButton = new QToolButton();
connect(minButton, SIGNAL(clicked()), this, SLOT(slotShowSmall()));
m_pMaxButton = new QToolButton();
connect(m_pMaxButton, SIGNAL(clicked()), this, SLOT(slotShowMaxRestore()));
QToolButton *closeButton = new QToolButton();
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
connect(this, SIGNAL(moveWindow()), this, SLOT(onMoveWindow()));

QHBoxLayout *titleLayout = new QHBoxLayout();
titleLayout->addWidget(logoLabel);
titleLayout->addWidget(titleLabel);
titleLabel->setContentsMargins(5, 0, 0, 0);
titleLayout->addStretch();
titleLayout->addWidget(minButton, 0, Qt::AlignTop);
titleLayout->addWidget(m_pMaxButton, 0, Qt::AlignTop);
titleLayout->addWidget(closeButton, 0, Qt::AlignTop);
titleLayout->setSpacing(0);
titleLayout->setContentsMargins(5, 0, 0, 0);

m_pTitleWidget->setFixedSize(600, TITLE_HEIGHT);
m_pTitleWidget->setLayout(titleLayout);
m_pTitleWidget->installEventFilter(0);
m_pTitleWidget->setAutoFillBackground(true);
QPalette palette;
palette.setColor(QPalette::Background, QColor(31,25,25));
m_pTitleWidget->setPalette(palette);

}

void CustomWidget::slotShowSmall()//最小化
{
this->showMinimized();
}

void CustomWidget::slotShowMaxRestore()//还原按钮
{

if (isMax) {
    this->showNormal();
    m_pMaxButton->setIcon(maxPixmap);
}
else {
    this->showMaximized();
    m_pMaxButton->setIcon(restorePixmap);
}
isMax = !isMax;

}

void CustomWidget::onMoveWindow()
{
//m_pContentWidget->move(m_pTitleWidget->rect().bottomLeft());
}

void CustomWidget::mousePressEvent(QMouseEvent *e)
{

startPos = e->globalPos();
clickPos = e->pos();

if (e->button() == Qt::LeftButton) {
    if (e->type() == QEvent::MouseButtonPress) {
        isPress = true;
    }
    else if (e->type() == QEvent::MouseButtonDblClick && e->pos().y() <= TITLE_HEIGHT) {
        this->slotShowMaxRestore();
    }
}

}

void CustomWidget::mouseMoveEvent(QMouseEvent *e)
{

if (isMax || !isPress) {
    return;
}
this->move(e->globalPos() - clickPos);
emit moveWindow();

}

void CustomWidget::mouseReleaseEvent(QMouseEvent *)
{
isPress = false;
}

bool CustomWidget::nativeEvent(const QByteArray & eventType, void * message, long * result)//实现拖拽边框的效果
{

Q_UNUSED(eventType);
const int HIT_BORDER = 5;
const MSG *msg = static_cast<MSG*>(message);
if (msg->message == WM_NCHITTEST) {
    int xPos = ((int)(short)LOWORD(msg->lParam)) - this->frameGeometry().x();
    int yPos = ((int)(short)HIWORD(msg->lParam)) - this->frameGeometry().y();
    if (this->childAt(xPos, yPos) == 0) {
        *result = HTCAPTION;
    }
    else {
        return false;
    }
    if (xPos > 0 && xPos < HIT_BORDER) {
        *result = HTLEFT;
    }
    if (xPos >(this->width() - HIT_BORDER) && xPos < (this->width() - 0)) {
        *result = HTRIGHT;
    }
    if (yPos > 0 && yPos < HIT_BORDER) {
        *result = HTTOP;
    }
    if (yPos >(this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
        *result = HTBOTTOM;
    }
    if (xPos > 0 && xPos < HIT_BORDER && yPos > 0 && yPos < HIT_BORDER) {
        *result = HTTOPLEFT;
    }
    if (xPos >(this->width() - HIT_BORDER) && xPos < (this->width() - 0) && yPos > 0 && yPos < HIT_BORDER) {
        *result = HTTOPRIGHT;
    }
    if (xPos > 0 && xPos < HIT_BORDER && yPos >(this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
        *result = HTBOTTOMLEFT;
    }
    if (xPos >(this->width() - HIT_BORDER) && xPos < (this->width() - 0) && yPos >(this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
        *result = HTBOTTOMRIGHT;
    }
    return true;
}
return false;

}

void CustomWidget::paintEvent(QPaintEvent *e)
{//绘制边框

int border = FRAME_BORDER;
if (this->isMaximized()) {
    border = 0;
}

QPainter painter(this);
QPainterPath painterPath;
painterPath.setFillRule(Qt::WindingFill);
painterPath.addRect(border, border, this->width() - 2 * border, this->height() - 2 * border);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.fillPath(painterPath, QBrush(Qt::black));
QColor color(200, 200, 200);
for (int i = 0; i<border; i++) {
    color.setAlpha((i + 1) * 30);
    painter.setPen(color);
    painter.drawRect(border - i, border - i, this->width() - (border - i) * 2, this->height() - (border - i) * 2);
}

painter.setPen(Qt::NoPen);
painter.setBrush(Qt::black);
// 这里可以在资源中指定一张标题背景图片  
//painter.drawPixmap(QRect(border, border, this->width()-2*border, this->height()-2*border), QPixmap(DEFAULT_SKIN));  
painter.drawRect(QRect(border, TITLE_HEIGHT, this->width() - 2 * border, this->height() - TITLE_HEIGHT - border));
QFrame::paintEvent(e);

}
///全文完

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本课程详细、全面地介绍了 Qt 开发中的各个技术细节,并且额外赠送在嵌入式端编写Qt程序的技巧。整个课程涵盖知识点非常多,知识模块囊括 Qt-Core 组件、QWidgets、多媒体、网络、绘图、数据库,超过200个 C++ 类的分析和使用,学完之后将拥有 Qt 图形界面开发的非常坚实的功底。 每个知识点不仅仅会通过视频讲解清楚,并且会配以精心安排的实验和作业,用来保证学习过程中切实掌握核心技术和概念,通过实验来巩固,通过实验来检验,实验与作业的目的是发现问题,发现技术盲点,通过答疑和沟通夯实技术技能。注意:本套视频教程来源于线下的实体班级,因此视频中有少量场景对话和学生问答,对此比较介意的亲们谨慎购买。注意:本套视频教程包含大量课堂源码,包含对应每个知识点的精心编排的作业。由于CSDN官方规定在课程介绍中不能出现作者的联系方式,因此在这里无法直接给出QQ答疑号,视频中的源码、资料和作业文档链接统一在购买后从CSDN平台跟我沟通,我会及时回复跟进。注意:本套视频教程包含全套10套作业题,覆盖所有视频知识点,循序渐进,各个击破,作业总纲如下:下面是部分作业题目展示,每道题都有知识点说明,是检验学习效果的一大利器:(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)(部分作业展示,为了防止盗图盗题对题干做了模糊处理)…… ……

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值