Qt无边框窗口拖拽和阴影

news2024/11/19 4:57:45

先看下效果:

在这里插入图片描述

说明

自定义窗口控件的无边框,窗口事件由于没有系统自带边框,无法实现拖拽拉伸等事件的处理,一种方法就是重新重写主窗口的鼠标事件,一种时通过nativeEvent事件处理。重写事件相对繁琐,我们这里推荐nativeEvent处理。注意后续我们在做win平台的进程通信,也会用到它!

  • 我们这里使用的是:nativeEvent

软件用到的样式表,这里就不展示了,大家可以自行调整!

关键点说明

QPainterPath

QPainterPath类提供一个容器,可以用来创建图形并且重复使用。绘制器路径是由许多图形构建基块(如矩形、椭圆形、直线和曲线)组成的对象。构建基块可以连接在封闭的子路径中,例如作为矩形或椭圆。封闭路径具有重合的起点和终点。或者它们可以作为未闭合的子路径独立存在,例如直线和曲线。

抗锯齿

  1. 抗锯齿是一种常见的图形处理技术,用于减少在显示器上呈现的图像中出现的锯齿状边缘。
    抗锯齿技术通过在边缘周围添加额外的像素来平滑边缘,从而减少锯齿状边缘。这种技术基于亚像素级别的渲染,它将颜色逐渐混合到边缘像素的周围像素中,使得边缘更加平滑。
  2. 打开抗锯齿可以使图像更加平滑,尤其是在呈现锐利直线或曲线时。这种技术可以减少锯齿状边缘,使得图像更加清晰,更加真实。特别是在高分辨率屏幕上,抗锯齿可以使得字体更加易读,图像更加细腻。
  3. 虽然抗锯齿可以使图像更加平滑,但在某些情况下,关闭抗锯齿可能更加合适。关闭抗锯齿可以提高图像处理速度。
  4. 这里我们基于Qt绘图框架用的是:
  • setRenderHint(QPainter::Antialiasing, true); //打开抗锯齿
  • setRenderHint(QPainter::Antialiasing, false); //关闭抗锯齿

具体实现

CDlgComBase,无边框窗口,带阴影,支持拖拽,注意:

  • 该实现方案不支持存在多个显示屏的情况!
  • 该实现方案仅支持win平台!

实现无边框带阴影的窗口代码,下面的代码供大家参考:

DlgComBase.h

#pragma once
#include "DlgShadow.h"
#include "FrameComTitleBar.h"
#include <QVBoxLayout>

class CDlgComBase : public CDlgShadow
{
	Q_OBJECT

public:
	CDlgComBase(QWidget *parent = 0, bool bCenterDlg = true, bool bHasTitleBar = true);
	~CDlgComBase();

	void SetWindowsTitle(const QString& strTitle, bool bCheckPos = false);

	// 显示隐藏按钮
	void ShowMinBtn(bool bShow);
	void ShowMaxBtn(bool bShow);
	void ShowCloseBtn(bool bShow);
	void ShowSettingBtn(bool bShow);
	
	void ShowMaximized();
	
	void SetTitleBarObjectName(QString strObjectName);
	void SetHeadBarHeight(int nHeight);

protected:
	virtual bool IsCaption(int nXPos, int nYPos);
	QWidget* GetCenterWidget() { return &m_frameCenter; }
	virtual void OnNcLBtnDbClick(int nXPos, int nYPos);

protected slots:
	void OnTimerCenter();

private:
	CFrameComTitleBar		m_frameComTitleBar;
	QVBoxLayout				m_vBoxLayout;
	QFrame					m_frameCenter;
	bool					m_bHasTitleBar;
};


DlgComBase.cpp

#include "DlgComBase.h"
#include <QTimer>

