【Qt】深入探索Qt主窗口與菜單欄:構建高效用戶界面的實踐指南

文章目錄

  • 前言
  • 1. 什么是Main Window?
  • 2. 詳細了解一下其中的 菜單欄:
    • 2.1. 創建菜單欄
    • 2.2. 添加快捷鍵
    • 2.3. 添加子菜單
    • 2.4. 添加分割線
    • 2.5. 添加圖標
  • 3. 內存泄漏問題:
  • 總結

前言

在現代軟件開發中,用戶界面的設計對于提升用戶體驗至關重要。Qt框架作為功能強大的跨平臺開發工具,提供了豐富的組件和工具來幫助開發者構建復雜的應用程序。本文將深入探討Qt中的主窗口(QMainWindow)及其菜單欄(QMenuBar)的創建和使用,包括菜單欄的創建、菜單項的添加、快捷鍵的設置、子菜單的嵌套、分割線的使用以及圖標的添加。此外,文章還將討論內存泄漏問題,以及如何在Qt中避免這類問題,確保應用程序的穩定性和性能。
前面學習的所有代碼,都是基于 QWidget(控件),QWidget 更多的是作為別的窗口的一個部分。

1. 什么是Main Window?

QMainWindow 是?個為用戶提供主窗口程序的類,繼承自 QWidget 類,并且提供了?個預定義的布局。QMainWindow 包含 ?個菜單欄(menu bar)、多個工具欄(tool bars)、多個浮動窗口(鉚接部件)(dock widgets)、?個狀態欄(status bar) 和?個中心部件(central widget),它是許多應用程序的基礎,如文本編輯器,圖片編輯器等。如下圖為 QMainwindow 中 各組件所處的位置:
在這里插入圖片描述

  • 菜單欄(Menu Bar):
    Qt 中的菜單欄是通過 QMenuBar 這個類來實現的。?個主窗口最多只有?個菜單欄。位于主窗口頂部、主窗口標題欄下面。
    在這里插入圖片描述

  • 工具欄(Tool Bar Area):
    工具具欄是應用程序中集成各種功能實現快捷鍵使用的?個區域。可以有多個,也可以沒有,它并不是應用程序中必須存在的組件。它是?個可移動的組件,它的元素可以是各種窗口組件,它的元素通常以圖標按鈕的方式存在。如下圖為工具欄的示意圖:
    在這里插入圖片描述

  • 鉚接部件/子窗口(Dock Widget Area)
    一個主窗口往往可以是由多個子窗口所構成的。
    在這里插入圖片描述

  • 中央控件(Central Widget)
    窗口最核心的部分
    在這里插入圖片描述

  • 狀態欄(Status Bar)
    用于顯示一些信息供用戶去參考。
    在這里插入圖片描述

2. 詳細了解一下其中的 菜單欄:

Qt 中的菜單欄是通過 QMenuBar 這個類來實現的。?個主窗口最多只有?個菜單欄。位于主窗口頂部、主窗口標題欄下面。
菜單欄中包含菜單. 菜單中包含菜單項。
在這里插入圖片描述

一個主窗口最多只有一個菜單欄,工具欄,本質上就是菜單中的一些選項的“快捷方式”
QAction 動作

2.1. 創建菜單欄

“在這里輸入” 可以在這里添加菜單了
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

菜單欄(QMenuBar) -> 菜單(QMenu) -> 菜單項(QAction

在這里插入圖片描述
由于當前每個菜單都是空著的,點上去沒反應,添加后有反應。
在這里插入圖片描述
使用代碼去創建菜單結構:

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 1.先創建一個菜單欄QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);// 2. 創建菜單QMenu* menu1 = new QMenu("文件");QMenu* menu2 = new QMenu("編輯");QMenu* menu3 = new QMenu("視圖");menuBar->addMenu(menu1);menuBar->addMenu(menu2);menuBar->addMenu(menu3);// 3. 給菜單添加菜單項QAction* action1 = new QAction("新建");QAction* action2 = new QAction("打開");QAction* action3 = new QAction("保存");QAction* action4 = new QAction("另存為");QAction* action5 = new QAction("退出");menu1->addAction(action1);menu1->addAction(action2);menu1->addAction(action3);menu1->addAction(action4);menu1->addAction(action5);}MainWindow::~MainWindow()
{delete ui;
}

