Qt——實現”Hello World“、認識對象樹與Qt坐標系

在創建項目時,使用的基類Base ClassQWidget

1. 使用圖形化界面的方式實現“Hello World”

  1. 雙擊文件:widget.ui,進入designer模式:

在這里插入圖片描述

  1. 在“控件盒子”的“Display Widgets”中找到“Label”,并拖放到白板中

    在這里插入圖片描述

  2. 雙擊剛剛拖放到Label,輸入"Hello World"

    在這里插入圖片描述

  3. 最后直接運行即可:

    在這里插入圖片描述

此時我們回過頭來看widget.ui和編譯生成的ui_widget.h文件,都發生了變化:

// widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>Widget</class><widget class="QWidget" name="Widget"><property name="geometry"><rect><x>0</x><y>0</y><width>800</width><height>600</height></rect></property><property name="windowTitle"><string>Widget</string></property><widget class="QLabel" name="label"><property name="geometry"><rect><x>230</x><y>110</y><width>81</width><height>51</height></rect></property><property name="text"><string>&quot;Hello World&quot;</string></property></widget></widget><resources/><connections/>
</ui>// ui_widget.h
/********************************************************************************
** Form generated from reading UI file 'widget.ui'
**
** Created by: Qt User Interface Compiler version 6.7.3
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/#ifndef UI_WIDGET_H
#define UI_WIDGET_H#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QWidget>QT_BEGIN_NAMESPACEclass Ui_Widget
{
public:QLabel *label;void setupUi(QWidget *Widget){if (Widget->objectName().isEmpty())Widget->setObjectName("Widget");Widget->resize(800, 600);label = new QLabel(Widget);label->setObjectName("label");label->setGeometry(QRect(230, 110, 81, 51));retranslateUi(Widget);QMetaObject::connectSlotsByName(Widget);} // setupUivoid retranslateUi(QWidget *Widget){Widget->setWindowTitle(QCoreApplication::translate("Widget", "Widget", nullptr));label->setText(QCoreApplication::translate("Widget", "\"Hello World\"", nullptr));} // retranslateUi};namespace Ui {class Widget: public Ui_Widget {};
} // namespace UiQT_END_NAMESPACE#endif // UI_WIDGET_H

2. 用代碼的方式實現“Hello World”

一般來說,在實現圖形化界面時,一般在繼承類的構造函數中進行編寫,如這里的widget.h

實現如下:

#include "widget.h"
#include "./ui_widget.h"
#include <QLabel>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QLabel* label = new QLabel(this);label->setText("\"Hello World\"");
}Widget::~Widget()
{delete ui;
}
  • Qt中每個類都有其同名的頭文件,要使用類QLabel,就需要包含頭文件<QLabel>

  • 在定義QLabel對象時,一般建議在堆上創建,同時建議將這個對象掛到對象樹上,其父節點就是this

  • 方法label->setText的形參實際上是類型QString

    • Qt的誕生時間比C++標準形成的時間要早,因此,對于一些常見的數據結構,Qt自己造了一些輪子
    • 例如:QStringQVectorQListQMap
    • C++標準庫中的容器也可以很方便的和Qt中的容器類相互轉換

最后運行結果如圖:

在這里插入圖片描述

內存泄露問題

可以注意到,為了使用QLable對象,我們只用了new語句:QLabel* label = new QLabel(this);

我們在后面沒有delete掉,不就內存泄露了嗎?

這里可以告訴大家結論:

  • 上述代碼在Qt中,不會產生內存泄露, 及在合適的時候 **,**?label會被自動釋放
  • 原因就是,??label??對象被掛到對象樹上了

對象樹

引入對象樹的主要目的,就是將諸如QLable這樣的空間進行統一管理,這樣就可以統一在合適的時候進行釋放

  • 所謂合適的時候,就是圖形界面窗口關閉/銷毀的時候
  • 而如果不適用對象樹,就可能導致一些資源的提前釋放,具體到圖形化界面中就可能導致一些控件元素不會正常顯示
  • 在上面的代碼中,將QLabel對象開辟在堆空間上,就是為了將其生命周期交給對象樹進行管理

而如果開辟在棧上,就可能引發問題:

#include "widget.h"
#include "./ui_widget.h"
#include <QLabel>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// QLabel* label = new QLabel(this);// label->setText("\"Hello World\"");QLabel label(this);label.setText("\"Hello World\"");
}Widget::~Widget()
{delete ui;
}

運行:

在這里插入圖片描述

發現預期的"Hello World"不見了

為了驗證如果一個對象被掛到對象樹上,會被自動清理,我么可以新建一個類myQLabel,其繼承于QLabel

  1. 新建文件

在這里插入圖片描述

  1. 選擇C++中的C++ class

  2. 填寫自定義類的信息

    在這里插入圖片描述

代碼如下:

// myQLabel.h
#ifndef MYQLABEL_H
#define MYQLABEL_H#include <QLabel>class myQLabel : public QLabel
{
public:myQLabel(QWidget* parent);~myQLabel();
};#endif // MYQLABEL_H// myQlabel.cpp
#include "myqlabel.h"#include <iostream>myQLabel::myQLabel(QWidget* parent): QLabel(parent) {}myQLabel::~myQLabel()
{std::cout << "MyQLabel 被釋放" << std::endl;
}// widget.cpp
#include "widget.h"
#include "./ui_widget.h"
// #include <QLabel>
#include "myqlabel.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);myQLabel* label = new myQLabel(this);label->setText("\"Hello World\"");
}Widget::~Widget()
{delete ui;
}

可以看到,在關閉圖形化窗口時,會輸出:

在這里插入圖片描述

亂碼問題

從上面的輸出我們可以看到,本來應該被打印的漢字“被釋放”,輸出竟然是亂碼,這是為什么?

首先要說明結論:亂碼之所以出現,其最主要的原因就是編碼方式不一致

  • 源代碼文件的編碼格式
  • 終端(控制臺)的顯示編碼格式
  • 字符串本身的編碼處理方式

接下來,我們同樣用該清楚,一個漢字到底占幾個字節?

  • 對于這個問題,我們首先要區分漢字是采用哪種編碼方式進行編碼的——GBK,UTF-8
  • 如果采用GBK方式編碼,那一個漢字就占2個字節
  • 如果采用UTF-8方式編碼,那一個漢字就占2~4個字節,一般為3字節

我們先來查看輸出漢字的文件myqlable.cpp是采用哪種方式進行編碼:

在這里插入圖片描述

  • 可以看到,編碼方式為UTF-8
  • 而如果顯示為ANSI,那么編碼方式就是GBK

既然myqlabel.cpp的編碼方式為utf8,但輸出到控制臺卻出現亂碼,說明終端控制臺的編碼方式就不是UTF-8

qDebug

為了解決這一問題,我們不是用C++標準的標準輸出std::cout,而采用Qt提供的QDebug類:

#include "myqlabel.h"#include <QDebug>myQLabel::myQLabel(QWidget* parent): QLabel(parent) {}myQLabel::~myQLabel()
{qDebug() << "MyQLabel 被釋放";
}
  • QDebug這個類重載了移位運算符<<,不直接使用類QDebug;而qdebug是一個宏,封裝了QDebug對象,我們可以像使用std::cout一樣來使用它
  • 使用qDebug()還有另一個好處,我們可以使用開關來對日志輸出進行關閉, 防止日志信息對用戶的干擾

3. 使用輸入框實現 “Hello World”

3.1 使用圖形化界面的方式

  1. 雙擊文件widget.ui,進入designer模式后找到控件:Line Edit

    在這里插入圖片描述

  2. 將其拖放到白板中,雙擊控件,輸入"Hello World"

    在這里插入圖片描述

  3. 保存并運行即可

    在這里插入圖片描述

3.2 使用代碼的方式

QLabel的操作方式一樣,將widget.cpp文件修改如下:

#include "widget.h"
#include "./ui_widget.h"#include <QLineEdit>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QLineEdit* line_edit = new QLineEdit(this);line_edit->setText("\"Hello World\"");
}Widget::~Widget()
{delete ui;
}

運行:

在這里插入圖片描述

4. 使用按鈕的方式實現“Hello World”

4.1 使用圖形化界面的方式

  1. 雙擊文件widget.ui,進入designer模式后找到控件:Push Button

在這里插入圖片描述

  1. 將其拖放到白板中,雙擊控件,輸入"Hello World"

    在這里插入圖片描述

    同時可以看到,在QObject中出現了objectName和對應的值:

    • Qt Designer創建一個控件的時候,此時會給這個控件分配一個objectName屬性,這個屬性的值要求在界面中是唯一的。我么也可以自己指定這個值

    • CMake在預處理.ui文件的時候,就會根據objectName來生成同名的類。例如上面的控件pushButton被生成的類名就是myPushButton

    • 我們可以在生成的ui_widget.h中看到這樣的代碼:

      在這里插入圖片描述

  2. 進入編輯界面,修改widget.cpp如下:

// widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void clickHandler();private:Ui::Widget *ui;
};
#endif // WIDGET_H//widget.cpp
#include "widget.h"
#include "./ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->myPushButton, &QPushButton::clicked, this, &Widget::clickHandler);
}Widget::~Widget()
{delete ui;
}// 當控件內容為“Hello World”,點擊按鈕后,就會變為“Hello Qt”
// 當空間內容為“Hello Qt”,點擊按鈕后,就會變為“Hello World“
void Widget::clickHandler()
{if (ui->myPushButton->text() == "\"Hello World\"") {ui->myPushButton->setText("\"Hello Qt\"");} else {ui->myPushButton->setText("\"Hello World\"");}
}

上述出現的connect是類QObject提供的靜態函數,其功能是連接“信號”和“槽”,其4個參數的作用分別為:

在這里插入圖片描述

在這里插入圖片描述

4.2 使用代碼的方式

代碼如下:

// widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPushButton>QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void clickHandler();private:Ui::Widget *ui;QPushButton* myPushButton_ = nullptr;
};
#endif // WIDGET_H// widget.cpp
#include "widget.h"
#include "./ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), myPushButton_(new QPushButton(this))
{ui->setupUi(this);myPushButton_->setText("\"Hello World\"");connect(myPushButton_, &QPushButton::clicked, this, &Widget::clickHandler);
}Widget::~Widget()
{delete ui;
}void Widget::clickHandler()
{if (myPushButton_->text() == "\"Hello World\"") {myPushButton_->setText("\"Hello Qt\"");} else {myPushButton_->setText("\"Hello World\"");}
}

5. 圖形化方式開發和代碼方式開發

實際開發中,圖形化方式開發界面和以純代碼方式代碼界面都是很常用的方法

  • 如果界面內容是比較固定的,此時就會使用圖形化界面來構造
  • 如果界面內容經常要動態變化,就需要以代碼的方式進行開發
  • 此外,這兩種方式也可以配合使用

6. Qt 坐標系

Qt的坐標系是 平面直角坐標系,其X軸從左往右增長,Y軸從上往下增長

在這里插入圖片描述

坐標系的原點就是屏幕的左上角/窗口的左上角

給Qt的控件指定位置,就需要設置坐標,對于這個控件來說,其原點是相對于父窗口/父控件的

在這里插入圖片描述

而如果要指定控件或窗口的位置,就需要用到對應的move成員函數:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), myPushButton_(new QPushButton(this))
{ui->setupUi(this);myPushButton_->setText("\"Hello World\"");myPushButton_->move(200, 300);this->move(100, 200);
}
  • move的第一個參數為水平移動距離,單位為像素px
  • move的第二個參數為豎直移動距離,單位為像素px

運行如圖:

在這里插入圖片描述

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

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

相關文章

智能合約開發全流程實戰指南

目錄 靈感探索與概念驗證合約開發常見問題 Hardhat 初始化項目問題合約編譯錯誤處理智能合約設計缺陷 合約測試最佳實踐 單元測試環境配置測試用例編寫技巧測試覆蓋率和策略常見測試失敗原因 合約部署實戰指南 部署到不同網絡部署前準備事項部署后驗證方法部署費用和Gas優化 合…

IPA1299至為芯替代TI ADS1299的腦機接口芯片

在腦機接口、神經科學研究和醫療電子設備領域&#xff0c;腦電信號采集芯片是連接生物電信號與數字世界的重要組件。目前&#xff0c;TI等國際廠商憑借技術優勢占據市場主要份額&#xff0c;國內廠商在成本控制、供貨周期和技術自主性方面面臨挑戰。英集芯推出的IPA1299低噪聲多…

「數據獲取」《中國海洋生態環境狀況公報》(2001-2023年)(獲取方式看綁定的資源)

01、數據簡介在 2023 年的海洋環境監測工作中&#xff0c;監測范圍廣泛且細致。全年對 1359 個海洋環境質量國家控制點位進行了水質監測&#xff0c;這些點位分布在我國管轄的各大海域&#xff0c;能夠全面反映海洋整體水質狀況&#xff1b;對 230 個入海河流國家控制斷面開展監…

通過限制網絡訪問來降低服務器被攻擊風險的方法

限制網絡訪問是降低服務器被攻擊風險的核心思路之一&#xff0c;因為絕大多數入侵都是從開放的網絡入口開始的。思路是“減少暴露面 精確授權”&#xff0c;讓服務器只對必要的人、必要的業務開放。我給你分成幾個層次來說明&#xff0c;從最外層網絡入口到最內層系統配置都涉…

python與JavaScript的區別

Python 與 JavaScript 的主要區別&#xff08;按常用維度劃分&#xff09;維度PythonJavaScript誕生時間 / 背景1991 年&#xff0c;由 Guido van Rossum 設計&#xff0c;目標是“一種易讀、易寫的通用腳本語言”。1995 年&#xff0c;由 Brendan Eich 為 Netscape 瀏覽器誕生…

Java 比較器解析

一、比較器的核心作用與應用場景在 Java 編程中&#xff0c;數據比較是一個基礎但重要的操作。對于基本數據類型&#xff08;如 int、double、boolean、char 等&#xff09;&#xff0c;Java 語言本身就提供了完整的比較運算符&#xff08;>、<、、>、<、!&#xf…

Java學習第一百二十一部分——HTTP

目錄 一、前言簡介 二、核心特性 三、通信基礎結構 四、關鍵組件詳解 五、性能演進——版本對比 六、開發者建議 七、總結歸納 一、前言簡介 HTTP&#xff08;“H”yper“t”ext “T”ransfer “P”rotocol&#xff0c;超文本傳輸協議&#xff09;是互聯網上應用最廣泛…

記錄RK3588的docker中啟動rviz2報錯

安裝好rk3588 的docker&#xff0c;pull了ros的完整鏡像后&#xff0c;想要啟動rviz但是報錯&#xff0c;下面是我的踩坑記錄 0.原始的啟動鏡像的腳本&#xff1a; sudo docker run -it --rm --privileged --nethost -e DISPLAY$DISPLAY --namemy_image_name \-e DISPLAY$DIS…

ThingJS 新手學習技巧

一、ThingJS 基礎認知 1.1 ThingJS 是什么 ThingJS 是一款基于 WebGL 技術的 3D 可視化開發平臺&#xff0c;它為開發者提供了簡單易用的 API 和豐富的 3D 場景組件&#xff0c;讓開發者能夠快速構建出高質量的 3D 可視化應用。無論是智慧園區、智慧樓宇、智慧交通還是工業監…

【軟考架構】需求工程中,系統分析與設計的結構化方法

結構化方法誕生于20世紀70年代&#xff0c;是為了應對當時日益復雜的軟件系統開發挑戰&#xff08;如“軟件危機”&#xff09;而提出的。它強調系統性、規范性、分解和抽象&#xff0c;目標是提高軟件開發的效率、質量和可維護性&#xff0c;降低復雜性。 核心思想&#xff1a…

FPGA常用資源之IO概述

目錄 一、前言 二、I/O資源 2.1 I/O端口資源 2.1.1 IOB 2.1.2 ILOGIC/OLOGIC 2.2 ZHOLD 2.3 IDDR/ODDR 2.4 IDELAY 2.5 ISERDES/OSERDES 2.6 IO Logic Resource連接 2.7 Device示意圖 三、工程示例 3.1 工程代碼 3.2 Device結果 一、前言 FPGA芯片從內部結構看主…

密集遮擋場景識別率↑31%!陌訊輕量化部署方案在智慧零售的實戰解析

一、零售業痛點&#xff1a;當技術遇上客流洪流據《2024智慧零售技術白皮書》統計&#xff0c;高峰期超市顧客密度超3人/㎡時&#xff0c;??目標漏檢率高達48%??。核心挑戰包括&#xff1a;??動態遮擋??&#xff1a;購物車/貨架造成的持續性目標截斷??計算瓶頸??&a…

力扣(O(1) 時間插入、刪除和獲取隨機元素)

一、題目分析&#xff08;一&#xff09;功能需求 我們需要實現 RandomizedSet 類&#xff0c;包含以下功能&#xff1a; RandomizedSet()&#xff1a;初始化數據結構。bool insert(int val)&#xff1a;當元素 val 不存在時&#xff0c;插入該元素并返回 true&#xff1b;若已…

前端開發的面試自我介紹與準備

前端面試自我介紹不知道怎么說的&#xff0c;直接參考下面的模板&#xff0c;然后換成你的經歷 自我介紹控制在1分鐘左右&#xff0c;千萬不要說的太久&#xff0c;面試官會煩的&#xff0c;但是又不好意思打斷你 切記面試是人和人面對面的交流&#xff0c;要有&#xff0c;面試…

10、系統規劃與分析

一、系統規劃步驟系統規劃步驟對現有系統進行初步調查分析和確定系統目標分析子系統的組成和基本功能擬定系統的實施方案擬定系統的可行性研究指定系統建設方案系統規劃階段的產出物&#xff1a;可行性研究報告、系統設計任務書。習題1、擬定系統的實施方案是在系統規劃階段完成…

Nginx學習筆記(六)—— Nginx反向代理

&#x1f4da;Nginx學習筆記&#xff08;六&#xff09;—— Nginx反向代理 &#x1f4cc; 一、反向代理核心概念 本質原理&#xff1a; #mermaid-svg-UkFRDp2Ut7MK5T2N {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-s…

三伍微電子GSR2406 IoT FEM 2.4G PA 射頻前端模組芯片

三伍微電子GSR2406 IoT FEM 2.4G PA 射頻前端模組芯片規格書Product Description The GSR2406 is a high-performance, fully integrated RF front-end module (FEM) designed for Zigbee technology, Thread, and Bluetooth (including low energy) applications. The GSR2406…

開發避坑指南(24):RocketMQ磁盤空間告急異常處理,CODE 14 “service not available“解決方案

異常信息 Caused by: org.apache.rocketmq.client.exception.MQBrokerException: CODE: 14 DESC: service not available now, maybe disk full, CL: 0.94 CQ: 0.94 INDEX: 0.94, maybe your broker machine memory too small.異常背景 一個項目里面用到了rocketmq&#x…

開源WAF新標桿:雷池SafeLine用語義分析重構網站安全邊界

文章目錄前言【視頻教程】1.安裝Docker2.本地部署SafeLine3.使用SafeLine4.cpolar內網穿透工具安裝5.創建遠程連接公網地址6.固定Uptime Kuma公網地址前言 當個人或企業站點上線后面臨的首要威脅往往來自網絡攻擊——據統計&#xff0c;超過60%的Web應用漏洞利用嘗試在流量到達…

Mac M1探索AnythingLLM+SearXNG

SearXNG 能聚合來自多達 200 多個搜索服務&#xff0c;可私有化部署&#xff0c;并提供了靈活自定義選項。 AnythingLLMSearXNG&#xff0c;剛好能解決AnythingLLM因為網絡限制導致web search不可用的問題。 1 安裝docker 下載mac m1版本的docker并安裝。 https://docs.dock…