CDlgComBase::CDlgComBase(QWidget *parent, bool bCenterDlg, bool bHasTitleBar)
: CDlgShadow(parent), m_frameComTitleBar(this), m_frameCenter(this), m_bHasTitleBar(bHasTitleBar)
{
	m_frameComTitleBar.setObjectName("framComTitleBar");
	m_frameComTitleBar.setFixedHeight(GetHeadBarHeight());

	int nShadowLen = GetShadowLen();
	m_vBoxLayout.setContentsMargins(nShadowLen, nShadowLen, nShadowLen, nShadowLen);
	m_vBoxLayout.setSpacing(0);
	if (m_bHasTitleBar)
	{
		m_vBoxLayout.addWidget(&m_frameComTitleBar);
	}
	
	m_vBoxLayout.addWidget(&m_frameCenter);

	m_frameCenter.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
	setLayout(&m_vBoxLayout);

	if (bCenterDlg)
		QTimer::singleShot(10, this, SLOT(OnTimerCenter()));
}

CDlgComBase::~CDlgComBase()
{

}

void CDlgComBase::SetWindowsTitle(const QString& strTitle, bool bCheckPos)
{
	m_strTitle = strTitle;
	m_frameComTitleBar.SetWindowsTitle(strTitle, bCheckPos);
	setWindowTitle(strTitle);
}

void CDlgComBase::ShowMinBtn(bool bShow)
{
	m_frameComTitleBar.ShowMinBtn(bShow);
}

void CDlgComBase::ShowMaxBtn(bool bShow)
{
	SetHasMaxFun(bShow);
	m_frameComTitleBar.ShowMaxBtn(bShow);
}

void CDlgComBase::ShowCloseBtn(bool bShow)
{
	m_frameComTitleBar.ShowCloseBtn(bShow);
}

void CDlgComBase::ShowSettingBtn(bool bShow)
{
	m_frameComTitleBar.ShowSettingBtn(bShow);
}

bool CDlgComBase::IsCaption(int nXPos, int nYPos)
{
	QWidget* pChild = childAt(nXPos, nYPos);
	if (pChild == NULL)
	{
		ADD_LOGD("CDlgComBase::IsCaption() return true");
		return true;
	}

	if (pChild == &m_frameComTitleBar || pChild == m_frameComTitleBar.GetTitleLabel())
	{
		ADD_LOGD("CDlgComBase::IsCaption() return true");
		return true;
	}

	ADD_LOGD("CDlgComBase::IsCaption() return false");
	return false;
}

void CDlgComBase::SetTitleBarObjectName(QString strObjectName)
{
	m_frameComTitleBar.setObjectName(strObjectName);
}

void CDlgComBase::OnTimerCenter()
{
	CenterInParent((QWidget*)parent());
}

void CDlgComBase::SetHeadBarHeight(int nHeight)
{
	m_frameComTitleBar.setFixedHeight(nHeight);
	CDlgShadow::SetHeadBarHeight(nHeight);
}

void CDlgComBase::ShowMaximized()
{
	m_frameComTitleBar.ShowMaximized();
	CDlgShadow::ShowMaximized();
}

void CDlgComBase::OnNcLBtnDbClick(int nXPos, int nYPos)
{
	if (m_bHasMaxFun)
		m_frameComTitleBar.ShowMaxRestoreBtn(m_bMaximized);
	CDlgShadow::OnNcLBtnDbClick(nXPos, nYPos);
}

DlgShadow.h

#ifndef SHADOWDLG_H
#define SHADOWDLG_H
#include <QDialog>
#include <QMouseEvent>

class CDlgShadow : public QDialog
{
	Q_OBJECT

public:
	CDlgShadow(QWidget *parent = 0);
	~CDlgShadow();

	void HideDlg();
	void ShowDlg();
	void SetDlgBkColor(QColor& clrDlgBk);
	void CenterInParent(QWidget* pWidget);
	void SetResizeable(bool bOn) { m_bResizeable = bOn; }
	virtual void OnBtnSettingClicked(QPoint& ptBtnBottom);
	virtual void OnBtnMinClicked();
	virtual void OnBtnMaxClicked();
	virtual void OnBtnRestoreClicked();
	virtual void OnBtnCloseClicked();
	virtual bool OnProHotKey(int nFsModifiers, int nVk);
	virtual void OnMsgEndSession();

