日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

QT系统性总结(推荐新手看)

發(fā)布時(shí)間:2024/10/14 windows 72 豆豆
生活随笔 收集整理的這篇文章主要介紹了 QT系统性总结(推荐新手看) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文地址::

相關(guān)文章

1、關(guān)于QT的系統(tǒng)總結(jié)----http://www.cnblogs.com/wangqiguo/p/4625611.html

?

源地址:http://www.cnblogs.com/wangqiguo/p/4625611.html

閱讀目錄

  • 編譯環(huán)境與開(kāi)發(fā)流程
  • QT項(xiàng)目的構(gòu)成及原理
  • QT中的布局
  • QT中的通用控件
  • QVariant 類型
  • QComboBox控件
  • QTableWidget控件
  • QTabWidget控件
  • QWebview控件
  • 使用QSS
  • 編碼問(wèn)題
  • QT的內(nèi)存管理
  • QT的信號(hào)槽
  • QT中繪圖
  • QT的線程
  • QT中使用第三方的dll
  • QT中為控件添加右鍵菜單的方法
  • 結(jié)束語(yǔ)

?

回到頂部

編譯環(huán)境與開(kāi)發(fā)流程

開(kāi)發(fā)QT有兩種IDE可以使用,一種是使用 VS + Qt 的插件,另一種就是使用QtCreator工具。前一種是微軟的工具,用的都比較多容易上手,缺點(diǎn)是信號(hào)槽的支持不太好,需要手寫,不能自動(dòng)生成,另外可能有中文編碼的問(wèn)題。后一種是Qt的官方IDE,智能提示與調(diào)試功能不如VS強(qiáng)大,但是是跨平臺(tái)的IDE,其QtDesigner設(shè)計(jì)UI界面操作比較方便,并且由于是QT官方的IDE,對(duì)編碼等支持都比較好,里面集成了Qt的幫助文檔。不得不說(shuō)Qt的幫助文檔做的是非常好的,集成進(jìn)QtCreator環(huán)境之后更加方便。

我開(kāi)發(fā)的時(shí)候使用的是QtCreator開(kāi)發(fā),目前除了調(diào)試功能比VS差以外,其他的用的比較順手,QtCreator是跨平臺(tái)的,ubuntu上也是可以使用,打開(kāi)之后界面如下:

下面將對(duì)QtCreator的界面各個(gè)功能進(jìn)行大致的介紹:

我們建立一個(gè)示例項(xiàng)目,選擇“文件”—“新建文件或項(xiàng)目”—“應(yīng)用程序”—“QT Widgets Application”選擇之后都選擇默認(rèn)設(shè)置,根據(jù)提示,就得到了一個(gè)項(xiàng)目,我們的UI是一個(gè)基于QMainWindow的類,默認(rèn)提供菜單欄,狀態(tài)欄。如果不需要這些,可以建立一個(gè)基于QWidget的UI類,項(xiàng)目如圖所示:

回到頂部

QT項(xiàng)目的構(gòu)成及原理

將項(xiàng)目切換到編輯模式,如下:

這個(gè)項(xiàng)目中一共有4個(gè)文件,入口文件main.cpp、mainwindow.ui文件、mainwindow.h和mainwindow.cpp后臺(tái)源文件,在main函數(shù)中直接調(diào)用MainWindow類的show()方法顯示主界面,那么我們切換到UI的設(shè)計(jì)視圖(雙擊項(xiàng)目中的mainwindow.ui文件),在主界面上添加兩個(gè)控件:

我們看一下MainWindow.cpp的代碼里面應(yīng)該如何操作界面上的控件:

我們使用的是ui->txtName->text();這樣的語(yǔ)句,也就是說(shuō)并不是像在C#中一樣在后臺(tái)代碼中直接可以通過(guò)類似this->txtName->text()的語(yǔ)句去訪問(wèn)界面上的控件對(duì)象,而MainWindow類中有一個(gè)成員變量是ui,其類型是Ui::MainWindow,通過(guò)這個(gè)ui成員去訪問(wèn)界面上的元素,那么這些界面控件是如何初始化的呢? 我們需要查看ui成員變量的類型Ui::MainWindow的實(shí)現(xiàn),注意Ui::Mainwindow類與MainWindow類是不同的兩個(gè)類,Ui::MainWindow類是在命名空間Ui下的類,而MainWindow是沒(méi)有命名空間的,我們?cè)趍ainwindow.h中可以看到:

MainWindow中的私有成員變量ui實(shí)際上是Ui::MainWindow類型的指針,那么Ui::MainWindow是如何定義的呢? 用鼠標(biāo)點(diǎn)進(jìn)去就看到了:

從這里就可以看出為什么我們的MainWindow類的構(gòu)造函數(shù)中一進(jìn)來(lái)就調(diào)用ui->setupUi(this)去初始化界面了

回到頂部

QT中的布局

QT中有四種布局方式,分別是:Vertical垂直布局、Horizontal水平布局、Grid布局、Form布局,效果如下:

其實(shí)Grid布局感覺(jué)跟HTML中的Table差不多,Form布局好像也是表格的效果,至于這兩種布局的差異在哪里我也不是很清楚,項(xiàng)目中基本沒(méi)有用過(guò)這兩種布局方式,一般而言所有的效果都可以通過(guò)水平布局和垂直布局嵌套實(shí)現(xiàn)。結(jié)合水平布局和垂直布局,以及他們之間的相互嵌套,再結(jié)合使用自動(dòng)伸縮調(diào)節(jié)的占位控件HorizontalSpacer和VerticalSpacer就可以實(shí)現(xiàn)非常復(fù)雜的布局效果。

一般使用布局有兩種方式,第一種即拖放這些布局控件到UI界面上,然后將希望布局的子控件拖放到這些布局控件中,但是這種方式個(gè)人認(rèn)為不夠靈活,特別是在控件之間希望嵌套的時(shí)候,工具箱中的布局控件如下:

另外一種使用方式,QT的容器控件(那些能夠放子控件的控件)都可以為其指定一種布局方式,當(dāng)為一個(gè)容器控件指定布局方式之后,該容器控件就會(huì)以這種布局方式來(lái)約束其所有子控件,直接在Qt設(shè)計(jì)器的容器控件中右鍵就可以設(shè)置:

我們?cè)谝粋€(gè)QFrame控件中放入兩個(gè)子控件,一個(gè)文本框一個(gè)按鈕,之后在QFrame的空白處右鍵單擊,在其右鍵菜單“布局”的子菜單中就可以指定該控件的布局模式了。實(shí)際上在代碼上的原理是一樣的,我們?cè)赒tCreator生成的ui_mainwindow.h中可以看到關(guān)于frame以及子控件和其布局設(shè)置的代碼:

