目錄
一、Qt 事件
1,事件的定義
2,事件的處理
3,鼠標事件
4,按鍵事件
5,定時器
6,事件分發器
7,事件過濾器
二、Qt 文件
1,輸入輸出類
2,文件讀寫類
3,文件和目錄信息類
4,示例
三、Qt 多線程
1 ,Qt 多線程概述
2 ,QThread 常用 API
3 ,使用線程
4 ,線程安全
(1) 互斥鎖:QMutex、QMutexLocker
(2) 條件變量:QWaitCondition
(3) 信號量:QSemaphore
(4) 讀寫鎖:QReadLocker、QWriteLocker、QReadWriteLock
四、Qt 網絡
1, 核心 API 概覽
2, 回顯服務器和客戶端
3, HTTP Client
五、Qt 音視頻
1,Qt 音頻
2,Qt 視頻
一、Qt 事件
1,事件的定義
事件是應用程序內部或者外部產生的事情或者動作的統稱。在 Qt 中使用一個對象來表示一個事件。所有的 Qt 事件均繼承于抽象類 QEvent。事件是由系統或者 Qt 平臺本身在不同的時刻發出的。 當用戶按下鼠標、敲下鍵盤 ,或者是窗口需要重新繪制的時候 ,都會發出一個相應的事件。
事件名稱 | 描述 |
鼠標事件 | 鼠標左鍵、 鼠標右鍵、 鼠標滾輪 , 鼠標的移動 ,鼠標按鍵的按下和松開 |
鍵盤事件 | 按鍵類型、按鍵按下、按鍵松開 |
定時器事件 | 定時時間到達 |
進入離開事件 | 鼠標的進入和離開 |
滾輪事件 | 鼠標滾輪滾動 |
繪屏事件 | 重繪屏幕的某些部分 |
顯示隱藏事件 | 窗口的顯示和隱藏 |
移動事件 | 窗口位置的變化 |
窗口事件 | 是否為當前窗口 |
大小改變事件 | 窗口大小改變 |
焦點事件 | 鍵盤焦點移動 |
2,事件的處理
事件處理?般常?的?法為:重寫相關的 Event 函數。
在 Qt 中,?乎所有的 Event 函數都是虛函數,所以可以重新實現。如:在實現?標的進?和離開事件時,直接重新實現 enterEvent() 和 leaveEvent() 即可。enterEvent() 和 leaveEvent() 函數原型如下:
3,鼠標事件
鼠標點擊
void Label::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){qDebug()<<"按下左鍵";}else if(event->button() == Qt::RightButton){qDebug()<<"按下右鍵";}// 當前 event 對象就包含了鼠標點擊的坐標qDebug() << event->x() << "," << event->y();// 以屏幕左上角為原點的坐標qDebug() << event->globalX() << "," << event->globalY();
}void Label::mouseReleaseEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){qDebug()<<"釋放左鍵";}else if(event->button() == Qt::RightButton){qDebug()<<"釋放右鍵";}
}void Label::mouseDoubleClickEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){qDebug()<<"雙擊左鍵";}else if(event->button() == Qt::RightButton){qDebug()<<"雙擊右鍵";}
}
鼠標移動和滾輪移動
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 把這個選項設置為true,才能夠追蹤鼠標位置this->setMouseTracking(true);
}void Widget::mouseMoveEvent(QMouseEvent *event)
{qDebug() << event->x() << event->y();
}void Widget::wheelEvent(QWheelEvent *event)
{qDebug() << event->delta();
}
4,按鍵事件
單鍵
void Widget::keyPressEvent(QKeyEvent *event)
{if(event->key() == Qt::Key_A){qDebug()<<"A鍵被按下";}
}
組合鍵
Qt::NoModifier | 無修改鍵 |
Qt::ShiftModifier | Shift 鍵 |
Qt::ControlModifier | Ctrl 鍵 |
Qt::AltModifier | Alt 鍵 |
Qt::MetaModifier | Meta鍵(在Windows上指Windows鍵 ,在macOS上指Command鍵) |
Qt::KeypadModifier | 使用鍵盤上的數字鍵盤進行輸入時 ,Num Lock鍵處于打開狀態 |
Qt::GroupSwitchModifier | 用于在輸入法組之間切換 |
5,定時器
Qt中的定時器分為QTimerEvent 和QTimer 這2個類。
QTimerEvent類
用來描述一個定時器事件。在使用時需要通過startTimer() 函數來開啟一個定時器,這個函數需要輸入一個以毫秒為單位的整數作為參數來表明設定的時間,它返回的整型值代表這個定時器。 當定時器溢出時(即定時時間到達)就可以在 timerEvent() 函數中獲取該定時器的編號來進行相關操作。
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 把這個選項設置為true,才能夠追蹤鼠標位置this->setMouseTracking(true);timer_id1 = startTimer(1000);timer_id2 = startTimer(2000);
}void Widget::timerEvent(QTimerEvent *event)
{if(event->timerId() == timer_id1){static int num1 = 1;// lb1每隔1秒加一次ui->label->setText(QString::number(num1++));}if(event->timerId() == timer_id2){static int num2 = 1;// lb2每隔2秒加一次ui->label_2->setText(QString::number(num2++));}
}
QTimer類
用來實現一個定時器,它提供了更高層次的編程接口,如:可以使用信號和槽,還可以設置只運行一次的定時器。
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{connect(ui->pushButton, &QPushButton::clicked,[=](){time->start(1000);});connect(time,&QTimer::timeout,[=](){static int num = 1;ui->label->setText(QString::number(num++));});connect(ui->pushButton_2, &QPushButton::clicked,[=](){time->stop();});
}
6,事件分發器
在 Qt 中,我們發送的事件都是傳給了 QObject 對象,更具體點是傳給了 QObject 對象的 event() 函數。所有的事件都會進?到這個函數??,那么我們處理事件就要重寫這個 event() 函數。event() 函數本?不會去處理事件,?是根據 事件類型(type值)調?不同的事件處理函數。
7,事件過濾器
在 Qt 中,?個對象可能經常要查看或攔截另外?個對象的事件,如對話框想要攔截按鍵事件,不讓別的組件接收到,或者修改按鍵的默認值等。通過上?的學習,我們已經知道,Qt 創建了 QEvent事件對象之后,會調?QObject 的 event()函數 處理事件的分發。顯然,我們可以在 event()函數 中實現攔截的操作。由于 event()函數是 protected 的,因此,需要繼承已有類。如果組件很多,就需要重寫很多個event()函數。這當然相當?煩,更不?說重寫 event()函數還得???堆問題。好在 Qt 提供了另外?種機制來達到這??的:事件過濾器。
二、Qt 文件
1,輸入輸出類
Qt 中,?件讀寫的類為 QFile 。QFile 的?類為 QFileDevice ,QFileDevice 提供了?件交互操作的底層功能。 QFileDevice 的?類是 QIODevice,QIODevice 的?類為 QObject 。
QIODevice 是 Qt 中所有輸?輸出設備(input/output device,簡稱 I/O 設備)的基礎類,I/O 設備就是能進?數據輸?和輸出的設備,例如?件是?種 I/O 設備,?絡通信中的 socket 是 I/O 設備,串?、藍?等通信接?也是 I/O 設備,所以它們也是從 QIODevice 繼承來的。Qt 中主要的?些 I/O 設備類的繼承關系如下圖所?
QFile 是?于?件操作和?件數據讀寫的類,使? QFile 可以讀寫任意格式文件。
QSaveFile 是?于安全保存?件的類。使? QSaveFile 保存?件時,它會先把數據寫??個臨時?件,成功提交后才將數據寫?最終的?件。如果保存過程中出現錯誤,臨時?件?的數據不會被寫?最終?件,這樣就能確保最終?件中不會丟失數據或被寫?部分數據。 在保存?較?的?件或復雜格式的?件時可以使?這個類,例如從?絡上下載?件等。
QTemporaryFile 是?于創建臨時?件的類。使?函數 QTemporaryFile::open() 就能創建?個?件名唯?的臨時?件,在 QTemporaryFile 對象被刪除時,臨時?件被?動刪除。
QTcpSocket 和 QUdpSocket 是分別實現了 TCP 和 UDP 的類。
QSerialPort 是實現了串?通信的類,通過這個類可以實現計算機與串?設備通信。
QBluetoothSocket 是?于藍?通信的類。?機和平板計算機等移動設備有藍?通信模塊,筆記本電腦?般也有藍?通信模塊。通過QBluetoothSocket類,就可以編寫藍?通信程。如編程實現筆記本電腦與?機的藍?通信。
QProcess 類?于啟動外部程序,并且可以給程序傳遞參數。
QBuffer 以?個 QByteArray 對象作為數據緩沖區,將 QByteArray 對象當作?個 I/O 設備來讀寫。
2,文件讀寫類
在 Qt 中 ,文件的讀寫主要是通過 QFile 類來實現。在 QFile 類中提供了一些用來讀寫文件的方法。對 于文件的操作主要有:
讀數據:QFile 類中提供了多個方法用于讀取文件內容;如 read()、 readAll()、 readLine()等。
寫數據:QFile 類中提供了多個方法用于往文件中寫內容;如 write()、writeData等。
關閉文件:文件使用結束后必須用函數 close() 關閉文件。
訪問一個設備之前 ,需要使用 open()函數 打開該設備 ,而且必須指定正確的打開模式 ,QIODevice 中 所有的打開模式由 QIODevice::OpenMode 枚舉變量定義 ,其取值如下:
QIODevice::NotOpen | 沒有打開設備 |
QIODevice::ReadOnly | 以只讀方式打開設備 |
QIODevice::WriteOnly | 以只寫方式打開設備 |
QIODevice::ReadWrite | 以讀寫方式打開設備 |
QIODevice::Append | 以追加方式打開設備 ,數據將寫到文件末尾 |
QIODevice::Truncate | 每次打開文件后重寫文件內容 ,原內容將被刪除 |
QIODevice::Text | 在讀文件時 ,行尾終止符會被轉換為 '\n'; 當寫入文件時 ,行尾終止符會被轉換為 本地編碼。如 Win32上為'\r\n'; |
QIODevice::Unbuffered | 無緩沖形式打開文件 ,繞過設備中的任何緩沖區 |
QIODevice::NewOnly | 文件存在則打開失敗 ,不存在則創建文件 |
3,文件和目錄信息類
QFileInfo 是 Qt 提供的一個用于獲取文件和目錄信息的類 ,如獲取文件名、文件大小、文件修改日期等。QFileInfo類中提供了很多的方法 ,常用的有:
isDir() 檢查該文件是否是目錄;
isExecutable() 檢查該文件是否是可執行文件;
fileName() 獲得文件名;
completeBaseName() 獲取完整的文件名;
suffix() 獲取文件后綴名;
completeSuffix() 獲取完整的文件后綴;
size() 獲取文件大小;
isFile() 判斷是否為文件;
fileTime() 獲取文件創建時間、修改時間、最近訪問時間等;
4,示例
class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void handleAction1();void handleAction2();private:Ui::MainWindow *ui;QPlainTextEdit* edit;
};MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);this->setWindowTitle("簡單的記事本");// 獲取到菜單欄QMenuBar* menuBar = this->menuBar();// 添加菜單QMenu* menu = new QMenu("文件");menuBar->addMenu(menu);// 添加菜單項QAction* action1 = new QAction("打開");QAction* action2 = new QAction("保存");menu->addAction(action1);menu->addAction(action2);// 指定一個輸入框edit = new QPlainTextEdit();QFont font;font.setPixelSize(20);edit->setFont(font);this->setCentralWidget(edit);// 連接QAction的信號槽connect(action1,&QAction::triggered,this,&MainWindow::handleAction1);connect(action2,&QAction::triggered,this,&MainWindow::handleAction2);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handleAction1()
{// 先彈出"打開文件"對話框,讓用戶選擇打開哪個文件QString path = QFileDialog::getOpenFileName(this);// 把文件名顯示到狀態欄里QStatusBar* statusBar = this->statusBar();statusBar->showMessage(path);// 根據用戶選擇的路徑,構造一個QFile對象,并打開文件QFile file(path);bool ret = file.open(QIODevice::ReadOnly);if(!ret){statusBar->showMessage(path + "打開失敗!");return;}// 讀取文件了QString text = file.readAll();// 關閉文件file.close();// 讀到的內容設置到輸入框中edit->setPlainText(text);
}void MainWindow::handleAction2()
{// 先彈出"保存文件"對話框QString path = QFileDialog::getSaveFileName(this);// 在狀態欄顯示這個文件名QStatusBar* statusBar = this->statusBar();statusBar->showMessage(path);// 根據用戶選擇的路徑,構造一個QFile對象,并打開文件QFile file(path);bool ret = file.open(QFile::WriteOnly);if(!ret){statusBar->showMessage(path + "打開失敗!");return;}// 寫文件const QString& text = edit->toPlainText();file.write(text.toUtf8());// 關閉file.close();
}
三、Qt 多線程
1 ,Qt 多線程概述
在 Qt 中 ,多線程的處理一般是通過 QThread類 來實現。
QThread 代表一個在應用程序中可以獨立控制的線程 ,也可以和進程中的其他線程共享數據。
QThread 對象管理程序中的一個控制線程。
2 ,QThread 常用 API
run() | 線程的入口函數. |
start() | 通過調用 run() 開始執行線程。操作系統將根據優先級參數調度線程。 如果線程已經在運行 ,這個函數什么也不做。 |
currentThread() | 返回一個指向管理當前執行線程的 QThread的指針。 |
isRunning() | 如果線程正在運行則返回true;否則返回false。 |
sleep() / msleep() /usleep() | 使線程休眠 ,單位為秒 / 毫秒 / 微秒 |
wait() | 阻塞線程 ,直到滿足以下任何一個條件: 與此 QThread 對象關聯的線程已經完成執行(即當它從run()返回時)。 如果線程已 經完成 ,這個函數將返回 true。 如果線程尚未啟動 ,它也返回 true。已經過了幾毫秒。 如果時間是 ULONG_MAX(默認值) ,那么等待永遠不會超時(線程 必須從run()返回)。 如果等待超時 ,此函數將返回 false。 這提供了與 POSIX pthread_join() 函數類似的功能。 |
terminate() | 終止線程的執行。線程可以立即終止 ,也可以不立即終止 ,這取決于操作系統的調 度策略。在terminate() 之后使用 QThread::wait() 來確保。 |
finished() | 當線程結束時會發出該信號 ,可以通過該信號來實現線程的清理工作。 |
3 ,使用線程
創建線程的步驟:
(1) 自定義一個類 ,繼承于 QThread ,并且只有一個線程處理函數(和主線程不是同一個線程) ,這個線程處理函數主要就是重寫父類中的 run() 函數。
(2) 線程處理函數里面寫入需要執行的復雜數據處理;
(3) 啟動線程不能直接調用 run() 函數 ,需要使用對象來調用 start() 函數實現線程啟動;
(4) 線程處理函數執行結束后可以定義一個信號來告訴主線程;
(5) 最后關閉線程。
Qt::AutoConnection | 在 Qt 中 ,會根據信號和槽函數所在的線程自動選擇連接類型。 如果信號和槽函 數在同一線程中 ,那么使用 Qt:DirectConnection 類型; 如果它們位于不同的 線程中 ,那么使用Qt::QueuedConnection 類型。 |
Qt::DirectConnection | 當信號發出時 ,槽函數會立即在同一線程中執行。這種連接類型適用于信號和 槽函數在同一線程中的情況 ,可以實現直接的函數調用 ,但需要注意線程安全 性。 |
Qt::QueuedConnection | 當信號發出時 ,槽函數會被插入到接收對象所屬的線程的事件隊列中 ,等待下 一次事件循環時執行。 這種連接類型適用于信號和槽函數在不同線程中的情況 ,可以確保線程安全。 |
Qt::BlockingQueuedConnec tion | 與 Qt:QueuedConnection 類似 ,但是發送信號的線程會被阻塞 ,直到槽函數執行完畢 ,這種連接類型適用于需要等待槽函數執行完畢再繼續的場景 ,但需要注意可能引起線程死鎖的風險。 |
Qt::UniqueConnection | 這是一個標志 ,可以使用位或與上述任何一種連接類型組合使用。 |
4 ,線程安全
實現線程互斥和同步常用的類有:
(1) 互斥鎖:QMutex、QMutexLocker
互斥鎖是一種保護和防止多個線程同時訪問同一對象實例的方法 ,在 Qt 中 ,互斥鎖主要是通過 QMutex類來處理。
特點:QMutex 是 Qt 框架提供的互斥鎖類 ,用于保護共享資源的訪問 ,實現線程間的互斥操作。
用途:在多線程環境下 ,通過互斥鎖來控制對共享數據的訪問 ,確保線程安全。
(2) 條件變量:QWaitCondition
在多線程編程中,假設除了等待操作系統正在執行的線程之外,某個線程還必須等待某些條件滿足才能執行 ,這時就會出現問題。這種情況下,線程會很自然地使用鎖的機制來阻塞其他線程 ,因為這只是線程的輪流使用,并且該線程等待某些特定條件 ,人們會認為需要等待條件的線程 ,在釋放互斥鎖或讀寫鎖之后進入了睡眠狀態 ,這樣其他線程就可以繼續運行。當條件滿足時,等待條件的線程將被另一個線程喚醒。
在 Qt 中 ,專門提供了 QWaitCondition類 來解決像上述這樣的問題。
特點:QWaitCondition 是 Qt 框架提供的條件變量類 ,用于線程之間的消息通信和同步。
用途:在某個條件滿足時等待或喚醒線程 ,用于線程的同步和協調。
(3) 信號量:QSemaphore
有時在多線程編程中,需要確保多個線程可以相應的訪問一個數量有限的相同資源。例如,運行程序 的設備可能是非常有限的內存 ,因此我們更希望需要大量內存的線程將這一事實考慮在內,并根據可用的內存數量進行相關操作,多線程編程中類似問題通常用信號量來處理。信號量類似于增強的互斥鎖,不僅能完成上鎖和解鎖操作, 而且可以跟蹤可用資源的數量。
特點:QSemaphore 是 Qt 框架提供的計數信號量類 ,用于控制同時訪問共享資源的線程數量。
用途: 限制并發線程數量 ,用于解決一些資源有限的問題。
(4) 讀寫鎖:QReadLocker、QWriteLocker、QReadWriteLock
特點:
QReadWriteLock 是讀寫鎖類 ,用于控制讀和寫的并發訪問。
QReadLocker 用于讀操作上鎖 ,允許多個線程同時讀取共享資源。
QWriteLocker 用于寫操作上鎖 ,只允許一個線程寫入共享資源。
用途:在某些情況下 ,多個線程可以同時讀取共享數據 ,但只有一個線程能夠進行寫操作。讀寫鎖提 供了更高效的并發訪問方式。
四、Qt 網絡
1, 核心 API 概覽
核心類有兩個:QTcpServer 和 QTcpSocket
名稱 | 類型 | 說明 | 對標原生 API |
listen(const QHostAddress&, quint16 port) | 方法 | 綁定指定的地址和端口號, 并開始監 聽. | bind 和 listen |
nextPendingConnection() | 方法 | 從系統中獲取到一個已經建立好的 tcp 連接. 返回一個 QTcpSocket , 表示這個 客戶端的連接. 通過這個 socket 對象完成和客戶端 之間的通信. | accept |
newConnection | 信號 | 有新的客戶端建立連接好之后觸發. |
QTcpSocket 用戶客戶端和服務器之間的數據交互
名稱 | 類型 | 說明 | 對標原生 API |
readAll() | 方法 | 讀取當前接收緩沖區中的所有數據. 返回 QByteArray 對象. | read |
write(const QByteArray& ) | 方法 | 把數據寫入 socket 中. | write |
deleteLater | 方法 | 暫時把 socket 對象標記為無效. Qt 會在下個事件循環中析構釋放該對 象. | 無 (但是類似于 "半自動化的 垃圾回收") |
readyRead | 信號 | 有數據到達并準備就緒時觸發. | 無 (但是類似于 IO 多路復用 中的通知機制) |
disconnected | 信號 | 連接斷開時觸發. | 無 (但是類似于 IO 多路復用 中的通知機制) |
2, 回顯服務器和客戶端
核心類是兩個:QTcpServer 和 QTcpSocket。
QTcpServer 用于監聽端口, 和獲取客戶端連接。
名稱 | 類型 | 說明 | 對標原生 API |
listen(const QHostAddress&, quint16 port) | 方法 | 綁定指定的地址和端口號, 并開始監 聽. | bind 和 listen |
nextPendingConnection() | 方法 | 從系統中獲取到一個已經建立好的 tcp 連接. 返回一個 QTcpSocket , 表示這個 客戶端的連接. 通過這個 socket 對象完成和客戶端 之間的通信. | accept |
newConnection | 信號 | 有新的客戶端建立連接好之后觸發. | 無 (但是類似于 IO 多路復用 中的通知機制) |
QTcpSocket 用戶客戶端和服務器之間的數據交互.
名稱 | 類型 | 說明 | 對標原生 API |
readAll() | 方法 | 讀取當前接收緩沖區中的所有數據. 返回 QByteArray 對象. | read |
write(const QByteArray& ) | 方法 | 把數據寫入 socket 中. | write |
deleteLater | 方法 | 暫時把 socket 對象標記為無效. Qt 會在下個事件循環中析構釋放該對 象. | 無 (但是類似于 "半自動化的 垃圾回收") |
readyRead | 信號 | 有數據到達并準備就緒時觸發. | 無 (但是類似于 IO 多路復用 中的通知機制) |
disconnected | 信號 | 連接斷開時觸發. | 無 (但是類似于 IO 多路復用 中的通知機制) |
3, HTTP Client
核心 的API,關鍵類主要有三個:
QNetworkAccessManager 和 QNetworkRequest 和 QNetworkReply
QNetworkAccessManager 提供了 HTTP 的核心操作
方法 | 說明 |
get(const QNetworkRequest& ) | 發起一個 HTTP GET 請求. 返回 QNetworkReply 對象. |
post(const QNetworkRequest& , const QByteArray& ) | 發起一個 HTTP POST 請求. 返回 QNetworkReply 對 象. |
QNetworkRequest 表示一個 HTTP 請求(不含 body)
方法 | 說明 |
QNetworkRequest(const QUrl& ) | 通過 URL 構造一個 HTTP 請求. |
setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value) | 設置請求頭. |
取值 | 說明 |
ContentTypeHeader | 描述 body 的類型. |
ContentLengthHeader | 描述 body 的長度. |
LocationHeader | 用于重定向報文中指定重定向地址. (響應中使用, 請求 用不到) |
CookieHeader | 設置 cookie |
UserAgentHeader | 設置 User-Agent |
QNetworkReply 表示一個 HTTP 響應. 這個類同時也是 QIODevice 的子類.
方法 | 說明 |
error() | 獲取出錯狀態. |
errorString() | 獲取出錯原因的文本. |
readAll() | 讀取響應 body. |
header(QNetworkRequest::KnownHeaders header) | 讀取響應指定 header 的值. |
五、Qt 音視頻
1,Qt 音頻
在 Qt 中 ,音頻主要是通過 QSound 類來實現。但是需要注意的是 QSound 類只支持播放 wav 格式的音頻文件。也就是說如果想要添加音頻效果 ,那么首先需要將非wav格式 的音頻文件轉換為 wav 格式。
示例
#include "widget.h"
#include "ui_widget.h"
#include <QSound> //添加音頻頭文件Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);//實例化對象QSound *sound = new QSound(":/1.wav",this);connect(ui->btn,&QPushButton::clicked,[=](){ sound->play(); //播放});}
2,Qt 視頻
在 Qt 中 ,視頻播放的功能主要是通過 QMediaPlayer類 和 QVideoWidget類 來實現。在使用這兩個類 時要添加對應的模塊 multimedia 和 multimediawidgets 。
示例
// widget.h#include <QWidget>
#include <QHBoxLayout> //水平布局
#include <QVBoxLayout> //垂直布局
#include <QVideoWidget> //顯示視頻
#include <QMediaPlayer> //播放聲音
#include <QPushButton> //按鈕
#include <QStyle> //設置圖標
#include <QFileDialog> //選擇文件/文件夾class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public slots:void chooseVideo();private:QMediaPlayer *mediaPlayer;QVideoWidget *videoWidget;QVBoxLayout *vbox;//創建兩個按鈕:選擇視頻按鈕和開播放按鈕QPushButton *chooseBtn,*playBtn;};// widget.cpp#include "widget.h"
#include <QMediaPlayer>
#include <QSlider>Widget::Widget(QWidget *parent): QWidget(parent)
{//對象實例化mediaPlayer = new QMediaPlayer(this);videoWidget = new QVideoWidget(this);//設置播放畫面的窗口videoWidget->setMinimumSize(600,600);//實例化窗口布局---垂直布局this->vbox = new QVBoxLayout(this);this->setLayout(this->vbox);//實例化選擇視頻按鈕chooseBtn = new QPushButton("選擇視頻 ",this);//實例化播放按鈕playBtn = new QPushButton(this);//設置圖標代替文件playBtn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay)); 64//實例化一個水平布局,將以上控件放入水平布局中QHBoxLayout *hbox = new QHBoxLayout;//添加控件hbox->addWidget(chooseBtn);hbox->addWidget(playBtn);//將播放窗口和水平布局都添加到垂直布局中vbox->addWidget(videoWidget);//布局中添加布局vbox->addLayout(hbox);//將選擇視頻對應的按鈕和槽函數進行關聯connect(chooseBtn,&QPushButton::clicked,this,&Widget::chooseVideo);
}void Widget::chooseVideo()
{//選擇視頻,返回一個播放視頻的名字QString name = QFileDialog::getSaveFileName(this,"選擇視頻",".","WMV(*.wmv)");//設置媒體聲音mediaPlayer->setMedia(QUrl(name));
}