	void ShowMaximized();

protected:
	void paintEvent(QPaintEvent* event);
	void keyPressEvent(QKeyEvent* event);
	int GetShadowLen() { return m_nShadowLen; }
	int GetHeadBarHeight() { return m_nHeadBarHeight; }
	void SetHeadBarHeight(int nHeight);
	void SetHasMaxFun(bool bHasMaxFun) { m_bHasMaxFun = bHasMaxFun; }
	bool nativeEvent(const QByteArray& eventType, void* pMessage, long* pResult);
	virtual bool IsCaption(int nXPos, int nYPos);
	virtual void OnNcLBtnDbClick(int nXPos, int nYPos);
	virtual void OnKeyReturnPress();
	virtual void OnKeyEscapePress();
	virtual void OnNcLBtnClick();
	void closeEvent(QCloseEvent *event);

protected:
	int					m_nFrameLen;		// 边框宽度,单位:像素
	int					m_nShadowLen;		// 阴影宽度,单位:像素
	int					m_nHeadBarHeight;	// 标题栏高度
	bool				m_bHasMaxFun;
	bool				m_bMaximized;
	bool				m_bNcLBtnClk;
	bool				m_bHideDlg;
	QString				m_strTitle;			// 调试时使用
	bool				m_bHotKey;			// 处理快捷键功能

private:
	QRect				m_rectDlg;
	QColor				m_clrDlgBk;
	bool				m_bResizeable;
};

#endif // SHADOWDLG_H

DlgShadow.cpp

#include "DlgShadow.h"
#include <QPainter>
#include <qmath.h>
#include <QApplication>
#include <QDesktopWidget>
#include <Windows.h>

CDlgShadow::CDlgShadow(QWidget *parent)
	: QDialog(parent)
{
	setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog | Qt::WindowMinimizeButtonHint);
	setAttribute(Qt::WA_TranslucentBackground);
	
	m_nFrameLen = 10;
	m_nShadowLen = 6;
	m_nHeadBarHeight = 36;
	m_bMaximized = false;
	m_bHasMaxFun = true;
	m_clrDlgBk = QColor(255, 255, 255);
	m_bResizeable = true;
	m_bNcLBtnClk = false;
	m_bHideDlg = false;
	m_bHotKey = false;
}

CDlgShadow::~CDlgShadow()
{

}

void CDlgShadow::paintEvent(QPaintEvent* event)
{
	QPainterPath path;
	path.setFillRule(Qt::WindingFill);
	path.addRoundedRect(m_nShadowLen, m_nShadowLen, width() - 2 * m_nShadowLen, height() - 2 * m_nShadowLen, 2, 2);

	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing, true);
	painter.fillPath(path, QBrush(m_clrDlgBk));

	QColor color(0, 0, 0, 50);
	for (int i = 0; i < m_nShadowLen; i++)
	{
		QPainterPath pathShadow;
		pathShadow.setFillRule(Qt::WindingFill);
		pathShadow.addRoundedRect(m_nShadowLen - i, m_nShadowLen - i, width() - (m_nShadowLen - i) * 2, height() - (m_nShadowLen - i) * 2, 2 + i, 2 + i);
		int nAlpha = 50 - qSqrt(i) * 25;
		if (nAlpha < 0)
			nAlpha = 0;
		color.setAlpha(nAlpha);
		painter.setPen(color);
		painter.drawPath(pathShadow);
	}

	painter.setRenderHint(QPainter::Antialiasing, false);
	painter.fillPath(path, QBrush(m_clrDlgBk));
	QDialog::paintEvent(event);
}

void CDlgShadow::OnBtnMinClicked()
{
	showMinimized();
}

void CDlgShadow::OnBtnMaxClicked()
{
	m_bMaximized = true;
	m_rectDlg = geometry();
	setGeometry(-m_nShadowLen, -m_nShadowLen, QApplication::desktop()->availableGeometry().width() + m_nShadowLen * 2,
		QApplication::desktop()->availableGeometry().height() + m_nShadowLen * 2);
}

void CDlgShadow::OnBtnRestoreClicked()
{
	m_bMaximized = false;
	setFixedHeight(QWIDGETSIZE_MAX);
	setGeometry(m_rectDlg);
}

void CDlgShadow::SetDlgBkColor(QColor& clrDlgBk)
{
	m_clrDlgBk = clrDlgBk;
}