可以看到是這么樣的關(guān)系,QFrame的子控件QPushButton以及QLineEdit(文本框)在構(gòu)造的時(shí)候指定的父對(duì)象就是frame,而布局對(duì)象QHBoxLayout指定的父控件對(duì)象也是frame,也就是說(shuō)除了我們?cè)诮缑嫔峡吹降陌粹o,文本框是frame的子控件以外,我們通過(guò)右鍵生成的布局對(duì)象(QtCreator自動(dòng)生成的,其對(duì)象id也是自動(dòng)生成的),也是frame的子控件,QHBoxLayout通過(guò)addWidget函數(shù)將frame的所有直接子控件添加到布局中進(jìn)行布局。而我們?cè)诠ぞ呦渲型蟿?dòng)布局控件到頂級(jí)窗口UI界面之后,實(shí)際上QtCreator自動(dòng)生成了一個(gè)QWidget作為該布局控件的容器,并且自動(dòng)生成的這個(gè)QWidget的父控件就是頂級(jí)的MainWindow窗口。也就是說(shuō)我們每往UI界面上拖放一個(gè)布局控件,那么QtCreator會(huì)為該布局控件自動(dòng)生成一個(gè)QWidget作為該布局控件的容器(也就是父控件),并且該自動(dòng)生成的QWidget的父控件就是布局控件被拖動(dòng)到的位置所在的直接容器。例如:

當(dāng)選定一個(gè)布局控件(如果該布局控件是從工具箱拖放到UI上的,則其在UI設(shè)計(jì)器上是可以看到的),或者是選擇一個(gè)容器控件的時(shí)候(如果該容器控件已經(jīng)通過(guò)右鍵的方式指定了布局方式)。這兩種情況下在QtCreator的屬性欄上就可以看到布局的相關(guān)屬性:

如果是從工具箱中拖放的布局控件,那么其屬性中的Margin默認(rèn)都是0 ,如果是通過(guò)右鍵為容器控件指定的布局,那么該布局的Margin默認(rèn)是9,所以這種方式下可以看到如果此時(shí)相容器控件中添加子控件,那么子控件與容器控件之間是有間隙的,除非將這里的屬性手工改為0,layoutSpacing參數(shù)對(duì)于這兩種方式產(chǎn)生的布局默認(rèn)值都是6,表示該布局中的子控件之間的間隔是6

回到頂部

QT中的通用控件

QT中最常用的控件QPushButton(按鈕)、QLineEdit(文本框)、QRadioButton(單選框)、QCheckBox(復(fù)選框)、QFrame(一般用作容器控件,配合布局)、QProgressBar(進(jìn)度條控件)這些控件的使用方法都非常簡(jiǎn)單,查一下幫助文檔就可以搞定,下面的章節(jié)中,我們會(huì)講解另外的一些控件的常用但是卻不是很容易找到的功能。

回到頂部

QVariant 類型

再講解其他控件之前,我們需要先了解Qt中的QVariant類型,為什么呢,因?yàn)樾枰獮榭丶壎〝?shù)據(jù),就離不開(kāi)對(duì)QVariant類型的了解,下面章節(jié)中我們要說(shuō)到的一些控件,在綁定數(shù)據(jù)的時(shí)候就會(huì)使用QVariant類型。他除了可以包裹Qt中常見(jiàn)的QString,int等類型之外,還可以包裹自定義的類對(duì)象。該類型提供了一系列的構(gòu)造函數(shù)以及轉(zhuǎn)換函數(shù)來(lái)攜帶常見(jiàn)類型的數(shù)據(jù),和轉(zhuǎn)換到常見(jiàn)類型數(shù)據(jù)的方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

QVariant(int?val)

QVariant(uint val)

QVariant(qlonglong val)

QVariant(qulonglong val)

QVariant(bool?val)

QVariant(double?val)

QVariant(float?val)

QVariant(const?char?* val)

QVariant(const?QString & val)

QVariant(const?QDate & val)

QVariant(const?QTime & val)

QVariant(const?QDateTime & val)

?

bool????toBool()?const

QByteArray? toByteArray()?const

QChar?? toChar()?const

QDate?? toDate()?const

QDateTime?? toDateTime()?const

double??toDouble(bool?* ok = 0)?const

float???toFloat(bool?* ok = 0)?const

int?toInt(bool?* ok = 0)?const

QJsonArray? toJsonArray()?const

qlonglong?? toLongLong(bool?* ok = 0)?const

QString toString()?const

QTime?? toTime()?const

uint??? toUInt(bool?* ok = 0)?const

qulonglong? toULongLong(bool?* ok = 0)?const

這只是其中的一部分,其實(shí)還包括了一些畫圖相關(guān)的類型的封裝,例如QPoint,QRect等,當(dāng)然Qt提供的是使用頻率很高的常見(jiàn)的類型,有時(shí)候我們需要綁定自己定義的類對(duì)象,例如實(shí)體類:

1

2

3

4

5

6

//設(shè)置

MyClass myclass;

QVariant courseModelVariant=QVariant::fromValue(myclass);

?????

//獲取

myclass = courseModelVariant.value<MyClass>();

這樣我們就可以使用QVariant攜帶任意數(shù)據(jù)類型了

回到頂部

QComboBox控件

下拉列表框控件最常見(jiàn)的功能需求就是為該控件添加下拉項(xiàng)目,并且為每個(gè)下拉項(xiàng)目添加對(duì)應(yīng)的自定義隱藏?cái)?shù)據(jù),例如在下拉列表中每一項(xiàng)上面顯示的文字描述是給用戶看的,然而在程序中,我們可能需要該項(xiàng)目對(duì)應(yīng)的隱藏?cái)?shù)據(jù),例如ID甚至是自定義的對(duì)象。

QComboBox類使用QComboBox::addItem(const QString &atext, const QVariant &auserData)成員函數(shù)為下拉列表添加項(xiàng)目,第一個(gè)參數(shù)text表示顯示在下拉項(xiàng)中的文字,而第二個(gè)參數(shù)我們可以利用來(lái)為該項(xiàng)綁定自定義的數(shù)據(jù),其類型為QVariant類型。我們可以通過(guò)QVariant類型方便的為該下拉項(xiàng)關(guān)聯(lián)任意自定義的數(shù)據(jù)類型。

在獲取數(shù)據(jù)的時(shí)候,通過(guò)QComboBox:: currentData(int role = Qt::UserRole)函數(shù)獲取當(dāng)前選中下拉項(xiàng)關(guān)聯(lián)的QVariant類型的數(shù)據(jù),也可以通過(guò)QComboBox:: itemData(int index, int role = Qt::UserRole)獲取指定下拉項(xiàng)的關(guān)聯(lián)數(shù)據(jù)。通過(guò)currentText()、itemText(int index)可以獲取下拉項(xiàng)上顯示的文本。