在這里插入圖片描述
怎樣使它點擊的時候有反應呢?

QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("打開");
QAction* action3 = new QAction("保存");
QAction* action4 = new QAction("另存為");
QAction* action5 = new QAction("退出");

被點擊的時候會觸發一個信號!triggered 觸發

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 1.先創建一個菜單欄QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);// 2. 創建菜單QMenu* menu1 = new QMenu("文件");QMenu* menu2 = new QMenu("編輯");QMenu* menu3 = new QMenu("視圖");menuBar->addMenu(menu1);menuBar->addMenu(menu2);menuBar->addMenu(menu3);// 3. 給菜單添加菜單項QAction* action1 = new QAction("新建");QAction* action2 = new QAction("打開");QAction* action3 = new QAction("保存");QAction* action4 = new QAction("另存為");QAction* action5 = new QAction("退出");menu1->addAction(action1);menu1->addAction(action2);menu1->addAction(action3);menu1->addAction(action4);menu1->addAction(action5);// 4. 給 action 添加信號槽connect(action1, &QAction::triggered, this, &MainWindow::handle);connect(action5, &QAction::triggered, this, &MainWindow::close); // close 是Qt自帶關閉窗口的槽函數}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle()
{qDebug() << "觸發新建操作!";
}

在這里插入圖片描述

2.2. 添加快捷鍵

給菜單和菜單項設置快捷鍵
設置好的快捷鍵就可以搭配 alt 來進行使用了

QMenu* menu1 = new QMenu("文件(&F)");

通過給文本添加 &F 這樣的操作,就是添加了快捷鍵 alt+F
與,QLabel,中設置伙伴的方式比較相似,當然使用 QShortcut 也可以實現同樣的效果但是太麻煩了。
在這里插入圖片描述
給菜單項同樣可以添加快捷鍵:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menBar = new QMenuBar();this->setMenuBar(menBar);QMenu* menu1 = new QMenu("文件(&F)");QMenu* menu2 = new QMenu("視圖(&V)");menBar->addMenu(menu1);menBar->addMenu(menu2);// 創建四個菜單項QAction* action1 = new QAction("action1(&Q)");QAction* action2 = new QAction("action2(&W)");QAction* action3 = new QAction("action3(&E)");QAction* action4 = new QAction("action4(&R)");menu1->addAction(action1);menu1->addAction(action2);menu2->addAction(action3);menu2->addAction(action4);// 如果不綁定槽函數,通過快捷鍵選中也沒啥反應connect(action1, &QAction::triggered, this, &MainWindow::handle1);connect(action2, &QAction::triggered, this, &MainWindow::handle2);connect(action3, &QAction::triggered, this, &MainWindow::handle3);connect(action4, &QAction::triggered, this, &MainWindow::handle4);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle1()
{qDebug() << "handle1" ;
}void MainWindow::handle2()
{qDebug() << "handle2" ;
}void MainWindow::handle3()
{qDebug() << "handle3" ;
}void MainWindow::handle4()
{qDebug() << "handle4" ;
}

2.3. 添加子菜單

菜單欄 -> 菜單 -> 菜單項
菜單欄->菜單->子菜單->菜單項

QMenuBar 可以通過 addMenu 添加菜單的,QMenu 也提供了 addMenu

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menuParent = new QMenu("父菜單");QMenu* menuChild = new QMenu("子菜單");menuBar->addMenu(menuParent);menuParent->addMenu(menuChild);QAction* action1 = new QAction("菜單項1");QAction* action2 = new QAction("菜單項2");menuChild->addAction(action1);menuChild->addAction(action2);QMenu* menuChild2 = new QMenu("子菜單2");menuChild->addMenu(menuChild2);}MainWindow::~MainWindow()
{delete ui;
}

