使用QT 开发不规则窗体

news2025/6/22 7:32:31

使用QT 开发不规则窗体

  • 不规则窗体
  • 贴图法的不规则窗体
    • 创建UI模板
    • 创建一个父类
    • 创建业务窗体
    • main函数直接调用user_dialog
    • 创建QSS文件
  • 完整的QT工程

不规则窗体

QT中开发不规则窗体有两种方法:(1)第一种方法,使用QWidget::setMask函数设置绘制区域,然后在paintEvent()绘制。(2)第二种方法,在窗体四周设置一圈QWidget,设置一些不规则的图片,达到不规则窗体的目的。本次介绍贴图的这种方法。

贴图法的不规则窗体

创建UI模板

在QT中创建一个UI窗体。
在这里插入图片描述

在上下左右不同的区域设置QWidget:(1)上方:左上角,右上角,上方正中是标题栏;(2)下方:左下角,下方正中,右下角。(3)窗体两侧(4)窗体正中是业务窗体的窗体,业务窗体下方放置两按钮【确定】【取消】

运行效果图:

在这里插入图片描述

创建一个父类

创建一个父类,用于显示不规则窗体的四周,以后的窗体就不用重新作,直接继承就可以了。为了简捷,就不用cpp,把代码直接写到头文件里。

#ifndef CUSTOM_DIALOG_BASE_H
#define CUSTOM_DIALOG_BASE_H

#include <QDialog>
#include <QDesktopWidget> 
#include <QApplication>
#include <QMouseEvent> 
#include <QDebug> 
#include <QKeyEvent> 
#include "ui_custom_dialog_base.h"
class custom_dialog_base : public QDialog
{
    Q_OBJECT

public:
    explicit custom_dialog_base(QWidget *parent = 0)
    {
        setWindowFlags(windowFlags() | Qt::FramelessWindowHint|Qt::Dialog);//无边框
        this->setAttribute(Qt::WA_TranslucentBackground, true);//窗体背景全透明
        ui.setupUi(this);
        m_bMouseLeftButtonPressed = false;
        m_bCtrlKeyPressed = false;

        connect(ui.pushButton_close, &QPushButton::clicked, this, &QDialog::close);

        connect(ui.pushButton_ok, &QPushButton::clicked, this, &QDialog::accept);

        connect(ui.pushButton_cancel, &QPushButton::clicked, this, &QDialog::reject);

        ui.label_title->installEventFilter(this);

    }

    ~custom_dialog_base(){};

    // 居中在父窗体中
    void centerParent()
    {
        QWidget* parentWidget = this->parentWidget();
        QRect rect = this->geometry();
        QRect rectParent;
        if(parentWidget != nullptr)
        {
            rectParent = parentWidget->geometry();
        }
        else
        {
            rectParent = QApplication::desktop()->geometry();
        }
        QPoint center = rectParent.center();
        int width = rect.width();
        int height = rect.height();
        this->setGeometry(center.x()-width/2, center.y() - height/2, width, height);
    }

     // 设置标题
    void setDialogTitle(const QString& strTitle)
    {
        ui.label_title->setText(strTitle);
    }
    //获取中间的内容面板
    QWidget* getContainerWidget() { return ui.inner_frame;  }

protected:
    // ctrl键按下
    virtual void  keyPressEvent(QKeyEvent *event)
    {
        if (event->key() &Qt::Key_Control)
        {
            m_bCtrlKeyPressed = true;
            this->setSizeGripEnabled(true);// ctrl键按下,显示窗体缩放抓手。
        }
    }

    // ctrl键松开
    virtual void  keyReleaseEvent(QKeyEvent *event)
    {
        if (event->key() &Qt::Key_Control)
        {
            m_bCtrlKeyPressed = false;
            this->setSizeGripEnabled(false);
        }
    }

    // 窗体移动实现
    bool eventFilter(QObject *obj, QEvent *event)
    {
         // ctrl键按下时返回
        if (m_bCtrlKeyPressed)
        {
            return false;
        }

        // 判断是标题栏
        if (obj == ui.label_title)
        {
            //鼠标左键按下
            if (event->type() == QEvent::MouseButtonPress)
            {
                m_bMouseLeftButtonPressed = true;
                m_pointMouseLeftButtonPressed = QCursor::pos();
                return true;
            }
            else if (event->type() == QEvent::MouseButtonRelease)
            {//鼠标左键松开
                m_bMouseLeftButtonPressed = false;
                return true;
            }
            else if (event->type() == QEvent::MouseMove && m_bMouseLeftButtonPressed)
            {//鼠标左键按下时移动鼠标,开始移动窗体
                QPoint offset = QCursor::pos() - m_pointMouseLeftButtonPressed;
                QPoint pos = this->pos();
                this->move(offset + pos);
                m_pointMouseLeftButtonPressed = QCursor::pos();
                return true;
            }
        }

        return false;
    }

private:
    Ui_custom_dialog_base ui;