回到頂部

QTableWidget控件

QTableWidget是Qt中的表格顯示控件,與C#中的Grid、GridView類似,主要是用來(lái)綁定數(shù)據(jù)。在UI設(shè)計(jì)界面中選中該控件之后可以在屬性欄對(duì)控件的屬性進(jìn)行設(shè)置,最常用的屬性有如下:

focusPolicy 焦點(diǎn)策略,如果設(shè)置為NoFocus可以去掉單擊時(shí)候現(xiàn)實(shí)的單元格的虛線框
contextMenuPolicy 可以設(shè)置右鍵菜單
frameShape 設(shè)置外邊框,一般設(shè)置為NoFrame去掉邊框
editTriggers觸發(fā)單元格的編輯狀態(tài),值NoEditTriggers表示不觸發(fā)編輯狀態(tài)
selectionMode選擇模式,值ExtendedSelection表示多選
selectionBehavior選擇行為,值SelectRows按行選擇
showGrid是否顯示網(wǎng)格線
rowCount行數(shù)
columnCount列數(shù)
horizontalHeaderVisible是否顯示水平表頭
verticalHeaderVIsible是否顯示垂直表頭
verticalScrollBarPolicy設(shè)置垂直滾動(dòng)條策略
horizontalScrollBarPolicy設(shè)置水平滾動(dòng)條策略

另外的一些比較實(shí)用的功能代碼:
在單元格中添加控件:

1

2

3

4

QComboBox *comBox =?new?QComboBox();

comBox->addItem("F");

comBox->addItem("M");

ui->qtablewidget->setCellWidget(0,3,comBox);//這里不是setItem而是setCellWidget

為單元格添加checkBox:

1

2

3

4

5

6

QTableWidgetItem *item =?new?QTableWidgetItem();

//設(shè)置item的check狀態(tài)的時(shí)候,item會(huì)自動(dòng)變成QCheckBox的樣子,

//不必通過(guò)setCellWidget專門插入QCheckBox控件

//通過(guò)item->checkState()可以獲取該item是否勾選

item->setCheckState(Qt::Unchecked);

ui->tableWidgetCourseList->setItem(rowIndex, columnIndex, item);

單元格中顯示字符串:

1

2

QTableWidgetItem *item =?new?QTableWidgetItem(QString("xx"));

ui->tableWidgetCourseList->setItem(rowIndex, columnIndex, item);

設(shè)置單元格關(guān)聯(lián)的自定義數(shù)據(jù):

1

2

3

4

QTableWidgetItem *item =?new?QTableWidgetItem(QString(""));

QVariant courseModelVariant=QVariant::fromValue(MyClass("xx"));

item->setData(USER_DEFINE_ROLE,courseModelVariant);

this->ui->tableWidgetCourseList->setItem(rowIndex, columnIndex, item);

獲取單元格關(guān)聯(lián)的自定義數(shù)據(jù):

1

2

QTableWidgetItem * item =?this->ui->tableWidgetCourseList->item(row,col);

Myclass model = item->data(USER_DEFINE_ROLE).value<MyClass>();

設(shè)置單元格中的文本對(duì)齊方式:

1

ui->tableWidgetCourseList->item(rowIndex, columnIndex)->setTextAlignment(Qt::AlignCenter);

通過(guò)x,y坐標(biāo)獲取所在的item對(duì)象:

1

2

3

4

QModelIndex index = ui->tableWidgetCourseList->indexAt(QPoint(x,y));

int?row = index.row();

int?col = index.column();

QTableWidgetItem * item = ui->tableWidgetCourseList->item(row,col);

設(shè)置表頭的列寬:

1

ui->tableWidgetCourseList->horizontalHeader()->resizeSection(colIndex,20);//寬20

設(shè)置列寬自適應(yīng):

1

ui->tableWidgetCourseList->horizontalHeader()->setSectionResizeMode(colIndex,QHeaderView::Stretch);

初始化表頭文本:

1

2

3

4

5

QStringList headerText;

headerText.append("列1");

headerText.append("列2");

headerText.append("列3");

ui->tableWidgetCourseList->setHorizontalHeaderLabels(headerText);

為表頭添加復(fù)選框按鈕:

在表頭上添加復(fù)選框不能通過(guò)在表頭單元格中添加QCheckBox的方式實(shí)現(xiàn),必須進(jìn)行重繪,下面的代碼是我們自定義的表頭類
myqheaderview.h的內(nèi)容:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//該類實(shí)現(xiàn)自定義的表頭,主要是為了在表頭中加入CheckBox控件

class?MyQHeaderView :?public?QHeaderView

{

????Q_OBJECT

public:

????explicit?MyQHeaderView(Qt::Orientation orientation, QWidget *parent = 0);

?

????void?setChecked(bool?checked);

?

signals:

????void?headCheckBoxToggled(bool?checked);

?

protected:

????void?paintSection(QPainter *painter,?const?QRect &rect,?int?logicalIndex)?const;

????void?mousePressEvent(QMouseEvent *event);

?

private:

????QRect checkBoxRect(const?QRect &sourceRect)?const;

?

????bool?m_isOn;

};

myqheadview.cpp的內(nèi)容:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

MyQHeaderView::MyQHeaderView(Qt::Orientation orientation, QWidget *parent)

????: QHeaderView(orientation, parent)

????, m_isOn(false)

{

????// set clickable by default

????setChecked(false);

}

?

void?MyQHeaderView::setChecked(bool?checked)

{

????if?(isEnabled() && m_isOn != checked)

????{

????????m_isOn = checked;

????????updateSection(0);

????????emit headCheckBoxToggled(m_isOn);

????}

}

?

void?MyQHeaderView::paintSection(QPainter *painter,?const?QRect &rect,?int?logicalIndex)?const

{

????painter->save();

????QHeaderView::paintSection(painter, rect, logicalIndex);

????painter->restore();

????if?(logicalIndex == 0)

????{

????????QStyleOptionButton option;

????????if?(isEnabled())

????????????option.state |= QStyle::State_Enabled;

????????option.rect = checkBoxRect(rect);

????????if?(m_isOn)

????????????option.state |= QStyle::State_On;

????????else

????????????option.state |= QStyle::State_Off;

????????style()->drawControl(QStyle::CE_CheckBox, &option, painter);

????}

}

?

void?MyQHeaderView::mousePressEvent(QMouseEvent *event)