void CDlgShadow::SetHeadBarHeight(int nHeight)
{
	m_nHeadBarHeight = nHeight; 
}

bool CDlgShadow::IsCaption(int nXPos, int nYPos)
{
	if (childAt(nXPos, nYPos) == 0)
	{
		ADD_LOGD("CDlgShadow::IsCaption() return true");
		return true;
	}
	else
	{
		ADD_LOGD("CDlgShadow::IsCaption() return false");
		return false;
	}
}

bool CDlgShadow::nativeEvent(const QByteArray& eventType, void* pMessage, long* pResult)
{
	ADD_LOGD(QString("CDlgShadow::nativeEvent in"));

	if (m_bHideDlg)
	{
		ADD_LOGD(QString("CDlgShadow::nativeEvent out"));
		return QDialog::nativeEvent(eventType, pMessage, pResult);
	}

	const MSG* pMsg = static_cast<MSG*>(pMessage);
	if (pMsg->message == WM_NCHITTEST)
	{
		RECT rect;
		SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
		int nWin32Width = rect.right - rect.left;
		int nWin32Height = rect.bottom - rect.top;
		int nQtWidth = QApplication::desktop()->availableGeometry().width();
		int nQtHeight = QApplication::desktop()->availableGeometry().height();
		int nMsgX = ((int)(short)LOWORD(pMsg->lParam)) * nQtWidth / nWin32Width;
		int nMsgY = ((int)(short)HIWORD(pMsg->lParam)) * nQtHeight / nWin32Height;
		int xPos = nMsgX - frameGeometry().x();
		int yPos = nMsgY - frameGeometry().y();
		if (IsCaption(xPos, yPos))
		{
			*pResult = HTCAPTION;
		}
		else
		{
			ADD_LOGD(QString("CDlgShadow::nativeEvent out, WM_NCHITTEST pResult:%1").arg(*pResult));
			return false;
		}

		if (!m_bResizeable)
		{
			if (*pResult == HTCAPTION)
			{
				ADD_LOGD(QString("CDlgShadow::nativeEvent out, WM_NCHITTEST pResult:%1").arg(*pResult));
				return true;
			}

			ADD_LOGD(QString("CDlgShadow::nativeEvent out, WM_NCHITTEST pResult:%1").arg(*pResult));
			return QDialog::nativeEvent(eventType, pMessage, pResult);
		}

		if (xPos > 0 && xPos < m_nFrameLen)
			*pResult = HTLEFT;

		if (xPos >(width() - m_nFrameLen) && xPos < (width() - 0))
			*pResult = HTRIGHT;

		if (yPos > 0 && yPos < m_nFrameLen)
			*pResult = HTTOP;

		if (yPos >(height() - m_nFrameLen) && yPos < (height() - 0))
			*pResult = HTBOTTOM;

		if (xPos > 0 && xPos < m_nFrameLen && yPos > 0 && yPos < m_nFrameLen)
			*pResult = HTTOPLEFT;

		if (xPos >(width() - m_nFrameLen) && xPos < (width() - 0) && yPos > 0 && yPos < m_nFrameLen)
			*pResult = HTTOPRIGHT;

		if (xPos > 0 && xPos < m_nFrameLen && yPos >(height() - m_nFrameLen) && yPos < (height() - 0))
			*pResult = HTBOTTOMLEFT;

		if (xPos >(width() - m_nFrameLen) && xPos < (width() - 0) && yPos >(height() - m_nFrameLen) && yPos < (height() - 0))
			*pResult = HTBOTTOMRIGHT;

		ADD_LOGD(QString("CDlgShadow::nativeEvent out, WM_NCHITTEST pResult:%1").arg(*pResult));
		return true;
	}
	else if (pMsg->message == WM_NCLBUTTONDBLCLK)
	{
		int xPos = ((int)(short)LOWORD(pMsg->lParam)) - frameGeometry().x();
		int yPos = ((int)(short)HIWORD(pMsg->lParam)) - frameGeometry().y();
		OnNcLBtnDbClick(xPos, yPos);
		ADD_LOGD(QString("CDlgShadow::nativeEvent out, WM_NCLBUTTONDBLCLK"));
		return true;
	}
	else if (pMsg->message == WM_NCLBUTTONDOWN)
	{
		if (m_bNcLBtnClk)
		{
			OnNcLBtnClick();
		}
	}
	else if (pMsg->message == WM_HOTKEY)
	{
		if (m_bHotKey)
		{
			UINT nFuModifiers = (UINT)LOWORD(pMsg->lParam);  // 模式
			UINT nVirtKey = (UINT)HIWORD(pMsg->lParam);     // 键值
			if (OnProHotKey(nFuModifiers, nVirtKey))
			{
				ADD_LOGD(QString("CDlgShadow::nativeEvent out, WM_HOTKEY"));
				return true;
			}
		}
	}
	else if (pMsg->message == WM_ENDSESSION)
	{
		ADD_LOGD(QStringLiteral("截获关机指令1"));
		OnMsgEndSession();
	}

	ADD_LOGD(QString("CDlgShadow::nativeEvent out"));
	return QDialog::nativeEvent(eventType, pMessage, pResult);
}