在這里插入圖片描述

2.4. 添加分割線

菜單里菜單特別多,就可以通過分割線進行分組

QMenu 中提供了 addSeparator 這樣的函數

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menu = new QMenu("菜單");menuBar->addMenu(menu);QAction* action1 = new QAction("菜單項1");QAction* action2 = new QAction("菜單項2");menu->addAction(action1);menu->addSeparator();menu->addAction(action2);
}MainWindow::~MainWindow()
{delete ui;
}

在這里插入圖片描述

2.5. 添加圖標

Qlcon 類, qrc

在這里插入圖片描述

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QMenuBar* menuBar = new QMenuBar();this->setMenuBar(menuBar);QMenu* menu = new QMenu("菜單");menuBar->addMenu(menu);QAction* action1 = new QAction("菜單項1");action1->setIcon(QIcon(":/open.png"));QAction* action2 = new QAction("菜單項2");action2->setIcon(QIcon(":/save.png"));menu->addAction(action1);menu->addAction(action2);
}MainWindow::~MainWindow()
{delete ui;
}

在這里插入圖片描述
如果給 QMenu 設置圖標,當前 QMenu 是長在 QMenuBar 上的,此時文本就不顯示,圖標就覆蓋了文本。

QMenu 是子菜單,圖標和文本都是能顯示的。

3. 內存泄漏問題:

QMenuBar* menuBar = new QMenuBar();
this->setMenuBar(menuBar);

如果咱們創建項目,沒有勾選生成ui,文件,此時上述代碼是可以的,如果勾選了自動生成 ui 文件,上述代碼則會引起內存泄漏。
自動生成 ui 文件:Qt已經給你生成了一個 QMenuBar 了。

之前程序已經創建好了一個 QMenuBar , 當設置新的 QMenuBar 進來的時候, 就會導致舊的 QMenuBar 脫離了 Qt 的對象樹了,意味著后續無法對這個對象樹進行釋放了

上訴程序如果窗口關閉,對象樹釋放,此時進程也就介紹了。進程結束,自然所有內存都回收給系統。上述內存泄漏也不會造成影響,但是如果這樣的如果出現在一個多窗口的程序中。如果涉及到窗口的頻繁跳轉切換(窗口的頻繁創建銷毀),上述代碼泄漏會更嚴重一些。但是實際上由于現在的計算機內存都比較充裕上述內存泄漏都還好。

服務器程序相比于客戶端程序相比更害怕內存泄漏。

  1. 服務器要處理很多請求,每個請求泄漏一點,請求累積下來就會泄漏很多
  2. 服務器要 7 * 24 小時運行。

當然,即使如此,還是期望代碼寫的更規范一些。

QMenuBar* menuBar = this->menuBar();
  1. 如果 QMenuBar 已經存在,直接獲取并返回
  2. 如果 QMenuBar 不存在,就先創建一個新的,再返回。
this->setMenuBar(menuBar);

如果是活的已經存在的 QMenuBar, 這里的設置就是自己替換自己,仍然對象樹上

如在嵌入式,設備上內存泄漏的問題就比較重要了。

總結

本文詳細介紹了Qt中主窗口(QMainWindow)的構成和功能,特別是菜單欄(QMenuBar)的創建和使用。通過一系列具體的代碼示例,我們學習了如何創建菜單欄、添加菜單和菜單項、設置快捷鍵、嵌套子菜單、使用分割線以及添加圖標,這些都是構建用戶友好界面的關鍵步驟。同時,文章也指出了在Qt開發中可能遇到的內存泄漏問題,并提供了解決方案,強調了在開發過程中遵循良好編程實踐的重要性。通過這些知識點,開發者可以更有效地利用Qt框架,創建出既美觀又實用的應用程序界面。

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

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

相關文章

【雅特力AT32】串口UART、USART配置和使用方法,數組的阻塞發送函數編寫,串口接收中斷、回環、重定向

