qt中的QWidget窗口支持窗体绘制,但是不支持窗口标题栏绘制,想要美观的界面,还需要自己去定制,下面我就介绍一种定制窗体的方法

一个窗口无非就3部分,标题栏、窗体和状态栏,接下来我定制的窗口没有状态栏,如果自己想加状态栏的话,照着这个模式自己也可以添加,说白了,窗口定制就是把完整的窗口分3部分定制,而每个部分又都是一个qt窗口

定制窗口效果图如下,根据个人喜好,自己也可以定制不同的效果

图1 定制窗口

如图1所示,这个窗口包含两部分,标题栏和窗体,这两部分其实分别是一个没有标题栏的QWidget,接下来我分别介绍下这两部分

标题栏

构造函数代码如下​

 setAutoFillBackground(true);//自动填充背景色,防止继承父窗口背景色

 setStyleSheet(QStringLiteral("background:blue;"));//背景色

 ​setFixedHeight();//设置高度 看个人喜好 可以做微调​

 _p->minimize = new QToolButton(this);

 _p->maximize = new QToolButton(this);

 _p->close = new QToolButton(this);

/// 设置系统按钮图标.

 QPixmap pix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton);

 _p->close->setIcon(pix);

 _p->maxPix = style()->standardPixmap(QStyle::SP_TitleBarMaxButton);

 _p->maximize->setIcon(_p->maxPix);

 pix = style()->standardPixmap(QStyle::SP_TitleBarMinButton);

 _p->minimize->setIcon(pix);

 _p->restorePix = style()->standardPixmap(QStyle::SP_TitleBarNormalButton);

 _p->minimize->setMinimumHeight();

 _p->close->setMinimumHeight();

 _p->maximize->setMinimumHeight();

 _p->label = new QLabel(this);

 _p->label->setAttribute(Qt::WA_TransparentForMouseEvents, true); //鼠标穿透

 _p->label->setStyleSheet(QStringLiteral("  font-size:12px;\

     font - weight:Bold"));

     _p->label->setMargin();

 SetWindowTitle("title");

 QHBoxLayout *hbox = new QHBoxLayout;

 hbox->addWidget(_p->label);

 hbox->addWidget(_p->minimize);

 hbox->addWidget(_p->maximize);

 hbox->addWidget(_p->close);

 //_p->maximize->setVisible(false);

 hbox->insertStretch(, );

 hbox->setSpacing();

 connect(_p->minimize, &QToolButton::clicked, this, [this]{

     BaseWidget * widget = qobject_cast(parent());

     if (widget)

     {

         widget->SetWindowMovePos(widget->pos());

         emit WindowDockedSignal();

     }

 });

 connect(_p->maximize, &QToolButton::clicked, this, &TitleBar::showMaxRestore);

 connect(_p->close, &QToolButton::clicked, this, [this]{emit WindowCloseSignal(_p->label->text()); });

 hbox->setMargin();

 hbox->setSpacing();

 setLayout(hbox);

 ​void TitleBar::showMaxRestore()//最大化或者还原

 {

     if (_p->maxNormal)

     {

         _p->maxNormal = !_p->maxNormal;

         _p->maximize->setIcon(_p->maxPix);

     }

     else

     {

         _p->maxNormal = !_p->maxNormal;

         _p->maximize->setIcon(_p->restorePix);

     }

     emit WindowMaxRestoreSignal(_p->maxNormal);

 }

 void TitleBar::SetWindowTitle(const QString & title)//设置窗口标题

 {

     if (_p)

     {

         _p->label->setText(title);

     }

 }

 void TitleBar::SetWindowMaxable(bool isMax)

 {

     if (_p)

     {

         _p->maxNormal = isMax;

         if (_p->maxNormal)

         {

             _p->maximize->setIcon(_p->maxPix);

         }

         else

         {

             _p->maximize->setIcon(_p->restorePix);

         }

     }

 }

 void TitleBar::mousePressEvent(QMouseEvent * event)//移动窗口

 {

     QPoint mousePos = _p->minimize->mapFromParent(event->pos());

     if (_p->minimize->rect().contains(mousePos))//如果点击了最小化 则不能移动

     {

         return;

     }

     if (_p->maximize->rect().contains(mousePos))//如果点击了最大化不能移动

     {

         return;

     }

     _p->leftButtonPressed = true;

     _p->startPos = event->globalPos();

     _p->clickPos = mapToParent(event->pos());

 }

 void TitleBar::mouseReleaseEvent(QMouseEvent * event)

 {

     _p->leftButtonPressed = false;

 }

 void TitleBar::mouseMoveEvent(QMouseEvent * event)

 {

     if (_p->maxNormal)

     {

         return;

     }

     if (_p->leftButtonPressed)

     {

         parentWidget()->move(event->globalPos() - _p->clickPos);//移动父窗口

     }

 }

 void TitleBar::mouseDoubleClickEvent(QMouseEvent * event)

 {

     showMaxRestore();

 }

窗体定制

直接上代码

​   cpp如下​

 setFrameShape(Panel);

 setMouseTracking(true);

 setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Tool);/// 隐藏窗口标题栏.

 setFixedSize(, );

 _p->m_mouse_down = false;

 _p->m_titleBar = new TitleBar(this);

 _p->m_titleBar->installEventFilter(this);

 connect(_p->m_titleBar, &TitleBar::WindowDockedSignal

 , this, [this]{

 setFixedSize(_p->m_content->size());

 setMinimumSize(, );

 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);

 _p->m_titleBar->setVisible(false);

 });

 connect(_p->m_titleBar, &TitleBar::WindowMaxRestoreSignal

 , this, [this](bool isMax){

 if (isMax)

 {

 showMaximized();

 }

 else

 {

 showNormal();

 }

 });

 _p->m_content = new QWidget(this);

 QPalette plt = _p->m_content->palette();

 plt.setColor(QPalette::Window, QColor("#000000"));

 _p->m_content->setPalette(plt);//设置背景色黑色

 _p->m_content->setAutoFillBackground(true);

 _p->m_content->setAttribute(Qt::WA_PaintOnScreen, true);

 QVBoxLayout *vbox = new QVBoxLayout(this);

 vbox->addWidget(_p->m_titleBar);

 vbox->setStretchFactor(_p->m_titleBar, );

 vbox->setMargin();

 vbox->setSpacing();

 QVBoxLayout *layout = new QVBoxLayout(this);

 layout->addWidget(_p->m_content);

 layout->setMargin();

 layout->setSpacing();

 vbox->addLayout(layout);

 vbox->setStretchFactor(layout, );

 TitleBar * BaseWidget::GetTitleBar() const

 {

          if (_p)

          {

               return _p->m_titleBar;

           }

 }

 QWidget * BaseWidget::GetContentWidget() const

 {

      if (_p)

       {

             return _p->m_content;

        }

 }

 BaseWidget::State BaseWidget::GetWindowState() const

 {

     if (_p)

     {

           return _p->state;

      } 

 }

 void BaseWidget::SetWindowState(BaseWidget::State state)

 {

      if (_p)

       {

              _p->state = state;

              if (_p->state == _floating)

              {

                   _p->m_titleBar->setVisible(true);

                }

                else

               {

                      _p->m_titleBar->setVisible(false);

                }

        }

 }

 QPoint BaseWidget::GetWindowFloatPos() const

 {

     if (_p)

     {

           return _p->floatPostion;

     }  

 }

 void BaseWidget::SetWindowFloatPos(const QPoint & point)

 {

      if (_p)

      {

            _p->floatPostion = point;

      }

 }

 QPoint BaseWidget::GetWindowMovePos() const

 {

     if (_p)

     {

     return _p->m_restorePos;

     }

 }

 void BaseWidget::SetWindowMovePos(const QPoint & pos)

 {

     if (_p)

     {

           _p->m_restorePos = pos;

      }

 }

 bool BaseWidget::eventFilter(QObject * object, QEvent * event)

 {

 if (object == _p->m_titleBar)

 {

      if (event->type() == QEvent::MouseMove)

      {

         QMouseEvent * mouseEvent = static_cast(event);

         if (mouseEvent && mouseEvent->button() & Qt::LeftButton)

          {

                 return true;//不做处理

             }

         }

     }

      return QWidget::eventFilter(object, event);

 }

 void BaseWidget::mousePressEvent(QMouseEvent * event)

 {

      if (event->button() == Qt::LeftButton)

      {

         _p->m_mouse_down = true;

          _p->dragPostion = event->globalPos() - frameGeometry().topLeft();

          event->accept();

      }

 }

 void BaseWidget::mouseMoveEvent(QMouseEvent * event)

 {

     if (_p->state != _floating || isMaximized())//如果窗口不是悬浮状态 或者最大化 不允许拖动

     {

          return;

     }

     if (_p->m_mouse_down)

     {

         move(event->globalPos() - _p->dragPostion);

         event->accept();

     }

 }

 void BaseWidget::mouseReleaseEvent(QMouseEvent * event)

 {

     _p->m_mouse_down = false; 

 }

 void BaseWidget::mouseDoubleClickEvent(QMouseEvent * event)

 {

  if (_p->state == _dock)

  {

          _p->state = _floating;

          _p->m_titleBar->setVisible(true);

          setParent(nullptr);

          setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint |      Qt::Tool);

          move(GetWindowMovePos());

         show();

     }

 }