void CDlgShadow::OnNcLBtnDbClick(int nXPos, int nYPos)
{
	if (!m_bHasMaxFun)
		return;

	if (nYPos > m_nFrameLen + m_nHeadBarHeight)
		return;

	if (m_bMaximized)
	{
		OnBtnRestoreClicked();
	}
	else
	{
		OnBtnMaxClicked();
	}
}

void CDlgShadow::CenterInParent(QWidget* pWidget)
{
	int nXPos = 0;
	int nYPos = 0;
	if (pWidget == NULL)
	{
		nXPos = (QApplication::desktop()->width() - width()) / 2;
		nYPos = (QApplication::desktop()->height() - height()) / 2;
	}
	else
	{
		QWidget* pParent = (QWidget*)pWidget->parent();
// 		if (pParent != NULL)
// 		{
// 			//QPoint ptGloba = pWidget->mapToGlobal(QPoint(0, 0));
// 			nXPos = /*ptGloba.x() + */(pWidget->width() - width()) / 2;
// 			nYPos = /*ptGloba.y() + */(pWidget->height() - height()) / 2;
// 		}
// 		else
		{
			QPoint ptGloba = pWidget->mapToGlobal(QPoint(0, 0));
			nXPos = ptGloba.x() + (pWidget->width() - width()) / 2;
			nYPos = ptGloba.y() + (pWidget->height() - height()) / 2;
		}
	}
	move(nXPos, nYPos);
}

void CDlgShadow::keyPressEvent(QKeyEvent* event)
{
	if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return/* || event->key() == Qt::Key_Space*/)
	{
		OnKeyReturnPress();
		event->accept();
	}
	else if (event->key() == Qt::Key_Escape)
	{
		OnKeyEscapePress();
		event->ignore();
	}
}


void CDlgShadow::OnKeyReturnPress()
{
	//accept();
}

void CDlgShadow::OnKeyEscapePress()
{
	//reject();
}

void CDlgShadow::OnBtnCloseClicked()
{
	reject();
}

void CDlgShadow::OnBtnSettingClicked(QPoint& ptBtnBottom)
{

}

void CDlgShadow::OnNcLBtnClick()
{

}

void CDlgShadow::HideDlg()
{
	m_bHideDlg = true;
	setWindowOpacity(0);
}

void CDlgShadow::ShowDlg()
{
	setWindowOpacity(1);
	m_bHideDlg = false;
}

void CDlgShadow::closeEvent(QCloseEvent *event)
{
	event->ignore();
	OnBtnCloseClicked();
}

bool CDlgShadow::OnProHotKey(int nFsModifiers, int nVk)
{
	return false;
}

void CDlgShadow::OnMsgEndSession()
{

}