    //鼠标是否按下
    bool m_bMouseLeftButtonPressed;

    //cltr键是否按下
    bool m_bCtrlKeyPressed;

    //按下后当前鼠标位置
    QPoint m_pointMouseLeftButtonPressed;
};
// 可以pro文件中加入custom_dialog_base.h,不要下句
#include "./moc/moc_custom_dialog_base.cpp"

#endif // CUSTOM_DIALOG_BASE_H

创建业务窗体

业务窗体直接继承custom_dialog_base 类。同样,把cpp省去。把代码直接写到头文件里。

#ifndef USER_DIALOG_H
#define USER_DIALOG_H

#include <QDialog>
#include <QDesktopWidget> 
#include <QApplication>
#include <QMouseEvent> 
#include <QDebug> 
#include <QKeyEvent> 
#include "ui_user_dialog.h"
#include "custom_dialog_base.h"

class user_dialog : public custom_dialog_base
{
    Q_OBJECT

public:
    explicit user_dialog(QWidget *parent = 0)
    {
        ui.setupUi(getContainerWidget());// 加载业务窗体,
        getContainerWidget()->setLayout(ui.formLayout_2);// 设置业务窗体的布局器到父类中的容器中。
        ui.formLayout_2->setSpacing(15);
    }

    ~user_dialog(){};

private:
    Ui_user_dialog ui;
};

// 可以在pro文件中加入user_dialog.h,不要下句
#include "./moc/moc_user_dialog.cpp"
#endif // USER_DIALOG_H

main函数直接调用user_dialog

在main里直接创建user_dialog的实例,显示不规则窗体。

#include <QApplication>
#include <QDir>
#include <QPushButton>
#include "user_dialog.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
	QFile file;
    QString strFile = QDir(QApplication::applicationDirPath()).canonicalPath() + "/ui.qss";
	file.setFileName(strFile);
	file.open(QFile::ReadOnly);
	file.seek(0);
    QString strQss= file.readAll();// 从ui.qss文件中读取样式
    a.setStyleSheet(strQss); // 设置样式
	user_dialog dlg;
    dlg.setDialogTitle(QString::fromLocal8Bit("窗体标题"));
    dlg.centerParent();// 居中父窗体。
    return dlg.exec();
}

创建QSS文件

把使用自己喜欢的图片放到资源文件中,供QSS文件使用。

qss文件:


QWidget#widget_topleft{
	background-color:transparent;
	border-image:url(:/resources/top_left.png);
}

QWidget#widget_topcenter{
	background-color:transparent;
	border-image:url(:/resources/top_center.png);
}

QWidget#widget_topright{
	background-color:transparent;
	border-image:url(:/resources/top_right.png);
}


QWidget#widget_bottomleft{
	background-color:transparent;
	border-image:url(:/resources/bottom_left.png);
}

QWidget#widget_bottom_center{
	background-color:transparent;
	border-image:url(:/resources/bottom_center.png);
}


QWidget#widget_bottomright{
	background-color:transparent;
	border-image:url(:/resources/bottom_right.png);
}



QWidget#widget_left{
	background-color:transparent;
	border-image:url(:/resources/left_center.png);
}

QWidget#widget_center{
	background-color:transparent;
	border-image:url(:/resources/center.png);
}


QWidget#widget_right{
	background-color:transparent;
	border-image:url(:/resources/right_center.png);
}

QPushButton#pushButton_close{
	background-color: transparent;
	background-image:url(:/resources/pushButton_close.png);
}

QLabel{
	font-size:16px;
	color:white;
}
QLabel#label_title{
	background-color: transparent;
    text-align: center;
	font-size:18px;
	color:white;
}


QLineEdit, QComboBox,QDateTimeEdit,QSpinBox {
	font-size:18px;
}

QSizeGrip {
      image: url(:/resources/resize_gripper.png);
      width: 32px;
      height: 32px;
  }

QPushButton#pushButton_ok,QPushButton#pushButton_cancel {
	background-color: transparent;
	border-image:url(:/resources/pushbutton.png);
	min-width:96px;
	min-height:32px;
}


