【QT】自定義QWidget標題欄,可拖拽(拖拽時窗體變為normal大小),可最小/大化、關閉(圖文詳情)

目錄

0.背景

1.詳細實現

思路簡介

.h文件

.cpp文件


0.背景

Qt + Linux;項目遇到問題,解決后特此記錄

項目需要,個性化的標題欄(是個widget),在傳統的三個按鈕(最大化、最小化、關閉)的基礎上,新增了標題欄拖拽功能,有個額外要求是:拖拽標題欄的同時,讓窗口變為normal狀態(非最大化,也非最小化),也就是跟網頁差不多的居中效果。

我希望的窗口大小效果:最大化(1920*1080);普通normal狀態(1344*756);最小化(0);

我遇到的問題是:在拖拽時界面從max變為normal時,大小雖然修改為了1344*756,但如果此時我的鼠標在點擊標題欄時,是在normal大小之外(如下圖示意),此時變為normal后,會發現鼠標和窗體是分開的狀態(按住鼠標時仍可拖動),就很怪。

排查后發現是因為【當窗口從最大化狀態恢復為普通大小時,窗口的左上角位置會改變,但鼠標的全局位置保持不變】;

修改思路:在最大化狀態下,記錄鼠標在窗口中的相對位置比例 (xRatio,?yRatio);恢復普通窗口后,按相同比例計算鼠標在新窗口中的位置 (newX,?newY);計算窗口的新位置?newWindowPos,使得鼠標在屏幕中的絕對位置保持不變。

修改后normal時鼠標狀態如下:

修改后可以保證鼠標無論點擊標題欄的何處,都是可以平滑的點擊、移動,鼠標不會有點擊后出現在normal窗體外的效果。詳細代碼見下文。

1.詳細實現

思路簡介

就是實現3個按鈕release的事件;然后重寫3個protectes函數;

.h文件

#ifndef BCI_SEEG_STEER_NEW_WIDGET_H
#define BCI_SEEG_STEER_NEW_WIDGET_H#include <QWidget>
#include <QMouseEvent>
#include <QDesktopWidget>namespace Ui {
class BCI_SEEG_Steer_New_Widget;
}class BCI_SEEG_Steer_New_Widget : public QWidget
{Q_OBJECTpublic:explicit BCI_SEEG_Steer_New_Widget(QWidget *parent = nullptr);~BCI_SEEG_Steer_New_Widget();protected:void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;private slots:void on_btn_mini_released();void on_btn_max_released();void on_btn_close_released();private:Ui::BCI_SEEG_Steer_New_Widget *ui;bool m_isDragging = false;///<拖動標題欄QPoint m_dragPosition;
};#endif // BCI_SEEG_STEER_NEW_WIDGET_H

.cpp文件

#include "BCI_SEEG_Steer_New_Widget.h"
#include "ui_BCI_SEEG_Steer_New_Widget.h"BCI_SEEG_Steer_New_Widget::BCI_SEEG_Steer_New_Widget(QWidget *parent) :QWidget(parent),ui(new Ui::BCI_SEEG_Steer_New_Widget)
{ui->setupUi(this);setWindowFlags(Qt::FramelessWindowHint);showMaximized();//初始化時先告訴widget,是最大化的狀態
}BCI_SEEG_Steer_New_Widget::~BCI_SEEG_Steer_New_Widget()
{delete ui;
}//重寫鼠標按下事件
void BCI_SEEG_Steer_New_Widget::mousePressEvent(QMouseEvent *event)
{///< 判斷是否點擊了自定義標題欄,我的ui中標題欄名字叫【title_frame】,使用時要改成你的控件,你希望鼠標在哪個區域按下時,觸發可移動的事件,就改成哪個控件的名字if (event->button() == Qt::LeftButton &&childAt(event->pos()) && childAt(event->pos())->objectName() == "title_frame"){if (isMaximized()) {// 保存鼠標在屏幕中的絕對位置QPoint globalMousePos = event->globalPos();// 保存鼠標在最大化窗口中的相對位置比例qreal xRatio = (qreal)event->pos().x() / width();qreal yRatio = (qreal)event->pos().y() / height();// 恢復普通窗口并調整大小showNormal();resize(1344, 756);ui->btn_max->setIcon(QIcon(":/img/maximize windows.svg"));// 計算鼠標在新窗口中的預期位置int newX = xRatio * width();int newY = yRatio * height();// 計算窗口應該移動到的位置,使鼠標保持在同一屏幕位置QPoint newWindowPos = globalMousePos - QPoint(newX, newY);// 確保窗口不會移出屏幕QRect screenGeometry = QApplication::desktop()->availableGeometry(this);newWindowPos.setX(qMax(screenGeometry.left(),qMin(newWindowPos.x(),screenGeometry.right() - width())));newWindowPos.setY(qMax(screenGeometry.top(),qMin(newWindowPos.y(),screenGeometry.bottom() - height())));// 移動窗口到新位置move(newWindowPos);// 更新拖動位置為鼠標在窗口中的新位置m_dragPosition = QPoint(newX, newY);}else {// 普通窗口狀態下直接計算偏移m_dragPosition = event->globalPos() - frameGeometry().topLeft();}m_isDragging = true;event->accept();return;}QWidget::mousePressEvent(event);
}//重寫鼠標移動事件
void BCI_SEEG_Steer_New_Widget::mouseMoveEvent(QMouseEvent *event)
{///< 處理窗口拖動if (m_isDragging && (event->buttons() & Qt::LeftButton)) {move(event->globalPos() - m_dragPosition);event->accept();return;}QWidget::mouseMoveEvent(event);
}//重寫鼠標釋放事件
void BCI_SEEG_Steer_New_Widget::mouseReleaseEvent(QMouseEvent *event)
{Q_UNUSED(event);m_isDragging = false;
}//點擊最小化按鈕
void BCI_SEEG_Steer_New_Widget::on_btn_mini_released()
{showMinimized();
}//點擊最大化/normal按鈕
void BCI_SEEG_Steer_New_Widget::on_btn_max_released()
{if (isMaximized()) {showNormal();this->resize(1344, 756);ui->btn_max->setIcon(QIcon(":/img/maximize windows.svg"));} else {showMaximized();this->resize(1920, 1080);ui->btn_max->setIcon(QIcon(":/img/restored windows.svg"));}
}//點擊關閉按鈕
void BCI_SEEG_Steer_New_Widget::on_btn_close_released()
{this->close();
}