void CDlgShadow::ShowMaximized()
{
	m_bMaximized = true;
	int nXPos = (QApplication::desktop()->availableGeometry().width() - (1273 + 11)) / 2;
	int nYPos = (QApplication::desktop()->availableGeometry().height() - (878 + 11)) / 2;
	int nMaxHeight = QApplication::desktop()->availableGeometry().height() + m_nShadowLen * 2;
	//setFixedHeight(nMaxHeight);
	setFixedHeight(QWIDGETSIZE_MAX);

	m_rectDlg = QRect(nXPos, nYPos, (1273 + 11), (878 + 11));
	setGeometry(-m_nShadowLen, -m_nShadowLen, QApplication::desktop()->availableGeometry().width() + m_nShadowLen * 2,
		QApplication::desktop()->availableGeometry().height() + m_nShadowLen * 2);
}

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

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

相关文章

HarmonyOS4.0系统性深入开发29层叠布局

层叠布局&#xff08;Stack&#xff09; 概述 层叠布局&#xff08;StackLayout&#xff09;用于在屏幕上预留一块区域来显示组件中的元素&#xff0c;提供元素可以重叠的布局。层叠布局通过Stack容器组件实现位置的固定定位与层叠&#xff0c;容器中的子元素&#xff08;子组…

maven中的version加不加SNAPSHOT的区别

我们平时开发时经常看到maven的pom.xml文件里面的包有两种 因为maven的远程仓库一般分为public(Release)和SNAPSHOT&#xff0c;前者代表正式版本&#xff0c;后者代表快照版本。 具体有什么区别呢&#xff1a; 举例说明&#xff0c;你开发了一个基础功能&#xff0c;打包发布…

bxCAN 主要特性

bxCAN 主要特性 ● 支持 2.0 A 及 2.0 B Active 版本 CAN 协议 ● 比特率高达 1 Mb/s ● 支持时间触发通信方案 发送 ● 三个发送邮箱 ● 可配置的发送优先级 ● SOF 发送时间戳 接收 ● 两个具有三级深度的接收 FIFO ● 可调整的筛选器组&#xff1a; — CAN1 和…

Execution failed for task ‘:app:compileFlutterBuildDebug‘. 解决

前言 项目场景&#xff1a;在Flutter项目中 或 在嵌入Flutter模块的Android原生项目&#xff1b; 启动场景&#xff1a;在Android原生端 编译 或 运行 项目时&#xff0c;可能出现这个异常&#xff1b; 异常 Build窗口并没有追踪到&#xff0c;引发异常代码位置&#xff0c;…

微信小程序Skyline在手机端不渲染的问题之一及其解决方式

问题&#xff1a;电脑端是skyline渲染&#xff0c;手机端是webview渲染?如何解? 开发者工具 当前渲染模式&#xff1a;Skyline 当进行预览时手机端却是: 请注意看轮播图的显示情况 请注意看轮播图的显示情况 请注意看轮播图的显示情况 从轮播图上来看,手机端是webview渲染…

[设计模式Java实现附plantuml源码~结构型]树形结构的处理——组合模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

聊聊Git合并和变基

一、 Git Merge 合并策略 1.1 Fast-Forward Merge&#xff08;快进式合并&#xff09; //在分支1下操作&#xff0c;会将分支1合并到分支2中 git merge <分支2>最简单的合并算法&#xff0c;它是在一条不分叉的两个分支之间进行合并。快进式合并是默认的合并行为&#…

【BUG】联想Y7000电池电量为0且无法充电解决方案汇总

因为最近火灾很多&#xff0c;所以昨天夜晚睡觉的时候把插线板电源关掉了&#xff0c;电脑也关机了。 各位一定要注意用电安全&#xff0c;网上的那些事情看着真的很难受qvq。 第二天早上起床的时候一看发现电脑直接没电了&#xff0c;插上电源后也是显示 你一定要冲进去啊(ू˃…

TypeScript(三) 声明变量

1.声明变量 1.1. typescript变量声明 变量是一种使用方便的占位符&#xff0c;用于引用计算机内存地址。   我们可以把变量看做存储数据的容器。   typescript变量的命名规则&#xff1a; &#xff08;1&#xff09;变量名称可以包含数字和字母。 &#xff08;2&#xff0…

flask初体验

1、定义 Flask是一个Python编写的Web 微框架,让我们可以使用Python语言快速实现一个网站或Web服务。 中文官网 2、初步上手 1、安装flask pip3 install flask 2、创建flask应用 # -*- coding = utf-8 -*- # @Time : 2024/1/28 23:02 # @Author: Frank # @File: main.py…