【雅特力AT32】串口UART、USART配置和使用方法&#xff0c;數組的阻塞發送函數編寫&#xff0c;串口接收中斷、回環、重定向 文章目錄 串口配置阻塞發送函數接收中斷和串口回環串口重定向附錄&#xff1a;Cortex-M架構的SysTick系統定時器精準延時和MCU位帶操作SysTick系統定時…

了解CentOS及其基礎

什么是CentOS&#xff1f; CentOS&#xff08;Community ENTerprise Operating System&#xff09;是一個社區支持的操作系統&#xff0c;基于Red Hat Enterprise Linux&#xff08;RHEL&#xff09;的源代碼。它是免費且開源的&#xff0c;廣泛用于服務器環境。 為什么選擇C…

深入理解HTTP:工作原理、特性及應用

HTTP&#xff0c;全稱Hypertext Transfer Protocol&#xff0c;即超文本傳輸協議&#xff0c;是互聯網上應用最為廣泛的一種網絡協議。它定義了客戶端和服務器之間如何交換信息&#xff0c;以及如何傳輸超文本和其他內容。HTTP協議的出現極大地推動了互聯網的普及和發展&#x…

ARM|DSP+FPGA+NVIDIA AI攝像頭定制

信邁擁有高性能的攝像頭全棧能力&#xff1a;掌握車載模組光學設計能力&#xff0c;具有多名經驗豐富光學設計專家&#xff1b;具備豐富的車載攝像模組硬件設計經驗&#xff1b;掌握目前市面上大部分車載平臺的ISP圖像畫質服務能力&#xff0c;能自主開發圖像ISP和增強算法&…

第十二章 網絡編程

第十二章 網絡編程 網絡協議概述 通信協議&#xff1a; 協議即規則&#xff0c;就好比汽車上路要遵守交通規則一樣&#xff0c;為了使全世界不同類型的計算機都可以連接起來&#xff0c;所以制定了一套全球通用的通信協議——Internet協議。有了Internet協議&#xff0c;任何…

【mysql】【docker】mysql8-互為主從

&#x1f338;&#x1f338; Linux/docker-compose/mysql8 互為主從 優雅部署 &#x1f338;&#x1f338; 記錄下兩臺Linux的mysql需要熱備份&#xff0c;互為主從&#xff0c;后期加上keepalived實現高可用切換 參考博客&#xff1a;答 案 &#x1f338; 一、準備文件 這里…

圖形學初識--直線插值算法

文章目錄 為什么需要插值算法&#xff1f;插值算法是什么&#xff1f;有哪些常見的插值算法呢&#xff1f;1. 線性插值&#xff08;Linear Interpolation&#xff09;2. 多項式插值&#xff08;Polynomial Interpolation&#xff09;3. 樣條插值&#xff08;Spline Interpolati…

Blazor 下支持 Azure AD 的多套登錄方案

比如上圖配置了兩套不同的登錄方案&#xff0c;各有自己的 TenantId 和 ClientId &#xff0c;要同時支持他們的登錄&#xff08;其實在同一套 TenantId 和 ClientId 里面配置多個登錄賬戶不就好了&#xff0c;但是......那套登錄的管理是在客戶自己的Azure AD賬戶管理下的&…

SpringBoot3 解決NoResourceFoundException: No static resource favicon.ico.異常

SpringBoot3 解決NoResourceFoundException: No static resource favicon.ico.異常 spring boot3項目中瀏覽器中訪問報錯找不到favicon.ico&#xff0c;雖然不影響使用&#xff0c;用api工具也可以忽略這個異常&#xff0c;但是防止瀏覽器訪問時出現異常干擾日志&#xff0c;所…

oracle數據庫解析過高分析

解析非常高&#xff0c;通過時間模型可以看到解析占比非常高 解析大致可以分為硬解析&#xff08; hard parse&#xff09;、軟解析&#xff08; soft parse&#xff09;和軟軟解析&#xff08; soft soft parse&#xff09;。如&#xff0c;執行一條 SQL 的時候&#xff0c;如…

星型模型和雪花模型的區別

