文章目錄
重載的信號和槽
函數指針
沒學過函數指針,這裏記錄一下:
以下內容來自:鏈接
通過一個例子說明:
#include <stdio.h>
// 函數原型
void sayHello();
//函數實現
void sayHello(){
printf("hello world\n");
}
// main函數調用
int main() {
sayHello();
}
int main() {
void (*sayHelloPtr)() = sayHello;
(*sayHelloPtr)();
}
- 這裏,關鍵字void的作用是說我們創建了一個函數指針,並讓它指向了一個返回void(也就是沒有返回值)的函數。
- 就像其他任何指針都必須有一個名稱一樣,這裏sayHelloPtr被當作這個函數指針的名稱。
- 我們用*符號來表示這是一個指針,這跟聲明一個指向整數或者字符的指針沒有任何區別。
- *sayHelloPtr兩端的括號是必須的,否則,上述聲明變成void *sayHelloPtr(),*會優先跟void結合,變成了一個返回指向void的指針的普通函數的聲明。因此,函數指針聲明的時候不要忘記加上括號,這非常關鍵。
- 參數列表緊跟在指針名之後,這個例子中由於沒有參數,所以是一對空括號()。
- 將上述要點結合起來,void (*syaHelloPtr)()的意義就非常清楚了,這是一個函數指針,它指向一個不接收參數且沒有返回值的函數。
下面這個例子有點難懂,但是很有意思
#include<iostream>
using namespace std;
void sayHello() {
printf("hello world\n");
}
int main() {
void *ptr = NULL;
ptr = sayHello;
(*(void(*)())ptr)();
}
void(*)()
是函數原型((void(*)())ptr)
是將ptr轉換爲上面的原型(*(void(*)())ptr)();
是以指定原型進行函數調用
理解上面這3步,函數指針就是:
(1)用一個指針記住函數地址,以便於後續使用
(2)需要使用時,用指定函數原型進行轉換和調用。
實際應用中,都是簡化爲直接聲明爲指定好函數原型的指針(所以叫函數指針),這樣調用時就不需要函數原型轉換了。
重載
出現了重載,需要利用函數指針明確指向函數地址,如下所示:
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QPushButton>
myWidget::myWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::myWidget)
{
ui->setupUi(this);
//創建一個老師的對象和學生的對象
this->zt = new Teacher(this);
this->st = new Student(this);
// //創建連接
// connect(zt,&Teacher::hungry,st,&Student::treat);
// //調用下課函數
// classIsOver();
void(Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
void(Student:: *studentSlot)(QString) = &Student::treat;
connect(zt,teacherSignal,st,studentSlot);
classIsOver();
}
myWidget::~myWidget()
{
}
void myWidget::classIsOver(){
emit zt->hungry("宮保雞丁");
}
QString轉化爲char*
1.使用toUtf8()轉化成QByteArray
2.使用.Data()轉化爲char*
信號觸發信號
按鈕連接信號
QPushButton * btn = new QPushButton("下課",this);
connect(btn,&QPushButton::clicked,this,&myWidget::classIsOver);
信號連接信號
1、信號是可以連接信號
2、一個信號可以連接多個槽函數
3、多個信號可以連接同一個槽函數
4、信號和槽函數的參數必須類型一一對應5、信號和槽的參數個數是不是要一致?信號的參教個數可以多餘槽函數的參數個數
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QPushButton>
myWidget::myWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::myWidget)
{
ui->setupUi(this);
//創建一個老師的對象和學生的對象
this->zt = new Teacher(this);
this->st = new Student(this);
QPushButton * btn = new QPushButton("下課",this);
void(Teacher:: *teacherSignal)(void) = &Teacher::hungry;
void(Student:: *studentSlot)(void) = &Student::treat;
connect(zt,teacherSignal,st,studentSlot);
connect(btn,&QPushButton::clicked,zt,teacherSignal);
// 斷開信號disconnect(btn,&QPushButton::clicked,zt,teacherSignal);
}
myWidget::~myWidget()
{
}
void myWidget::classIsOver(){
emit zt->hungry("宮保雞丁");
}
qt中的lambda表達式
[btn](){
btn->setText("aaaa");
}();
}
- 記住=是按照值傳遞,&是按照引用傳遞。
- mutable是修飾符,可以修改按值傳遞的數據,不能修改本身。
- ->加上返回類型,代表一個返回值
總結圖
菜單欄和工具欄
#include "mainwindow.h"
#include <QMenuBar>
#include <QPushButton>
#include <QToolBar>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
resize(600,400);
//創建菜單欄,只能有一個
QMenuBar * bar = menuBar();
//將菜單欄放入窗口中
setMenuBar(bar);
//創建菜單
QMenu * fileMenu = bar->addMenu("文件");
QMenu * editMenu = bar->addMenu("編輯");
//創建菜單項
fileMenu->addAction("新建");
//添加分隔線
fileMenu->addSeparator();
fileMenu->addAction("打開");
//工具欄,可以有多個
QToolBar *localQToolBar = new QToolBar(this);
addToolBar(Qt::LeftToolBarArea,localQToolBar);
//設置只允許左右停靠
localQToolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
//設置不允許浮動
localQToolBar->setFloatable(false);
//設置移動
//toolBar->setMovable(false);
//工具欄中設置內容
localQToolBar->addAction("新建");
localQToolBar->addAction("打開");
QPushButton * btn = new QPushButton("aa",this);
localQToolBar->addWidget(btn);
}
MainWindow::~MainWindow()
{
}
效果:
狀態欄和浮動窗口
QStatusBar *localQStatusBar = new QStatusBar();
setStatusBar(localQStatusBar);
QLabel *localQLabel = new QLabel("時間",this);
localQStatusBar->addPermanentWidget(localQLabel);
//鉚接部件(浮動窗口)
QDockWidget *localQDockWidget = new QDockWidget("浮動",this);
addDockWidget(Qt::BottomDockWidgetArea,localQDockWidget);
//設置中心部件
QTextEdit *localQTextEdit = new QTextEdit(this);
setCentralWidget(localQTextEdit);
效果:
添加資源文件
流程:
- 將文件拷貝到項目目錄中
- 創建新文件,右鍵項目,點擊添加新文件Qt resource file
- res生成res.qrc
- open in editor編輯資源
- 添加前綴,添加文件
- 使用:+前綴名+文件名使用文件
模態和非模態對話框
- 模態:不可以對其它窗口進行操作
- 非模態:可以對其它窗口進行操作
非模態的建立:
//必須放在堆中,但是這樣寫有可能內存泄漏
QDialog * dlg2= new QDialog(this);
dlg2->show();
//放在棧中,不能顯示,因爲立刻就被釋放了
QDialog dlg3(this);
dlg3.show();
模態的建立和非模態的內存自動釋放:
//模態對話框自動阻塞原窗口線程
QDialog dlg(this);
dlg.resize(200,100);
dlg.exec();
new QDialog(this);
QDialog * dlg2= new QDialog(this);
dlg2->resize(200,100);
dlg2->setAttribute(Qt::WA_DeleteOnClose);
dlg2->show();
模態建立的原理就是進入消息隊列,非模態建立的原理是分配內存開闢一個線程。
消息對話框
// 錯誤對話框
QMessageBox::critical(this,"critical","錯誤");
// 消息對話框
QMessageBox::information(this,"critical","錯誤");
// 問題對話框
if(QMessageBox::Save==QMessageBox::question(this,"critical","錯誤",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Save)){
}
;
// 消息對話框
QMessageBox::warning(this,"critical","錯誤");
其它標準對話框
// 顏色對話框
QColor color = QColorDialog::getColor(QColor(255,0,0));
// 文件對話框,返回文件路徑
QFileDialog::getOpenFileName(this,"打開文件","");
// 字體對話框
bool flag;
QFontDialog::getFont(&flag,QFont("華文彩雲",36));