unity36——原神等手游常用的物理bone(弹簧)裙摆,与Cloth(布料)裙摆插件 Magica Cloth 使用教程(一)

目前我们手游开发&#xff0c;经常会遇到头发&#xff0c;双马尾&#xff0c;长裙&#xff0c;飘带等。以前我们都是在三维软件中制作骨骼后&#xff0c;自己手动K针。这样做有一些弊端&#xff0c;时间长&#xff0c;并且K帧的飘带效果没法随着游戏中角色的移动&#xff0c;旋…

HarmonyOS鸿蒙ArkTS,封装http网络请求

HarmonyOS鸿蒙ArkTS&#xff0c;封装http网络请求 前提&#xff1a; 要想使用http请求&#xff0c;系统必须要具备ohos.permission.INTERNET权限&#xff0c;在model.json5文件中的module模块下添加如下请求权限&#xff1a; 在module.json5文件中 配置 "requestPermi…

构建外卖跑腿系统:技术实现与架构设计

在当今数字化时代&#xff0c;外卖跑腿系统已成为人们生活中不可或缺的一部分。本文将探讨如何利用先进的技术和架构设计&#xff0c;开发一个高效、可靠的外卖跑腿系统。 1. 技术选型 在开发外卖跑腿系统之前&#xff0c;我们需要仔细选择适合的技术栈&#xff0c;以确保系…

HCIP复习课(三层架构)

1、ip配置 R1&#xff1a; R2&#xff1a; SW1&#xff1a; SW2: 2、vlanif配置&#xff1a; SW1&#xff1a; SW2&#xff1a; 3、ospf配置&#xff1a; R1&#xff1a; SW1&#xff1a; SW2&#xff1a; 4、vlan配置 SW1&#xff1a; SW2&#xff1a; SW3&#xff1a; SW…

在中国如何方便地使用GPT Plus?

一、背景 通过魔法&#xff0c;顺利登录ChatGPT&#xff0c;准备升级GPT Plus时&#xff0c;发现需要国外信用卡才能支付&#xff0c;这对大多数中国人来说是不方便的。在google搜索解决方案时&#xff0c;发现了WildCard平台&#xff0c;可以一键升级 GPT Plus (GPT-4)。将基…

【开源】基于JAVA+Vue+SpringBoot的康复中心管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 普通用户模块2.2 护工模块2.3 管理员模块 三、系统展示四、核心代码4.1 查询康复护理4.2 新增康复训练4.3 查询房间4.4 查询来访4.5 新增用药 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的康复中…

BGP同步规则

BGP同步规则&#xff1a;开启同步下&#xff0c;从IBGP收到一条路由不会传给任何EBGP邻居(实验效果IBGP邻居和EBGP邻居都不传)&#xff0c;除非从自身的IGP中也学到这条路由。目的是防止AS内部出现路由黑洞&#xff0c;向外部通告了一个本AS不可达的虚假的路由。 同步规则只影响…

一道CTFsql注入的问题

打开页面一个登录框&#xff0c;我甚至都没先弱口令登录&#xff0c;直接开始sql测试&#xff0c;结果测到最后发现没有&#xff0c;直接admin/admin就就去了&#xff0c;下次遇到登录框请先测试弱口令&#xff0c;ok&#xff1f; 登录成功后&#xff1a; 这句话提示中提到了…

【QT+QGIS跨平台编译】之十五:【libTiff+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、libTiff介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libTiff介绍 libTiff是一个用于处理TIFF图像文件格式的开源软件库。 TIFF(Tagged Image File Format)是一种灵活且广泛支持的图像文件格式,常用于存储照片和其他高质量图像。libTiff提供了一套…

代理IP使用指南:风险与注意事项

在当今的数字化时代&#xff0c;使用在线代理IP已经成为一种常见的网络行为。然而&#xff0c;在使用这些代理IP时&#xff0c;我们需要注意一些风险和问题&#xff0c;以确保我们的网络安全和隐本私文。将探讨使用代理IP时需要注意的几个关键问题。 1、代理IP的安全性 使用代理…