星型模型和雪花模型都是數據倉庫設計中常用的維度建模方法&#xff0c;它們之間的主要區別在于數據組織結構、數據冗余度、查詢效率、可擴展性和正規化程度等方面&#xff1a; 星型模型 結構特點&#xff1a;星型模型中&#xff0c;一個中心的事實表連接多個維度表&#xff0…

在電腦中,Apple Mobile Device Support程序是什么?

Apple Mobile Device Support 是一項關鍵的后臺服務&#xff0c;它為 Windows 用戶提供了與蘋果 iOS 設備&#xff08;包括 iPhone、iPad 和 iPod&#xff09;順暢互動的能力。這項服務的核心功能是為iTunes軟件提供必要的支持&#xff0c;使得用戶能夠將他們的移動設備與電腦連…

Google Find My Device:科技守護,安心無憂

在數字化的時代&#xff0c;我們的生活與各種智能設備緊密相連。而 Google Find My Device 便是一款為我們提供安心保障的實用工具。 一、Find My Decice Netword的定義 谷歌的Find My Device Netword旨在通過利用Android設備的眾包網絡的力量&#xff0c;幫助用戶安全的定位所…

HTML5 歷史、地理位置處理、全屏處理

目錄 歷史HistoryAPI地理位置處理GeolocationAPI全屏處理FullscreenAPIHistoryAPI window.history 對象 window.history 是瀏覽器提供的一個內置對象,它提供了對瀏覽器歷史記錄的訪問和操作能力。通過這個對象,開發者可以實現無刷新頁面跳轉、添加新的瀏覽歷史條目等,從而提…

STM32F4_HAL控制GPIO輸出——跑馬燈實驗

1、GPIO工作模式 1.1 端口輸入數據寄存器&#xff08;IDR&#xff09; 1.2 端口輸出數據寄存器&#xff08;ODR&#xff09; 1.3 端口置位/復位寄存器&#xff08;BSRR&#xff09; 為什么有了 ODR 寄存器&#xff0c;還要這個 BSRR 寄存器呢&#xff1f;我們先看看 BSRR 的寄…

23種設計模式(持續輸出中)

一.設計模式的作用 設計模式是軟件從業人員長期總結出來用于解決特定問題的通用性框架&#xff0c;它提高了代碼的可維護性、可擴展性、可讀性以及復用性。 二.設計模式 1.工廠模式 工廠模式提供了創建對象的接口&#xff0c;而無需制定創建對象的具體類&#xff0c;工廠類…

hive表在HDFS的每個文件的大小加大

配置參數&#xff1a; spark.hadoop.hive.exec.orc.default.stripe.size78643200 spark.hadoop.orc.stripe.size78643200 spark.hadoopRDD.targetBytesInPartition78643200 spark.hadoop.hive.exec.dynamic.partition.modenonstrict spark.sql.sources.partitionOverwriteMode…

華為OD機試 - 剩余銀飾的重量(Java 2024 C卷 100分)

華為OD機試 2024C卷題庫瘋狂收錄中&#xff0c;刷題點這里 專欄導讀 本專欄收錄于《華為OD機試&#xff08;JAVA&#xff09;真題&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一題都有詳細的答題思路、詳細的代碼注釋、樣例測試…

【Python】 如何對對象列表進行排序,有點意思

在Python中&#xff0c;我們經常需要對對象列表進行排序&#xff0c;這可以通過多種方式實現。當對象是一個自定義類實例時&#xff0c;排序通常基于對象的一個或多個屬性。Python提供了內置的sorted()函數和列表的sort()方法&#xff0c;它們都允許我們指定一個排序的關鍵字。…

iPhone徹底刪除的照片怎么恢復?專業技巧助您解憂

在使用iPhone的過程中&#xff0c;我們可能會因為誤操作或其他原因將一些重要的照片徹底刪除。然而&#xff0c;即使照片被徹底刪除&#xff0c;也并不意味著它們就永遠消失了&#xff0c;它們只是被打上了“可覆蓋的空間”的標簽。 在照片被新數據覆蓋之前&#xff0c;我們仍…