【二十七】【QT开发应用】VS如何复制项目,QT无边窗窗口Pro版本,信号与信号槽的应用,背景图片自适应控件大小

news2024/11/17 6:34:54

VS复制项目

在使用VS的过程中,有的时候我们需要复制我们已经存在的项目.

在这里插入图片描述
我们可以先创建一个新的项目.
在这里插入图片描述

接着把需要复制的项目的文件复制粘贴到新的项目文件夹中.

在这里插入图片描述
不要忘记添加现有项目.

CFrameLessWidgetBase.h

#pragma once
#include <QWidget>
class CFrameLessWidgetBase : public QWidget{
	QOBJECT_H

public:
	CFrameLessWidgetBase(QWidget* p = nullptr);
	~CFrameLessWidgetBase();
private:

protected:
	bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;

private:
	int m_nBorderWidth = 10;
};


CFrameLessWidgetBase.cpp

#include "CFrameLessWidgetBase.h"
#include <qt_windows.h>
#include <windows.h>
#include <windowsx.h>

#pragma comment(lib, "user32.lib")
#pragma comment(lib,"dwmapi.lib")

CFrameLessWidgetBase::CFrameLessWidgetBase(QWidget* p)
	:QWidget(p) {
	this->setWindowFlags(Qt::FramelessWindowHint);
}
CFrameLessWidgetBase:: ~CFrameLessWidgetBase() {};

bool CFrameLessWidgetBase::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) {
	MSG* param = static_cast<MSG*>(message);

	switch (param->message) {
	case WM_NCHITTEST:
	{

		/*int nX = GET_X_LPARAM(param->lParam) - this->geometry().x();
		int nY = GET_Y_LPARAM(param->lParam) - this->geometry().y();*/

		QPoint globalPos = QCursor::pos(); // 获取鼠标的全局坐标
		QPoint localPos = this->mapFromGlobal(globalPos); // 转换为窗口坐标
		int nX = localPos.x(); // 现在的 nX 应该是相对于窗口的坐标
		int nY = localPos.y();

		//if (childAt(nX, nY) != nullptr)
		//	return QWidget::nativeEvent(eventType, message, result);



		if (nX > m_nBorderWidth && nX < this->width() - m_nBorderWidth &&
			nY > m_nBorderWidth && nY < this->height() - m_nBorderWidth) {
			if (childAt(nX, nY) != nullptr)
				return QWidget::nativeEvent(eventType, message, result);
		}

		if ((nX > 0) && (nX < m_nBorderWidth))
			*result = HTLEFT;

		if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()))
			*result = HTRIGHT;

		if ((nY > 0) && (nY < m_nBorderWidth))
			*result = HTTOP;

		if ((nY > this->height() - m_nBorderWidth) && (nY < this->height()))
			*result = HTBOTTOM;

		if ((nX > 0) && (nX < m_nBorderWidth) && (nY > 0)
			&& (nY < m_nBorderWidth))
			*result = HTTOPLEFT;

		if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
			&& (nY > 0) && (nY < m_nBorderWidth))
			*result = HTTOPRIGHT;

		if ((nX > 0) && (nX < m_nBorderWidth)
			&& (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
			*result = HTBOTTOMLEFT;

		if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
			&& (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
			*result = HTBOTTOMRIGHT;

		return true;



	}
	}

	return false;
}

将相关的代码放到一个类里面.
在这里插入图片描述
在这里插入图片描述
将主widget继承这个类.

CTitleBar.h

#pragma once
#include <QWidget>
#include <QLabel>
#include <QPushButton>
class CTitleBar : public QWidget 
{
	Q_OBJECT

public:
	CTitleBar(QWidget* p = nullptr);
	~CTitleBar();

private:
	void initUI();

private:
	void mousePressEvent(QMouseEvent* event) override;
	void mouseDoubleClickEvent(QMouseEvent* event) override;

private slots:
	void onClicked();

signals:
	void sig_close();

private:
	QLabel* Label_mpLogo;
	QLabel* Label_mpTitleText;

	QPushButton* Btn_mpSet;
	QPushButton* Btn_mpMin;
	QPushButton* Btn_mpMax;
	QPushButton* Btn_mpClose;

};


void mouseDoubleClickEvent(QMouseEvent* event) override;鼠标双击事件.
private slots: void onClicked();自定义槽函数.
signals: void sig_close();自定义信号.