QPushButton#pushButton_ok:pressed,QPushButton#pushButton_cancel:pressed {
	background-color: transparent;
	border-image:url(:/resources/pushbutton_pressed.png);
}


QPushButton#pushButton_ok:hover,QPushButton#pushButton_cancel:hover {
	background-color: transparent;
	border-image:url(:/resources/pushbutton_hover.png);
}

qrc文件:

<RCC>
    <qresource prefix="/">
        <file>./resources/top_left.png</file>
        <file>./resources/top_center.png</file>
        <file>./resources/top_right.png</file>
        <file>./resources/left_center.png</file>
        <file>./resources/center.png</file>
        <file>./resources/right_center.png</file>
        <file>./resources/bottom_left.png</file>
        <file>./resources/bottom_center.png</file>
        <file>./resources/bottom_right.png</file>
        <file>./resources/pushButton_close.png</file>
        <file>./resources/resize_gripper.png</file>
        <file>./resources/pushbutton.png</file>
        <file>./resources/pushbutton_pressed.png</file>
        <file>./resources/pushbutton_hover.png</file>
    </qresource>
</RCC>

完整的QT工程

工程文件下载,不完善之处,老铁们一块讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1584750.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS伪元素::after清除浮动样式

一.代码 1.清除前 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </h…

Vue3学习01 Vue3核心语法

Vue3学习 1. Vue3新的特性 2. 创建Vue3工程2.1 基于 vue-cli 创建项目文件说明 2.2 基于 vite 创建具体操作项目文件说明 2.3 简单案例(vite) 3. Vue3核心语法3.1 OptionsAPI 与 CompositionAPIOptions API 弊端Composition API 优势 ⭐3.2 setup小案例setup返回值setup 与 Opt…

[计算机效率] 看图工具:Honeyview

3.23 看图工具&#xff1a;Honeyview Honeyview是一款轻量级、快速且功能强大的图片浏览器&#xff0c;具有多种强大的功能和特点。 多种图像格式支持&#xff1a;Honeyview支持几乎所有常见的图像格式&#xff0c;包括JPG、PNG、BMP、GIF等&#xff0c;甚至包括一些不常见的格…

搭建NFS服务器,部署k8s集群,并在k8s中使用NFS作为持久化储存

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Kubernetes航线图&#xff1a;从船长到K8s掌舵者》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、k8s概述 2、NFS简介 二、NFS服务器…

机器学习和深度学习-- 李宏毅(笔记与个人理解)Day8

Day 8 classification &#xff1a;Probabilistic Generative Model 今天上了一整天的课&#xff0c; 本来实在是更新不动了&#xff0c;但是看到《剑来》更新了&#xff0c;想一想这本书里面一直强调的成功的feature – 心性&#xff0c;嗯心性坚毅就好&#xff01;主人公陈平…

日程安排组件DHTMLX Scheduler v7.0新版亮点 - 拥有多种全新的主题

DHTMLX Scheduler是一个类似于Google日历的JavaScript日程安排控件&#xff0c;日历事件通过Ajax动态加载&#xff0c;支持通过拖放功能调整事件日期和时间&#xff0c;事件可以按天、周、月三个种视图显示。 备受关注的DHTMLX Scheduler 7.0版本日前正式发布了&#xff0c;如…

使用ROCm的HIP API向量加法程序

一、向量加法程序 Radeon Open Compute (ROCm) 是一个开源平台&#xff0c;用于加速高性能计算 (HPC) 和机器学习应用程序。它支持包括GPUs在内的多种硬件&#xff0c;并提供HIP (Heterogeneous-compute Interface for Portability) 作为CUDA代码的便捷转换工具。为了提供一个…

BPMN.JS中文教程学习

基础篇 vue bpmn.js 建模BpmnModeler将数据转图形bpmnModeler.importXML // basic.vue<script>// 引入相关的依赖import BpmnModeler from bpmn-js/lib/Modelerimport {xmlStr} from ../mock/xmlStr // 这里是直接引用了xml字符串export default {name: ,components: {…

使用 Docker 部署 Open-Resume 在线简历平台

1&#xff09;Open-Resume 介绍 GitHub&#xff1a; https://github.com/xitanggg/open-resume Open-Resume 是一款功能强大的开源 简历生成器 和 简历解析器 。可以帮助我们快速的生成个人简历&#xff0c;并定制化不同的主题和布局风格。该项目的目标是为每个人提供免费的现…