​    有如上两部分代码,功能基本可以实现

Qt窗口定制的更多相关文章

  1. 自定义QT窗口部件外观之QStyle

    自定义QT窗口部件外观 重新定义Qt内置窗口部件的外观常用的方法有两种:一是通过子类化QStyle 类或者预定义的一个样式,例如QWindowStyle,来定制应用程序的观感:二是使用Qt样式表. Q ...

  2. 利用Qt Assistant 定制帮助文档

    为了将Qt Assistant定制为自己应用程序的帮助文档浏览器.需要完成以下几步: 一.导入HTML格式的帮助文档 (1)首先,针对自己的应用程序创建HTML格式的帮助文档,请参见<Doxyg ...

  3. CentOS下Qt窗口透明效果失效,成黑色背景的问题

    一.问题 Linux系统下Qt窗口的透明效果成了黑色,但同样的代码在windows机子上有透明效果,主要是修改系统的配置,仅在centos6.3及其以上版本实验过.其他系统可以相应配置. 二.问题运行 ...

  4. 深度探索QT窗口系统(五篇)

    窗口作为界面编程中最重要的部分,没有窗口就没有界面,是窗口让我们摆脱了DOS时代,按钮是一个窗口,文本框是一个窗口,标签页是一个窗口,...一个窗口可以由多个窗口组成,每天我们都在与窗口打交道,当你打 ...

  5. 调色板类QPalette——包含了Qt窗口不见的颜色组(collor group),和Windows右键属性外观非常类似

    QPalette类包含了Qt窗口不见的颜色组(collor group); 1.Active组,该组的颜色用户当前活动的(active)窗口,即具有键盘或鼠标焦点的窗口; 2.Inactive组,该组 ...

  6. QT窗口置顶/真透明/背景模糊/非矩形/跳过任务栏分页器/无边框/无焦点点击/焦点穿透

    qt 窗口置顶/真透明/背景模糊/非矩形/跳过任务栏分页器/无边框/无焦点点击/焦点穿透 窗口置顶qt 里是 setWindowFlags(Qt::WindowStaysOnTopHint)kde 里 ...

  7. Qt窗口操作函数(最大化,全屏,隐藏最大化,最小化)

    Qt窗口中的一些小技术总结 //Qt主窗口没有最小化,最大化按钮且最大化显示  int main(int argc, char *argv[]) { QApplication a(argc, argv ...

  8. 初识Qt窗口界面

    1.新建一个新的Qt Gui应用,项目名称随意,例如MyMainWindow,基类选择QMainWindow,类名为MainWindow. 2.项目建立后,双击mainwindow.ui文件,在界面的 ...

  9. qt 窗口控件自动调整大小

    /******************************************************************** * qt 窗口控件自动调整大小 * * 在写gui的时候,希 ...

随机推荐

  1. python默认参数陷阱

    对于学习python的人都有这样的困惑 def foo(a=[]): a.append(5) return a Python新手希望这个函数总是返回一个只包含一个元素的列表:[5].结果却非常不同,而 ...

  2. redis对hash进行的相关操作

    redis对hash类型操作的相关命令以及如何在python使用这些命令 redis对hash类型操作的命令: 命令 语法 概述 返回值 Redis Hdel 命令 hdel key field [f ...

  3. Linux-信号量与P,V操作

    Linux-信号量与P,V操作 内容 使用信号量实现进程互斥 使用信号量及PV实现子进程读写同步 机理 Linux信号量集 Linux信号量作为IPC机制的一种,与其他通信方式类似,Linux也是通过 ...

  4. <算法图解>读书笔记:第1章 算法简介

    阅读书籍:[美]Aditya Bhargava◎著 袁国忠◎译.人民邮电出版社.<算法图解> 第1章 算法简介 1.2 二分查找 一般而言,对于包含n个元素的列表,用二分查找最多需要\(l ...

  5. That girl

    音标 词汇 Purple Glasses Black Hat Brown Bag Clothes Blue Jacket Pink Handbag Sock White Skirt Shoe 1, s ...

  6. Android滑动列表(拖拽,左滑删除,右滑完成)功能实现(1)

    场景: 近期做的TODO APP需要在主页添加一个功能,就是可以左滑删除,右滑完成.看了一下当前其他人做的例如仿探探式的效果,核心功能基本一样,但是和我预想的还是有少量区别,于是干脆自己重头学一遍如何 ...

  7. DRAM的原理设计

    在一个电子系统中,CPU.内存.物理存储.IO这些单元必不可少,只不过有的集成在CPU内部,有的分离出来. 这里就针对系统中的内存,此处选用DRAM来进行说明,讲述下基本的原理设计,主要分为以下几个部 ...

  8. 快速幂 ,快速幂优化,矩形快速幂(java)

    快速幂形式 public static int f(int a,int b,int c){ int ans =1; int base=a; while(b!=0){ if((b&1)!=0) ...

  9. 大数据框架对比:Hadoop、Storm、Samza、Spark和Flink

    转自:https://www.cnblogs.com/reed/p/7730329.html 今天看到一篇讲得比较清晰的框架对比,这几个框架的选择对于初学分布式运算的人来说确实有点迷茫,相信看完这篇文 ...

  10. SpringBoot报错:The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone

    解决方法: 在数据库连接url配置后边加&serverTimezone=GMT%2B8 例: jdbc:mysql://127.0.0.1:3306/test改为jdbc:mysql://12 ...