CTitleBar.cpp

#include "CTitleBar.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <qt_windows.h>
#include <QPushButton>

CTitleBar::CTitleBar(QWidget* p)
	:QWidget(p) {
	initUI();
}

CTitleBar::~CTitleBar() {}

void CTitleBar::initUI() {
	setAttribute(Qt::WA_StyledBackground);
	this->setStyleSheet("background-color:rgb(156,156,156)");
	this->setFixedHeight(32);

	Label_mpLogo = new QLabel(this);
	Label_mpTitleText = new QLabel(this);
	Btn_mpSet = new QPushButton(this);
	Btn_mpMin = new QPushButton(this);
	Btn_mpMax = new QPushButton(this);
	Btn_mpClose = new QPushButton(this);

	Label_mpLogo->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/title_icon.png);");
	Btn_mpSet->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/set.svg);");
	Btn_mpMin->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/min.svg);");
	Btn_mpMax->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/normal.svg);");
	Btn_mpClose->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/close.svg);");





	Label_mpLogo->setFixedSize(24, 24);
	Label_mpTitleText->setText("我是标题");
	Label_mpTitleText->setFixedWidth(120);
	Btn_mpSet->setFixedSize(24, 24);
	Btn_mpMin->setFixedSize(24, 24);
	Btn_mpMax->setFixedSize(24, 24);
	Btn_mpClose->setFixedSize(24, 24);

	QHBoxLayout* Layout_pHTitle = new QHBoxLayout(this);
	Layout_pHTitle->addWidget(Label_mpLogo);
	Layout_pHTitle->addWidget(Label_mpTitleText);
	Layout_pHTitle->addStretch();
	Layout_pHTitle->addWidget(Btn_mpSet);
	Layout_pHTitle->addWidget(Btn_mpMin);
	Layout_pHTitle->addWidget(Btn_mpMax);
	Layout_pHTitle->addWidget(Btn_mpClose);

	Layout_pHTitle->setContentsMargins(5, 5, 5, 5);









	connect(Btn_mpSet, &QPushButton::clicked, this, &CTitleBar::onClicked);
	connect(Btn_mpMin, &QPushButton::clicked, this, &CTitleBar::onClicked);
	connect(Btn_mpMax, &QPushButton::clicked, this, &CTitleBar::onClicked);
	connect(Btn_mpClose, &QPushButton::clicked, this, &CTitleBar::onClicked);
}

void CTitleBar::mousePressEvent(QMouseEvent* event) {
	//实现窗口可拖拽
	if (ReleaseCapture()) {
		QWidget* pWindow = this->window();
		if (pWindow->isTopLevel()) {
			SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
		}
	}
}

void CTitleBar::mouseDoubleClickEvent(QMouseEvent* event) {
	Btn_mpMax->click();
}

void CTitleBar::onClicked() {
	QPushButton* btn_ptemp = qobject_cast<QPushButton*>(sender());

	QWidget* widget_window = this->window();

	if (btn_ptemp == Btn_mpMin) {
		widget_window->showMinimized();
	} else if (btn_ptemp == Btn_mpMax) {
		if (widget_window->isMaximized()) {
			widget_window->showNormal();
		} else {
			widget_window->showMaximized();
		}

	} else if (btn_ptemp == Btn_mpClose) {
		emit sig_close();
	}

}



图片自适应控件

	Label_mpLogo->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/title_icon.png);");
	Btn_mpSet->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/set.svg);");
	Btn_mpMin->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/min.svg);");
	Btn_mpMax->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/normal.svg);");
	Btn_mpClose->setStyleSheet("border-image:url(:/MainWidget/resources/titlebar/close.svg);");

使用border-image:这个属性可以让你设置控件的边框图像,并且可以在控件大小变化时保持图像的比例和位置。

信号槽连接

	connect(Btn_mpSet, &QPushButton::clicked, this, &CTitleBar::onClicked);
	connect(Btn_mpMin, &QPushButton::clicked, this, &CTitleBar::onClicked);
	connect(Btn_mpMax, &QPushButton::clicked, this, &CTitleBar::onClicked);
	connect(Btn_mpClose, &QPushButton::clicked, this, &CTitleBar::onClicked);

这四个按钮的点击信号全部链接相同的函数.在这一个函数中我们需要怎样区分信号的来源?