Qt5 编译 Qt Creator 源码中的 linguist 模块

文章目录 下载 Qt Creator 源码手动翻译多语言自动翻译多语言 下载 Qt Creator 源码 Github: https://github.com/qt/qttools 笔记打算用 Qt 5.12.12 来编译 qt creator-linguist 所以笔者下载的是 tag - 5.12.12 &#xff0c;解压后如下&#xff0c;先删除多余的文件&#xf…

视觉SLAM学习打卡【10】-后端·滑动窗口法位姿图

本节是对上一节BA的进一步简化&#xff0c;旨在提高优化实时性.难点在于位姿图部分的雅可比矩阵求解&#xff08;涉及李代数扰动模型求导&#xff09;&#xff0c;书中的相关推导存在跳步&#xff08;可能数学功底强的人认为过渡的理所当然&#xff09;&#xff0c;笔者参考了知…

B站广告推广操作教程及费用?

哔哩哔哩&#xff08;B站&#xff09;作为国内极具影响力的年轻人文化社区&#xff0c;已成为众多品牌与企业触达目标受众、提升品牌影响力的重要阵地。然而&#xff0c;面对B站复杂的广告系统与精细化运营需求&#xff0c;许多广告主可能对如何高效开展B站广告推广感到困惑。云…

2024年同城网总流量全新生态,个人工作室落地式游戏玩法,单账户月入3万

我要为大家解读的是本地生活新项目&#xff0c;这个业务模式中&#xff0c;即使是低收入的玩法&#xff0c;一个月赚取万儿八千也是完全可行的。而高收入的玩法&#xff0c;一单的收入甚至能超过一万。目前&#xff0c;你的圈子里已经有一些同行业的人开始以个人工作室的形式去…

stm32开发之threadx+netxduo(结合 modbus 编写tcp接口程序)

前言 本篇结合freemodbus源码程序进行移植,驱动实现的接口为modbus tcp需要知道threadx的 事件标志组、信号量、线程相关的知识需要知道netxduo tcp方面的api和创建流程方面的知识 freemodbus程序源码 本次使用的源码来自于rt-thread软件包里面的&#xff0c;可以参考之前的…

linux查看网络连接数

目录 netstat top netstat 1.netstat查看当前主机上网络连接信息&#xff0c;端口号&#xff0c;pid,程序名等等 #直接查看 netstat -anp #一般使用的时候&#xff0c;可能要筛选 #比如8080端口是否被占用 netstat -anp | grep 8080 #minio服务占用了那些端口 netstat -anp …

掌握判断IPv4地址是否正确的方法

在数字通信和互联网领域中&#xff0c;IPv4地址作为标识网络设备的核心元素&#xff0c;其正确性至关重要。一个有效的IPv4地址能够确保设备在网络中的正常通信和交互&#xff0c;而错误的IPv4地址则可能导致连接失败、通信中断甚至网络安全问题。因此&#xff0c;掌握判断IPv4…

【docker】之linux写shell脚本备份线上数据库(备份为dump文件)

目录 1. SH文件1.1 SH文件示例1.2 文件解释1.3 .sh文件执行 2. 备份线上数据库的.sh文件2.1 文件命令解析 3. 命令执行4. 线下dump文件的恢复与备份 环境&#xff1a;linux容器&#xff1a;docker 1. SH文件 SH文件通常指的是 Shell 脚本文件&#xff0c;文件后缀名为.sh&…

Spring Boot统一功能处理(一)

本篇主要介绍Spring Boot的统一功能处理中的拦截器。 目录 一、拦截器的基本使用 二、拦截器实操 三、浅尝源码 初始化DispatcherServerlet 处理请求&#xff08;doDispatch) 四、适配器模式 一、拦截器的基本使用 在一般的学校或者社区门口&#xff0c;通常会安排几个…

【C++学习】C++11新特性(第一节)

文章目录 ♫一.文章前言♫二.C11新特性♫一.统一的列表初始化♫二.std::initializer_list♫三.声明♫四.decltype关键字♫五.nullptr♫六.新增加容器---静态数组array、forward_list以及unordered系列♫6.1unordered_map与unoredered_set♫6.2array♫6.3 forward_list&#xff…

Leetcode算法训练日记 | day18

一、找树左下角的值 1.题目 Leetcode&#xff1a;第 513 题 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1示例 2: 输入: [1,2,3,4,null,5,6,null,null,7] 输出:…