{

????if?(isEnabled() && logicalIndexAt(event->pos()) == 0)

????{

????????m_isOn = !m_isOn;

????????updateSection(0);

????????emit headCheckBoxToggled(m_isOn);

????}

????else?QHeaderView::mousePressEvent(event);

}

?

QRect MyQHeaderView::checkBoxRect(const?QRect &sourceRect)?const

{

????QStyleOptionButton checkBoxStyleOption;

????QRect checkBoxRect = style()->subElementRect(QStyle::SE_CheckBoxIndicator,

?????????????????????????????????????????????????&checkBoxStyleOption);

????QPoint checkBoxPoint(sourceRect.x()+5,

?????????????????????????sourceRect.y() +

?????????????????????????sourceRect.height() / 2 -

?????????????????????????checkBoxRect.height() / 2);

????return?QRect(checkBoxPoint, checkBoxRect.size());

}

使用自定義表頭:

1

2

MyQHeaderView*myHeader=new?MyQHeaderView(Qt::Horizontal, ui->tableWidgetCourseList);

ui->tableWidgetCourseList->setHorizontalHeader(myHeader);

為QTableWidget添加一行數(shù)據(jù)實(shí)際上是根據(jù)行數(shù)和列數(shù),循環(huán)QTableWidget的所有單元格,對(duì)每個(gè)單元格item設(shè)置數(shù)據(jù)來(lái)實(shí)現(xiàn)的。

回到頂部

QTabWidget控件

該控件類就是一個(gè)選項(xiàng)卡控件,有多個(gè)tab頁(yè),下面是一些實(shí)用的方法:

切換到tab:

1

ui->tabWidgetExportEdit->setCurrentIndex(tabIndex);

移除選項(xiàng)卡:

1

ui->tabWidgetExportEdit->removeTab(tabIndex);

關(guān)于選項(xiàng)卡控件的操作不多,重要的是怎么美化控件的顯示,QSS將會(huì)作為單獨(dú)的一篇文章來(lái)講解如何美化Qt中的各種控件。

回到頂部

QWebview控件

該控件是用于在Qt中顯示網(wǎng)頁(yè)的控件,一般而言會(huì)將contextMenuPolicy屬性設(shè)置為NoContextMenu隱藏系統(tǒng)為其提供的默認(rèn)右鍵菜單

<1>. 加載網(wǎng)頁(yè):

1

2

3

ui->webViewCut->load(QUrl("http://www.baidu.com"));

//如果是本地網(wǎng)頁(yè),必須使用file:///的前綴作為網(wǎng)頁(yè)地址

ui->webViewCut->load(QUrl("file:///c:/test.html?"));

<2>. Qt代碼中調(diào)用QWebview加載的網(wǎng)頁(yè)中的js函數(shù):

1

2

3

4

5

6

7

8

9

10

//先作如下設(shè)置

ui->webViewCut->page()->setForwardUnsupportedContent(true);

ui->webViewCut->page()->settings()->setAttribute(QWebSettings::JavascriptEnabled,?true);

ui->webViewCut->page()->settings()->setAttribute(QWebSettings::PluginsEnabled,?true);

ui->webViewCut->page()->settings()->setAttribute(QWebSettings::JavaEnabled,?true);

ui->webViewCut->page()->settings()->setAttribute(QWebSettings::AutoLoadImages,?true);

?

//然后在QWebview的loadFinished槽函數(shù)中調(diào)用js,該槽函數(shù)表示網(wǎng)頁(yè)已經(jīng)加載完畢

QString js = QString("alert(\'hello Qt!\')");

ui->webViewCut->page()->mainFrame()->evaluateJavaScript(js);

<3>. 在QWebview加載的html的js代碼中調(diào)用Qt的函數(shù):

默認(rèn)情況下在QwebViewCut中的網(wǎng)頁(yè)里面的js不能直接調(diào)用Qt中的相關(guān)功能,這涉及到安全性問(wèn)題。要滿足js中調(diào)用Qt的功能必須滿足下面的條件:

在Qt中暴露一個(gè)對(duì)象給js,然后js就可以在網(wǎng)頁(yè)中直接使用這個(gè)對(duì)象以及該對(duì)象的[特定]函數(shù),要求是被暴露Qt對(duì)象必須繼承自QObject類,并且在js中調(diào)用這個(gè)暴露的對(duì)象的成員函數(shù)的定義是有要求的,該對(duì)象的滿足下面的要求的成員函數(shù)都可以直接被js調(diào)用:

1.必須是該對(duì)象的公共函數(shù),并且在函數(shù)聲明前面添加Q_INVOKABLE修飾,例如:

1

2

public?:

?Q_INVOKABLE?int?TestQt();

2.如果該函數(shù)被聲明成一個(gè)public slot 也可以不添加Q_INVOKABLE修飾:

1

2

public?slots:

??void?TestQt();

個(gè)人認(rèn)為第一種方法更好,因?yàn)榭梢栽O(shè)置返回值,而Qt的槽函數(shù)是沒(méi)有返回值的,都是返回void,只需要調(diào)用this->ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject("QtObj", this);?就可以將一個(gè)Qt對(duì)象,也就是這里傳遞的this代表的對(duì)象,當(dāng)然也可以直接傳遞其他對(duì)象指針,暴露給網(wǎng)頁(yè)中的javascript,網(wǎng)頁(yè)中的javascript在調(diào)用的時(shí)候可以直接使用 QtObj 去引用我們的Qt對(duì)象,以及通過(guò)QtObj去直接調(diào)用符合條件的Qt對(duì)象的成員函數(shù)。

那么this->ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject("QtObj", this);代碼在什么時(shí)候執(zhí)行呢? 推薦是在QWebFrame的信號(hào)javaScriptWindowObjectCleared發(fā)出的時(shí)候執(zhí)行,所以我們可以在當(dāng)前UI界面類的構(gòu)造函數(shù)中添加下面的代碼:

1

2

connect(ui->webViewCut->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),

????this, SLOT(populateJavaScriptWindowObject()));

然后在處理javaScriptWindowObjectCleared()信號(hào)的槽函數(shù)中實(shí)現(xiàn)上述暴露功能:

1

2

3

4

void?MainWindow::populateJavaScriptWindowObject()

{

???ui->webViewCut->page()->mainFrame()->addToJavaScriptWindowObject("QtObj",?this);

}

根據(jù)Qt文檔上對(duì)該信號(hào)的描述javaScriptWindowObjectCleared()這個(gè)信號(hào)會(huì)在我們調(diào)用QwebViewCut::load()加載新的url之前就觸發(fā),我們?cè)谶@個(gè)時(shí)候去處理這個(gè)信號(hào),將我們需要暴露的Qt對(duì)象暴露給即將載入的網(wǎng)頁(yè)