区分信号来源

void CTitleBar::onClicked() {
	QPushButton* btn_ptemp = qobject_cast<QPushButton*>(sender());

	QWidget* widget_window = this->window();

	if (btn_ptemp == Btn_mpMin) {
		widget_window->showMinimized();
	} else if (btn_ptemp == Btn_mpMax) {
		if (widget_window->isMaximized()) {
			widget_window->showNormal();
		} else {
			widget_window->showMaximized();
		}

	} else if (btn_ptemp == Btn_mpClose) {
		emit sig_close();
	}

}

函数结构

void CTitleBar::onClicked() {
    QPushButton* btn_ptemp = qobject_cast<QPushButton*>(sender());
  • void CTitleBar::onClicked():这是 CTitleBar 类中的槽函数,处理按钮点击事件。
  • QPushButton* btn_ptemp = qobject_cast<QPushButton*>(sender());:使用 sender() 获取发送信号的对象,并尝试将其转换为 QPushButton* 类型。qobject_cast 安全地进行类型转换,如果转换失败,则返回 nullptr

获取窗口

QWidget* widget_window = this->window();
  • QWidget* widget_window = this->window();:获取当前标题栏所属的窗口(父窗口)指针。

按钮点击处理

if (btn_ptemp == Btn_mpMin) {
    widget_window->showMinimized();
} else if (btn_ptemp == Btn_mpMax) {
    if (widget_window->isMaximized()) {
        widget_window->showNormal();
    } else {
        widget_window->showMaximized();
    }
} else if (btn_ptemp == Btn_mpClose) {
    emit sig_close();
}
  1. 最小化按钮

    • if (btn_ptemp == Btn_mpMin):检查点击的按钮是否是最小化按钮。
    • widget_window->showMinimized();:调用窗口的 showMinimized() 方法,将窗口最小化。
  2. 最大化按钮

    • else if (btn_ptemp == Btn_mpMax):检查是否是最大化按钮。
    • if (widget_window->isMaximized()):判断窗口是否已经最大化。
      • widget_window->showNormal();:如果是最大化,则恢复窗口到正常状态。
      • widget_window->showMaximized();:如果不是,则将窗口最大化。
  3. 关闭按钮

    • else if (btn_ptemp == Btn_mpClose):检查是否是关闭按钮。
    • emit sig_close();:发出 sig_close 信号,通常用于通知其他部分关闭窗口。

MainWidget.cpp

#include "MainWidget.h"
#include "QVBoxLayout"
#include <qt_windows.h>
#include <windows.h>
#include <windowsx.h>
#include <QMessageBox>

#pragma comment(lib, "user32.lib")
#pragma comment(lib,"dwmapi.lib")

MainWidget::MainWidget(QWidget* parent)
	: CFrameLessWidgetBase(parent) {
	//this->setWindowFlags(Qt::FramelessWindowHint |Qt::WindowMinMaxButtonsHint );
	this->setWindowFlags(Qt::FramelessWindowHint);



	initUI();
}


MainWidget::~MainWidget() {}

void MainWidget::initUI() {
	CTitleBar_mp = new CTitleBar(this);
	QWidget* Widget_Main = new QWidget(this);
	Widget_Main->setMinimumSize(600, 400);

	QVBoxLayout* Layout_pVMain = new QVBoxLayout(this);
	Layout_pVMain->addWidget(CTitleBar_mp);
	Layout_pVMain->addWidget(Widget_Main);

	Layout_pVMain->setContentsMargins(0, 0, 0, 0);
	setLayout(Layout_pVMain);

	connect(CTitleBar_mp, &CTitleBar::sig_close, this, &MainWidget::on_closeSlot);

}

void MainWidget::on_closeSlot() {
	close();
}


连接自定义信号和槽函数

connect(CTitleBar_mp, &CTitleBar::sig_close, this, &MainWidget::on_closeSlot);

信号和槽连接

connect(CTitleBar_mp, &CTitleBar::sig_close, this, &MainWidget::on_closeSlot);
  • connect(...):这是 Qt 的信号和槽机制,用于将一个对象的信号与另一个对象的槽连接起来。
  • CTitleBar_mp:这是 CTitleBar 类的一个实例,通常是一个自定义的标题栏控件。
  • &CTitleBar::sig_close:这是 CTitleBar 类中定义的信号。当这个信号被发出时,连接的槽会被调用。
  • this:指向当前对象(MainWidget 的实例)。
  • &MainWidget::on_closeSlot:这是 MainWidget 类中的槽函数。当 sig_close 信号被发出时,on_closeSlot() 函数将被调用。

槽函数实现

void MainWidget::on_closeSlot() {
    close();
}
  • close();:调用 close() 方法,该方法会关闭当前窗口(MainWidget 实例)。

总结

当用户在 CTitleBar 中点击关闭按钮时,会发出 sig_close 信号,随后 MainWidgeton_closeSlot 槽函数被调用,执行 close() 方法,从而关闭主窗口。这是 Qt 信号和槽机制的一种常见用法,用于实现不同组件之间的通信。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。
同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。
谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

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

相关文章

2025秋招内推--招联金融

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

【AHK】打造炒股利器系列——用数组和循环来简化语音报时器

上一篇文章&#xff0c;【AHK】打造炒股利器系列——语音报时器 作为AHK入门&#xff0c;讲解了 注释、赋值、if语句、逻辑运算符、定时器等基本知识。本篇将引入Array和Loop语句来简化化这个语音报时器&#xff0c;让代码更优雅&#xff0c;代码越简单越不容易出错误&#xff…

JavaWeb——Vue组件库Element(2/6):常见组件:Table表格、Pagination分页(介绍,属性,事件)

目录 常见组件-表格 介绍 属性 常见组件-分页 介绍 属性 事件 了解完了 Element 的快速入门程序之后&#xff0c;接下来要了解 Element 当中所提供的一些常见组件。对于 Element 当中常见组件的学习非常简单&#xff0c;基本上就是 CtrlC 复制、CtrlV 粘贴的过程。学习…

在 CentOS 8 服务器上运行 Selenium 代码

1.安装依赖包 sudo dnf update -y sudo dnf install -y wget unzip2. 安装 Google Chrome wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm sudo dnf localinstall google-chrome-stable_current_x86_64.rpm -y3. 安装 ChromeDriver 3.1首…

【深度学习】05-Rnn循环神经网络-01- 自然语言处理概述/词嵌入层/循环网络/文本生成案例精讲

循环神经网络&#xff08;RNN&#xff09;主要用于自然语言处理的。 循环神经网络&#xff08;RNN&#xff09;、卷积神经网络&#xff08;CNN&#xff09;和全连接神经网络&#xff08;FCN&#xff09;是三种常见的神经网络类型&#xff0c;各自擅长处理不同类型的数据。下面…

转做大模型开发,能不能挽救职业生涯?

大模型算是当之无愧最火的一个方向了&#xff0c;算是新时代的风口。有小伙伴觉得&#xff0c;既然是新领域、新方向&#xff0c;那么&#xff0c;人才需求肯定比较大&#xff0c;相应的人才缺乏&#xff0c;竞争也会更少&#xff0c;那转行去做大模型是不是一个更好的选择呢&a…

Leetcode 2320. 统计放置房子的方式数

原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 一条街道上共有 n * 2 个 地块 &#xff0c;街道的两侧各有 n 个地块。每一边的地块都按从 1 到 n 编号。每个地块上都可以放置一所房子。 现要求街道同一侧不能存在两所房子相邻的情况&#xff0c;请你计算并…

高并发内存池(五):ThreadCache、CentralCache和PageCache的内存回收机制 及 释放内存过程的调试

目录 ThreadCache的内存回收机制 补充内容1 补充内容2 补充内容3 新增关键函数ListTooLong CentralCache的内存回收机制 补充内容1 新增关键函数MapObjectToSpan 新增关键函数ReleaseListToSpans PageCache的内存回收机制 补充内容1 补充内容2 新增关键函数Releas…

初试React前端框架

文章目录 一、React概述二、React核心特性1、组件化设计2、虚拟DOM3、生态系统 三、实例操作1、准备工作2、创建项目结构3、启动项目4、编写React组件5、添加React样式6、运行项目&#xff0c;查看效果 四、实战小结 一、React概述 大家好&#xff0c;今天我们将一起探索React…

c语言 memmove模拟和momcpy模拟的比较

1.memcpy&#xff08;两者引用的头文件均是<stdlib.h>) 这个函数适用于开辟了两个空间的字符串数组&#xff0c;无法进行自身与自身的拷贝。eg: char* my_memcpy(void* s1, void* s2,int count) {char* start s1;while (count--) {*(char*)s1 *(char*)s2;(char*)s1 …

windows10使用bat脚本安装前后端环境之nginx注册服务

首先需要搞清楚nginx本地是怎么安装配置的、然后在根据如下步骤编写bat脚本&#xff1a; 思路 1.下载nginx-1.26 zip压缩包安装包 2.调整conf配置 3.借助winsw将nginx应用注册为服务&#xff0c;winsw下载地址 然后重命名nginx_service.exe 4.配置nginx-service.xml 5.注册wi…

【运维资料】系统运维管理方案(Doc原件2024)

1 编制目的 2 系统运行维护 2.1 系统运维内容 2.2 日常运行维护方案 2.2.1 日常巡检 2.2.2 状态监控 2.2.3 系统优化 2.2.4 软件系统问题处理及升级 2.2.5 系统数据库管理维护 2.2.6 灾难恢复 2.3 应急运行维护方案 2.3.1 启动应急流程 2.3.2 成立应急小组 2.3.3 应急处理过程 …

【数据结构】栈和队列(有完整的模拟实现代码!)

1、栈 1.1 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。…

爬取元气手机壁纸简单案例(仅用于教学,禁止任何非法获利)

爬虫常用的库 爬虫&#xff08;Web Scraping&#xff09;是一种从网页上提取数据的技术。在 Python 中&#xff0c;有许多库可以帮助实现这一目标。以下是一些常用的爬虫库&#xff0c;以及对 BeautifulSoup 的详细介绍。 常用爬虫库 1.Requests ​ a.功能&#xff1a;用于发…

利用 Llama-3.1-Nemotron-51B 推进精度-效率前沿的发展

今天&#xff0c;英伟达™&#xff08;NVIDIA&#xff09;发布了一款独特的语言模型&#xff0c;该模型具有无与伦比的准确性和效率性能。Llama 3.1-Nemotron-51B 源自 Meta 的 Llama-3.1-70B&#xff0c;它采用了一种新颖的神经架构搜索&#xff08;NAS&#xff09;方法&#…

MySQL的安装(环境为CentOS云服务器)

卸载内置环境 我们初期使用root账号&#xff0c;后期再切换成普通账号 使用 ps axj | grep mysql 查看系统中是否有MySQL相关的进程 使用 systemctl stop mysqld 关停进程 使用 rpm -qa | grep mysql 查看MySQL相关的安装包 使用 rpm -qa | grep mysql | xargs yum -y remo…

试用Debian12.7和Ubuntu24.4小札

Debian GNU/Linux 12 (bookworm)和Ubuntu 24.04.1 LTS是现阶段&#xff08;2024年9月26日&#xff09;两个发行版的最新版本。Ubuntu Server版本默认就不带桌面&#xff08;ubuntu-24.04-live-server-amd64.iso&#xff09;&#xff0c;这个默认就是最小化安装&#xff08;安装…

长芯微LPQ76930锂电池组保护芯片完全P2P替代BQ76930

LPQ76930系列芯片可作为 3-15 节串联电池组监控和保护解决方案的一部分。通过 TWI 通信&#xff0c;MCU 可以使用 LPQ76930 来执行电池管理功能1&#xff0c;例如监测&#xff08;电池电压、电池 组电流、电池组温度&#xff09;、保护&#xff08;控制充电/放电 FET&#xff0…

java中的强软弱虚

在java中对象的引用有强、软、弱、虚四种&#xff0c;这些引用级别的区别主要体现在对象的生命周期、回收时机的不同。 文章目录 准备工作1. 设置内存2. 内存检测 强引用软引用弱引用虚引用 准备工作 1. 设置内存 为方便调试&#xff0c;将内存设置为16MB 依次点击菜单栏的R…

springboot基于学习行为的学生选课成绩分析系统设计与实现

目录 功能介绍使用说明系统实现截图开发核心技术介绍&#xff1a;开发步骤编译运行核心代码部分展示开发环境需求分析详细视频演示源码获取 功能介绍 学生 课程学习行为数据录入: 学生填写每门课程的学习时长、学习态度、课后作业质量等。 课程学习行为数据修改: 学生可修改已…