.ui文件

ui界面代碼我就不附上了,相關的只有標題欄和3個按鈕而已,布局如下

--END--

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/83836.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/83836.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/83836.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何用 pnpm patch 給 element-plus 打補丁修復線上 bug(以 2.4.4 修復 PR#15197 為例)

背景 在實際項目開發中&#xff0c;依賴的三方庫&#xff08;如 element-plus&#xff09;難免會遇到 bug。有時候官方雖然已經修復&#xff0c;但新版本升級成本高&#xff0c;或者有兼容性風險。這時&#xff0c;給依賴打補丁是最優雅的解決方案之一。 本文以 element-plus…

Spring AI 入門:Java 開發者的生成式 AI 實踐之路

一、Spring AI 簡介 在人工智能技術快速迭代的今天&#xff0c;Spring AI 作為 Spring 生態系統的新生力量&#xff0c;正在成為 Java 開發者擁抱生成式 AI 的最佳選擇。該框架通過模塊化設計實現了與主流 AI 服務&#xff08;如 OpenAI、Anthropic&#xff09;的無縫對接&…

優化電腦的磁盤和驅動器提高電腦性能和延長硬盤壽命?

磁盤優化 磁盤清理&#xff1a; 使用系統自帶的磁盤清理工具&#xff08;如Windows的“磁盤清理”&#xff09;刪除不必要的文件。清空回收站。刪除臨時文件和緩存。 磁盤碎片整理&#xff08;針對機械硬盤&#xff09;&#xff1a; 定期進行磁盤碎片整理&#xff0c;以提高文…

EDA斷供危機下的冷思考:中國芯片設計軟件的破局之道優雅草卓伊凡

EDA斷供危機下的冷思考&#xff1a;中國芯片設計軟件的破局之道優雅草卓伊凡 一、EDA是什么&#xff1f;芯片行業的”隱形基石” 1.1 EDA技術解析 EDA&#xff08;Electronic Design Automation&#xff0c;電子設計自動化&#xff09;是用于設計和驗證集成電路的軟件工具鏈…

Jpackage

簡介 jpackage - 用于打包自包含 Java 應用程序的工具&#xff0c;是 JDK 14 引入的一個工具。 該工具將 Java 應用程序和 Java 運行時映像作為輸入&#xff0c;并生成包含所有必要依賴項的 Java 應用程序映像。它將能夠生成特定于平臺的格式的本機包&#xff0c;例如包括打包 …

CRM管理軟件的數據可視化功能使用技巧:讓數據驅動決策

在當今數據驅動的商業環境中&#xff0c;CRM管理系統的數據可視化功能已成為企業優化客戶管理、提升銷售效率的核心工具。據企銷客研究顯示&#xff0c;具備優秀可視化能力的CRM系統&#xff0c;用戶決策效率可提升47%。本文將深入解析如何通過數據可視化功能最大化CRM管理軟件…

智慧充電:新能源汽車智慧充電樁的發展前景受哪些因素影響?

全球能源結構轉型與碳中和目標的推進&#xff0c;新能源汽車產業迎來爆發式增長&#xff0c;而智慧充電樁作為其核心基礎設施&#xff0c;發展前景備受關注。智慧充電不僅關乎用戶充電體驗的優化&#xff0c;更是電網平衡、能源效率提升的關鍵環節。 然而&#xff0c;其發展并…

ABAP設計模式之---“簡單設計原則(Simple Design)”

“Simple Design”&#xff08;簡單設計&#xff09;是軟件開發中的一個重要理念&#xff0c;倡導以最簡單的方式實現軟件功能&#xff0c;以確保代碼清晰易懂、易維護&#xff0c;并在項目需求變化時能夠快速適應。 其核心目標是避免復雜和過度設計&#xff0c;遵循“讓事情保…

多模態大語言模型arxiv論文略讀(105)

UnifiedMLLM: Enabling Unified Representation for Multi-modal Multi-tasks With Large Language Model ?? 論文標題&#xff1a;UnifiedMLLM: Enabling Unified Representation for Multi-modal Multi-tasks With Large Language Model ?? 論文作者&#xff1a;Zhaowei…

SQLServer中的存儲過程與事務

一、存儲過程的概念 1. 定義 存儲過程&#xff08;Stored Procedure&#xff09;是一組預編譯的 SQL 語句的集合&#xff0c;它們被存儲在數據庫中&#xff0c;可以通過指定存儲過程的名稱并執行來調用它們。存儲過程可以接受輸入參數、輸出參數&#xff0c;并且可以返回執行…

使用UDP連接ssh

使用UDP連接ssh mosh簡介兩端安裝moshWindows安裝mosh 放行端口使用mosh登錄Linuxdebug mosh簡介 Mosh最大的特點是基于UDP方式傳輸&#xff0c;支持在服務端創建一個臨時的Key供客戶端一次性連接&#xff0c;退出后失效&#xff1b;也支持通過SSH的配置進行認證&#xff0c;但…

軟件功能模塊歸屬論證方法

文章目錄 **一、核心設計原則****二、論證方法****三、常見決策模式****四、驗證方法****五、反模式警示****總結** 在討論軟件功能點應該歸屬哪些模塊時&#xff0c;并沒有放之四海而皆準的固定方法&#xff0c;但可以通過系統化的論證和設計原則來做出合理決策。以下是常見的…

ServBay 1.13.0 更新,新增第三方反向代理/內網穿透

ServBay 作為一款簡化本地開發環境搭建與管理的強大工具&#xff0c;致力于打造一個開箱即用、穩定可靠的本地開發平臺&#xff0c;讓用戶專注于代碼編寫&#xff0c;提升開發效率。 ServBay 1.13.0 正式發布&#xff01;本次更新聚焦于提升本地開發項目的外部可訪問性、增強國…

如何利用樂維網管進行IP管理

IP管理是網絡管理中的關鍵環節&#xff0c;對于保障網絡的正常運行、提升資源利用效率以及保障網絡安全等方面都具有不可忽視的重要性。樂維網管在IP管理方面具有多種實用功能&#xff0c;以下從IP規劃與分配、IP狀態監測、IP沖突處理、IP審計與報表生成四個方面&#xff0c;介…

Go語言學習-->go的跨平臺編譯

Go語言學習–&#xff1e;go的跨平臺編譯 默認我們go build的可執行文件都是當前操作系統可執行的文件&#xff0c;Go語言支持跨平臺編譯——在當前平臺下編譯其他平臺的可執行文件。 eg&#xff1a;在windows界面的代碼&#xff0c;編譯完成后在linux上面運行 實現方式&#…

SpringBoot自動配置原理深度解析

一、引言 SpringBoot的"約定優于配置"理念極大地簡化了Spring應用的開發流程&#xff0c;而其核心魔法就是自動配置(Auto-Configuration)。本文將深入剖析自動配置的實現原理&#xff0c;幫助開發者更好地理解和定制SpringBoot應用。 二、自動配置核心機制 1. Ena…

使用阿里云百煉embeddings+langchain+Milvus實現簡單RAG

使用阿里云百煉embeddingslangchainMilvus實現簡單RAG 注意測試時&#xff0c;替換其中的key、文檔等 import os from langchain_community.embeddings import DashScopeEmbeddings from langchain_community.vectorstores import Milvus from langchain_text_splitters impor…

事件監聽 ——CAD C#二次開發

一、AutoCAD .NET API 事件機制 1. 事件監聽核心 - Database.ModifyObjects 事件 當數據庫中的實體&#xff08;如圖形對象&#xff09;發生修改時觸發&#xff0c;包括&#xff1a; - 幾何屬性變更&#xff08;移動、縮放、旋轉&#xff09;。 - 非幾何屬性變更&#xff08…

動量及在機器人控制中的應用

動量是物理學中的一個基本概念&#xff0c;在機器人學中也有重要應用。以下是詳細解釋&#xff1a; 1. 動量的基本定義 動量&#xff08;Momentum&#xff09;是描述物體運動狀態的物理量&#xff0c;定義為&#xff1a; 線性動量&#xff1a;$ p mv $ $ m $ 為質量&#xf…

LeetCode 2434.使用機器人打印字典序最小的字符串:貪心(棧)——清晰題解

【LetMeFly】2434.使用機器人打印字典序最小的字符串&#xff1a;貪心(棧)——清晰題解 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/using-a-robot-to-print-the-lexicographically-smallest-string/ 給你一個字符串 s 和一個機器人&#xff0c;機器人當前有一個…