<4>. 將Qt的屬性暴露出去供js調(diào)用,使用如下方法:

1

Q_PROPERTY(int?Qtvalue READ testValue WRITE setTestValue)

將上面的語(yǔ)句加入到類的聲明中,在private塊下面就可以,最后不需要以分號(hào)結(jié)尾,例如:

1

2

private:

?Q_PROPERTY(int?Qtvalue READ testValue WRITE setTestValue)

這一行的作用是將屬性 Qtvalue 注冊(cè)到Qt的元對(duì)象系統(tǒng)中,在js中可以通過(guò)名字Qtvalue來(lái)訪問(wèn)該屬性,但在js中訪問(wèn)該屬性的時(shí)候假設(shè)Qt暴露給js的對(duì)象為QtObj,那么在js中可以這樣訪問(wèn)該屬性:

1

2

QtObj.Qtvalue = 10;?//設(shè)置該屬性的時(shí)候會(huì)調(diào)用void setTestValue(int)

alert(QtObj.Qtvalue)?//獲取該屬性的時(shí)候會(huì)調(diào)用 int testValue()

Q_PROPERTY(int Qtvalue READ testValue WRITE setTestValue)的結(jié)構(gòu)如下:

1

2

Q_PROPERTY( 類型?? 屬性名??? READ???? 返回屬性值的函數(shù)??? WRITE???? 設(shè)置屬性值的函數(shù) )

????????????int???Qtvalue???????????int?testValue()??????????void?setTestValue(int)

也就是說(shuō)在js中我們可以直接使用Qtvalue,當(dāng)獲取Qtvalue的值的時(shí)候會(huì)自動(dòng)調(diào)用暴露對(duì)象的 int testValue() 函數(shù) ,Qt規(guī)定其返回值必須與Q_PROPERTY語(yǔ)句中指定的類型相同,并且必須沒(méi)有參數(shù)。當(dāng)我們?yōu)镼tvalue設(shè)置值的時(shí)候會(huì)調(diào)用暴露對(duì)象的void setTestValue(int)函數(shù),該函數(shù)必須有一個(gè)int類型的參數(shù)(類型也必須與前面Q_PROPERTY語(yǔ)句中指定的類型相同),并且不能有返回值。

經(jīng)過(guò)實(shí)驗(yàn)int testValue()與void setTestValue(int)函數(shù)的聲明在private區(qū)域也可以,好像無(wú)所謂。其實(shí)這兩個(gè)函數(shù)的名字是可以隨意定的,對(duì)js暴露的屬性名是Qtvalue,當(dāng)訪問(wèn)Qtvalue屬性的時(shí)候,會(huì)自動(dòng)調(diào)用Q_PROPERTY聲明中READ后面指定的函數(shù)去獲取值,并且調(diào)用WRITE后面指定的函數(shù)去設(shè)置值,而不在乎這兩個(gè)函數(shù)的名字。

另外這兩個(gè)函數(shù)獲取的值或者設(shè)置的值從哪里得來(lái)呢,我們可以在Qt對(duì)象中定義一個(gè)私有變量來(lái)保存這個(gè)值,而這個(gè)私有變量的名字是無(wú)所謂的,甚至如果需要的話,我們也不必保存這個(gè)值,直接在函數(shù)testValue里面返回一個(gè)常量值,也就是說(shuō)是否應(yīng)該定義一個(gè)私有變量來(lái)保存Qtvalue相關(guān)聯(lián)的屬性值,這個(gè)也不是必須的。

更多Qt QWidget與js的交互可以在Qt文檔中搜索? The Qt WebKit Bridge關(guān)鍵字,其實(shí)Q_PROPERTY并不是專用于暴露屬性給js的,Q_PROPERTY是Qt元對(duì)象系統(tǒng)的一部分。

<5>. 如果在QWebview加載的網(wǎng)頁(yè)中有Flex應(yīng)用程序,并且Qt中調(diào)用該QWebview加載的網(wǎng)頁(yè)中的js函數(shù)中需要調(diào)用flex程序暴露給js的接口,那么還需要作如下設(shè)置:

在"%appdata%\Macromedia\Flash Player\#Security\FlashPlayerTrust\"路徑下新建xxx.cfg文件,將當(dāng)前flex應(yīng)用程序所在位置(也就是swf文件所在的目錄)填寫到該文件中即可,該xxx.cfg的名字是無(wú)所謂的,隨便什么名字,在xxx.cfg文件中指定的目錄路徑中的swf文件的運(yùn)行是被信任的。xxx.cfg文件中可以指定多個(gè)目錄,每行一個(gè)。實(shí)際上%appdata%\Macromedia\Flash Player\#Security\FlashPlayerTrust\路徑下也可以有多個(gè)文件名不同的cfg文件。xxx.cfg文件中指定的目錄實(shí)際上可以直接指定為根目錄,例如swf文件的路徑是F:/xxx/yyy/zzz/test.swf,那么我們新建的xxx.cfg中的內(nèi)容的第一行可以直接指定為F:/即可。

其實(shí)FlexBuilder在建立項(xiàng)目的時(shí)候,其生成的swf所在的目錄都被添加到了%appdata%\Macromedia\Flash Player\#Security\FlashPlayerTrust\下面的flashbuilder.cfg中了,所以使用FlexBuilder調(diào)試項(xiàng)目的時(shí)候,運(yùn)行的swf都是被信任的。

回到頂部

使用QSS

QSS是Qt中的樣式表,用來(lái)定義Qt中控件的外觀,實(shí)際上QSS的語(yǔ)法與屬性大量參考了CSS,如果你有web的CSS開(kāi)發(fā)經(jīng)驗(yàn),幾乎沒(méi)有任何障礙就可以掌握QSS,QSS中的選擇器基本上與CSS中的相同,但是QSS只有幾種常用的選擇器類型。

QSS中選擇器的類型:

<1>. 類型選擇器,例如:QPushButton{} 設(shè)置所有類型是QPushButton或者繼承自QPushButton的控件的樣式。
<2>. 屬性選擇器,例如:QPushButton[flat="false"]{} 設(shè)置所有flat屬性是false的QPushButton控件的樣式。
<3>. 類選擇器,例如:.QPushButton{} 設(shè)置所有QPushButton的樣式,但是不會(huì)設(shè)置繼承自QPushButton類型的控件的樣式,QSS中的類選擇器與CSS中的含義不同,QSS中的類選擇器點(diǎn)號(hào)后面指定的類的名稱,而CSS中的類選擇器中的點(diǎn)號(hào)后面指定的是HTML標(biāo)簽中的class屬性的名稱。
<4>. ID選擇器,例如:#okButton{} 設(shè)置所有對(duì)象名(object name)為okButton的控件的樣式。
<5>. 后代選擇器,例如:QDialog QPushButton{} 設(shè)置所有QDialog中的QPushButton子控件的樣式,只要是QDialog的子控件都會(huì)應(yīng)用該樣式,包括直接或非直接的子控件。
<5>. 直接子選擇器:例如 QDialog > QPushButton{} 設(shè)置所有是QDialog直接子控件的QPushButton的樣式。
<6>. QSS支持選擇器分組,支持選擇器組合,例如:QPushButton#okButton{} 設(shè)置所有ID為okButton的QPushButton控件的樣式。#okButton,#cancelButton{} 設(shè)置id為okButton、cancelButton的控件的樣式。

那么如何在Qt中使用這些QSS設(shè)置控件的外觀呢,一般在代碼中通過(guò)調(diào)用控件對(duì)象的setStyleSheet(QString)成員函數(shù)進(jìn)行設(shè)置,參數(shù)即是QSS字符串。例如:

1

ui->btnTest->setStyleSheet("border:1px solid red;");//設(shè)置按鈕的邊框

另外我們可以將所有的QSS放到文件中,例如main.qss,然后將該文件添加到Qt的資源文件中,在主UI界面中加載該main.qss文件,并調(diào)用主UI界面類的成員函數(shù)設(shè)置其下控件的樣式:

1

2

3

4

5

6

QFile file(":/qss/main.qss");

file.open(QFile::ReadOnly);

QTextStream filetext(&file);

QString stylesheet = filetext.readAll();

this->setStyleSheet(stylesheet);

file.close();

要注意的是main.qss中設(shè)置的樣式應(yīng)該是針對(duì)當(dāng)前UI界面上的控件的,也就是這里調(diào)用的this->setStyleSheet(stylesheet);中的this就是當(dāng)前UI界面的類的實(shí)例。

有關(guān)QSS的細(xì)節(jié)很多,而且每個(gè)控件的美化技巧不同,同時(shí)QSS中還提供了偽類,子控件樣式等功能,限于篇幅,本節(jié)只做一個(gè)大致的介紹,后面將會(huì)單獨(dú)一篇文章詳細(xì)講解QSS的細(xì)節(jié),以及如何美化Qt中的各種常見(jiàn)控件。

回到頂部

編碼問(wèn)題

之前在寫Qt程序的時(shí)候,如果在原文件中的字符串直接寫中文,例如有些地方需要彈出錯(cuò)誤或者警告的對(duì)話框提示,那么提示內(nèi)容就是中文信息,我發(fā)現(xiàn)有部分字符會(huì)出現(xiàn)亂碼,并且有時(shí)候編譯的時(shí)候會(huì)報(bào)錯(cuò):error C2001: 常量中有換行符這一般是編碼問(wèn)題。我是這么解決的,在包含中文(即使是注釋中有中文有時(shí)候也報(bào)錯(cuò))的源文件的開(kāi)頭加入?#pragma execution_character_set("utf-8")?這一行指定文件的編碼,同時(shí)使用UE編輯器打開(kāi)該文件,另存為UTF-8的編碼,在QtCreator中重新打開(kāi)即可。遇到跟我同樣問(wèn)題的人也可以試一下這個(gè)辦法。

回到頂部

QT的內(nèi)存管理

這一小節(jié)說(shuō)題目命名為QT的內(nèi)存管理,題目有點(diǎn)過(guò)大,其實(shí)我在寫Qt程序的時(shí)候,包括Qt的例子程序,中經(jīng)常出現(xiàn)類似如下的代碼:

1

2

3

4

5

void?MainWidget::on_btnClick()

{

????QLabel * lblMessage =?new?QLabel(“hello”,this);

????lblMessage->show();

}

似乎Qt中new出來(lái)的控件類型都只負(fù)責(zé)new不用delete的,感到很奇怪,后來(lái)經(jīng)過(guò)查資料發(fā)現(xiàn)很多人有同樣的疑問(wèn),有人給出原因是因?yàn)镼t中的所有的控件類是繼承自QObject類,如果在new的時(shí)候指定了父親(在構(gòu)造函數(shù)的參數(shù)中有parent這個(gè)參數(shù)),那么它的清理是在其父親被delete的時(shí)候被delete的。Qt不建議程序員在代碼中手工delete一個(gè)QObject,如果一定要這么做,需要使用QObject的deleteLater()函數(shù),否則可能出現(xiàn)Qt正在一級(jí)一級(jí)的從一個(gè)父親類開(kāi)始清理下面的所有子對(duì)象的時(shí)候,程序中手工調(diào)用delete也去清理其中的子對(duì)象,那么這個(gè)時(shí)候就可能出現(xiàn)問(wèn)題,所以建議使用deleteLater()函數(shù),它會(huì)讓所有事件都發(fā)送完成之后再清理該片內(nèi)存。

回到頂部

QT的信號(hào)槽

在大多數(shù)Qt的編程中,我們通過(guò)Qt信號(hào)槽機(jī)制來(lái)對(duì)鼠標(biāo)或鍵盤在界面上的操作進(jìn)行響應(yīng)處理,例如鼠標(biāo)點(diǎn)擊按鈕的處理。Qt中的控件能夠發(fā)出什么信號(hào),在什么情況下發(fā)射信號(hào),這在Qt的文檔中有說(shuō)明,每個(gè)不同的控件能夠發(fā)射的信號(hào)種類和觸發(fā)時(shí)機(jī)也是不同的。

如何為控件發(fā)射的信號(hào)指定對(duì)應(yīng)的處理槽函數(shù)呢,我們有兩種方式,第一種是在UI設(shè)計(jì)界面上操作:

?

在按鈕控件上點(diǎn)擊右鍵,選擇“轉(zhuǎn)到槽”菜單之后彈出如下的對(duì)話框:

?

可以看到按鈕控件會(huì)發(fā)射很多信號(hào),只要選擇一個(gè)信號(hào),點(diǎn)擊OK之后就會(huì)生成對(duì)應(yīng)的槽函數(shù)對(duì)按鈕發(fā)出的該信號(hào)進(jìn)行處理

1

2

3

void?MainWindow::on_btnTest_clicked()

{

}

選擇clicked()信號(hào)之后生成的處理該信號(hào)的槽函數(shù),除了通過(guò)UI界面自動(dòng)生成槽函數(shù)的方式以外,我們還可以在代碼中自己手寫槽函數(shù),并通過(guò)QObject::connect()函數(shù)將特定對(duì)象的信號(hào)與另外一個(gè)對(duì)象的槽函數(shù)進(jìn)行連接,當(dāng)該對(duì)象的信號(hào)發(fā)射之后,會(huì)被關(guān)聯(lián)的對(duì)象的槽函數(shù)處理。例如我們可以用下面的一行代碼完成上面的功能:

1

connect(ui->btnTest,SIGNAL(clicked()),this,SLOT(on_btnTest_clicked()));

使用代碼的好處是,很多控件的信號(hào)在上面的對(duì)話框中并沒(méi)有顯示出來(lái),也就是說(shuō)上面的對(duì)話框中其實(shí)只列出了該控件對(duì)象的一部分信號(hào),另外如果我們的對(duì)象是在程序中通過(guò)代碼動(dòng)態(tài)構(gòu)建的,那么我們也就需要在代碼中為該控件的信號(hào)指定處理的槽函數(shù)了。上面的connect代碼是我們直接在UI界面類的構(gòu)造函數(shù)中寫的(當(dāng)然在任何地方都可以,并不一定要在構(gòu)造函數(shù)中),由于UI界面類也是繼承自QObject所以自然也繼承了connect函數(shù),通過(guò)connect函數(shù)我們可以將一個(gè)對(duì)象的信號(hào)與另一個(gè)對(duì)象的槽函數(shù)進(jìn)行連接,當(dāng)個(gè)該對(duì)象的信號(hào)發(fā)射的時(shí)候(信號(hào)的發(fā)射時(shí)機(jī)有可能在代碼中調(diào)用對(duì)象的某個(gè)成員函數(shù)觸發(fā),也有可能在程序的UI界面上操作鼠標(biāo),鍵盤等觸發(fā))。

另外信號(hào)與槽在通過(guò)connect函數(shù)連接的時(shí)候,其參數(shù)類型必須完全一致,否則是沒(méi)有效果的。實(shí)際上信號(hào)槽的原理,是依賴于Qt的元對(duì)象系統(tǒng),Qt的一系列的構(gòu)建工具為程序員做了很多自動(dòng)化的工作,自動(dòng)生成了一些代碼,所以使得我們看起來(lái)只需要用connect函數(shù)進(jìn)行關(guān)聯(lián)之后,在信號(hào)發(fā)射的時(shí)候(通過(guò)emit發(fā)射信號(hào)),槽函數(shù)會(huì)被自動(dòng)調(diào)用。在我們的Qt的項(xiàng)目的debug目錄下,我們往往會(huì)看到很多以moc_為前綴的cpp文件,打開(kāi)這些文件我們就可以看到該文件中的qt_meta_data_為前綴的靜態(tài)數(shù)組里面描述了信號(hào)槽的關(guān)聯(lián)信息,而在qt_static_metacall函數(shù)的實(shí)現(xiàn)中,我們可以大致看到通過(guò)一系列的case分支,對(duì)應(yīng)的槽函數(shù)被調(diào)用。如果要詳細(xì)研究Qt的信號(hào)槽的實(shí)現(xiàn)原理,可以研究QObject類的源碼,以及Qt的元對(duì)象系統(tǒng)。

槽函數(shù)被slots修飾,當(dāng)然它可以是普通的成員函數(shù)。信號(hào)被signals修飾。一個(gè)信號(hào)可以關(guān)聯(lián)多個(gè)槽函數(shù),當(dāng)信號(hào)被發(fā)射的時(shí)候,這些槽函數(shù)依次被執(zhí)行,但是執(zhí)行的順序是未知的,一個(gè)槽函數(shù)可以被多個(gè)信號(hào)關(guān)聯(lián)。一個(gè)信號(hào)也可以關(guān)聯(lián)另外一個(gè)信號(hào),當(dāng)該信號(hào)被發(fā)射的時(shí)候,與它關(guān)聯(lián)的信號(hào)也被發(fā)射。通過(guò)disconnect函數(shù)可以取消信號(hào)與槽函數(shù)之間的關(guān)聯(lián)關(guān)系。在槽函數(shù)中直接調(diào)用sender()就可以獲得觸發(fā)該槽函數(shù)的信號(hào)源對(duì)象,該函數(shù)是QObject的成員函數(shù),返回的也是一個(gè)QObject類型的指針。

另外信號(hào)槽可以在不同的線程之間使用,但是使用的時(shí)候需要注意調(diào)用connect時(shí)候指定連接的方式,不同的線程之間Qt可以通過(guò)消息隊(duì)列來(lái)實(shí)現(xiàn)信號(hào)與槽函數(shù)的關(guān)聯(lián),我經(jīng)常在UI線程中關(guān)聯(lián)另外一個(gè)工作線程的信號(hào)到UI界面類中的成員函數(shù),以便在工作線程中通過(guò)發(fā)送信號(hào)的方式來(lái)調(diào)用UI主線程中的UI界面類的成員函數(shù),來(lái)達(dá)到更新UI界面的效果。Qt中不能在工作線程中直接對(duì)UI界面控件進(jìn)行操作。有關(guān)信號(hào)的連接方式可以參考這篇文章:對(duì)信號(hào)與事件的認(rèn)識(shí)(http://blog.chinaunix.net/uid-25147458-id-3706122.html)

回到頂部

QT中繪圖

?

我們可以在Qt中繪圖,在Qt的控件上繪圖,一般是需要重寫該控件的重繪事件的,例如:

1

2

3

4

5

6

7

8

9

10

void?MovieImageWidget::paintEvent(QPaintEvent*p)

{

????QPainter painter(this);

????if(this->currentImagePath!="")

????{

????????QImage image(this->currentImagePath);

????????QRect rect(0,0,this->width(),this->height());

????????painter.drawImage(rect,image);

????}

}

在重繪事件中,我們先建立一個(gè)基于控件的QPainter對(duì)象,然后在重繪事件函數(shù)中,我們就可以利用該painter對(duì)象的一系列的繪制函數(shù)進(jìn)行繪圖操作了,繪制的圖形會(huì)在該P(yáng)ainter關(guān)聯(lián)的控件上顯示,其原點(diǎn)坐標(biāo)是從該控件的左上角開(kāi)始的。在需要的時(shí)候我們可以手工調(diào)用控件的update()函數(shù),這樣會(huì)直接觸發(fā)重繪事件進(jìn)行重繪。

QPainter類提供的一系列的draw函數(shù)可以幫助我們繪制各種各樣的圖形,這里就不再舉例說(shuō)明,可以自行查閱Qt的幫助文檔。

回到頂部

QT的線程

Qt的線程使用起來(lái)非常簡(jiǎn)單,我們首先要建立一個(gè)自定義的類(例如MyThread),繼承自QThread,并實(shí)現(xiàn)其run方法即可。在使用線程的時(shí)候直接得到MyThread的實(shí)例,調(diào)用其start()函數(shù)即可啟動(dòng)線程,線程啟動(dòng)之后會(huì)自動(dòng)調(diào)用其實(shí)現(xiàn)的run方法,該方法就是線程的執(zhí)行函數(shù),我們的線程任務(wù)就寫在這里,當(dāng)run退出之后線程基本就結(jié)束了,QThread有一個(gè)started和finished信號(hào),我們可以為這兩個(gè)信號(hào)指定槽函數(shù),在線程啟動(dòng)和結(jié)束的時(shí)候執(zhí)行一段代碼進(jìn)行資源的初始化和資源的釋放操作。

回到頂部

QT中使用第三方的dll

通過(guò)QtCreator的向?qū)Э梢苑浅7奖愕脑赒t程序中使用第三方的dll,具體步驟如下:

在項(xiàng)目上點(diǎn)擊右鍵,選擇“添加庫(kù)”菜單

選擇外部庫(kù)

指定對(duì)應(yīng)的lib文件,以及頭文件的包含路徑,設(shè)置平臺(tái)為windows,選擇庫(kù)的連接類型然后點(diǎn)擊下一步

最后點(diǎn)擊完成既可,可以看到實(shí)際上在Qt的個(gè)工程文件中,也就是pro文件中添加了如下的代碼:

1

2

3

4

5

win32: LIBS += -L$$PWD/E://trans/ -lTransAPI

INCLUDEPATH += $$PWD/E:/trans/include

DEPENDPATH += $$PWD/E:/trans/include

win32:!win32-g++: PRE_TARGETDEPS += $$PWD/E:/trans/TransAPI.lib

else:win32-g++: PRE_TARGETDEPS += $$PWD/E:/trans/libTransAPI.a

在需要使用的地方,包含頭文件之后就可以就可以直接調(diào)用庫(kù)里面的函數(shù)了,使用方式與VC中沒(méi)有區(qū)別。

回到頂部

QT中為控件添加右鍵菜單的方法

在Qt中QWidget控件以及其子類都可以添加右鍵菜單,Qt中所有界面上顯示的控件基本都繼承自QWidget控件,所以基本上Qt中的控件都可以添加右鍵菜單,下面舉例說(shuō)明為按鈕添加右鍵菜單的方法:
<1>. 在UI設(shè)計(jì)界面中選中按鈕,在屬性欄中設(shè)置其屬性contextMenuPolicy的值為CustomContextMenu(如果控件是在代碼中生成,可以通過(guò)控件對(duì)象的成員函數(shù)setContextMenuPolicy()在代碼中設(shè)置)
<2>. 在UI設(shè)計(jì)界面的按鈕上單擊右鍵,轉(zhuǎn)到槽,在彈出的對(duì)話框中選擇customContextMenuRequested(const QPoint&),單擊確定,為按鈕的該信號(hào)指定槽函數(shù),在代碼中可以通過(guò)connect手工關(guān)聯(lián)。
<3>. 在該槽函數(shù)中生成菜單代碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

void?MainWindow::on_menu_click(bool?checked)

{

????//通過(guò)sender()得到信號(hào)的發(fā)送對(duì)象,也就是哪個(gè)菜單項(xiàng)被單擊

}

?

void?MainWindow::on_btnTest_customContextMenuRequested(const?QPoint &pos)

{

????QMenu *cmenu =?new?QMenu(ui->btnTest);

????QAction *action1 = cmenu->addAction("Menu 1");

????QAction *action2 = cmenu->addAction("Menu 2");

????QAction *action3 = cmenu->addAction("Menu 3");

????connect(action1, SIGNAL(triggered(bool)),?this, SLOT(on_menu_click(bool)));

????connect(action2, SIGNAL(triggered(bool)),?this, SLOT(on_menu_click(bool)));

????connect(action3, SIGNAL(triggered(bool)),?this, SLOT(on_menu_click(bool)));

????cmenu->exec(QCursor::pos());

}

當(dāng)然這里僅僅是demo代碼,每次點(diǎn)擊右鍵的時(shí)候,我們都要重新new出菜單來(lái),這樣肯定會(huì)耗費(fèi)資源,這些菜單創(chuàng)建的代碼可以放在一個(gè)全局的函數(shù)中,只需要?jiǎng)?chuàng)建一次,但是cmenu->exec(QCursor::pos());這條語(yǔ)句是顯示菜單用的,執(zhí)行之后菜單才能顯示出來(lái),所以每次槽函數(shù)被執(zhí)行的時(shí)候都需要調(diào)用一次來(lái)呼出菜單。

最終顯示效果如下:

除了上面的方法之外,還可以通過(guò)重寫contextMenuEvent()事件來(lái)實(shí)現(xiàn)右鍵菜單,這里就不細(xì)說(shuō)了,可以自行百度。

回到頂部

結(jié)束語(yǔ)

本篇總結(jié)性的講解了Qt的諸多方面的知識(shí)點(diǎn),有些地方限于篇幅,可能需要單獨(dú)另起一篇文章進(jìn)行講解,有的是我自己也并沒(méi)有完全弄透徹怕誤人子弟。

由于公司需要開(kāi)發(fā)一個(gè)窗口程序,要求不需要安裝附帶的框架,所以.NET就被排除在外了,因?yàn)楣局坝型率褂肳PF開(kāi)發(fā)過(guò)其他的程序,界面也比較漂亮,但是工程部的同事在外面部署的時(shí)候由于安裝框架的原因經(jīng)常出現(xiàn)各種系統(tǒng)問(wèn)題。至于MFC太古老,學(xué)習(xí)周期長(zhǎng),所以也被排除,另外兩個(gè)一個(gè)是Flex AIR,一個(gè)是Qt,權(quán)衡之下還是選擇了Qt,經(jīng)過(guò)一個(gè)月的邊學(xué)邊做,效果還可以。其實(shí)Qt還是比較好學(xué)的,基本上熟練掌握了QSS的話,也可以實(shí)現(xiàn)非常好的界面效果,而且還是跨平臺(tái)的,特別是在嵌入式系統(tǒng)中,如果需要顯示界面的話,會(huì)是一個(gè)非常好的選擇。

希望這篇文章對(duì)大家有所幫助,由于篇幅比較長(zhǎng),雖然我已經(jīng)檢查過(guò),如果發(fā)現(xiàn)文字錯(cuò)誤,還希望園友不吝指正,我會(huì)及時(shí)改正。

轉(zhuǎn)載于“”

?

總結(jié)

以上是生活随笔為你收集整理的QT系统性总结(推荐新手看)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。