Qt示例总结
Qt5的例子在哪里
最近剛用qt5.3.0+VS2013去開發程序,突然發現,qt以前自帶的例子咋找不到了呢?
但在安裝目錄里是有的啊,見C:\Qt\Qt5.3.0\Examples。
最后才發現貌似安裝后的開始目錄里,已經沒有了當年經常看到的《Qt Examples Launcher》快捷方式
,也沒有了這個應用程序。
qt5.3
qtcreator
1
仔細找了找,原來qt已經把所有的例子融合在qtcreator中。以前一直用VS和qt開發,沒咋用qtcreator
。
Qt5的例子在哪里?
2
打開qtcreator,在歡迎界面就能看到所有examples。它的列表展現方式也比以前更加直觀了。
========
Qt實現應用程序單實例運行--LocalServer方式
使Qt應用程序能夠單實例運行的典型實現方法是使用共享內存實現。該方法實現簡單,代碼簡潔。
但有一個致命缺陷:共享內存(QSharedMemory)實現的單程序運行,當運行環境是UNIX時,并且程序不
幸崩潰,會導致共享內存無法釋放,從而無法重新運行程序!
所以應該尋找其他的使Qt應用程序能夠單實例運行的方案。于是找到LocalSocket和LocalServer通訊方
案(據說Qt官方商業版的QSingleApplication的原理好像跟這個差不多)。
“要用到Qt的QLocalSocket,QLocalServer類,這兩個類從接口上看和網絡通信socket沒有區別,但是
它并不是真正的網絡API,只是模仿了而已。這兩個類在Unix/Linux系統上采用Unix域socket實現,而在
Windows上則采用有名管道(named pipe)來實現。”
參見:
http://www.oschina.net/code/snippet_54100_629
http://blog.csdn.net/qq19831030qq/article/details/6199896
?
上面的方案實際操作過程中出現很多問題:
QString serverName = QCoreApplication::applicationName(); //獲取到的serverName為空
為了解決上面的問題,最直接的測試方法是先手動指定一個serverName,
然后將QFile::remove(m_localServer->serverName());改成QFile::remove(serverName);
當手動指定serverName時,習慣上將serverName設為當前的應用程序名,在linux下這又導致下面的問題
QFile::remove(m_localServer->serverName()); //執行刪除失敗(實際測試發現失敗原因是:嘗試刪除
應用程序文件自身!)
?
?上面的兩個問題導致Qt應用程序無法單實例運行。
后來終于在StackOverflow上面看到解決方案:使用QLocalServer::removeServer()刪除LocalServer名
下面是實現代碼:
頭文件:
復制代碼
?1 #ifndef SINGLEAPPLICATION_H
?2 #define SINGLEAPPLICATION_H
?3?
?4 #include <QObject>
?5 #include <QApplication>
?6 #include <QtNetwork/QLocalServer>
?7 #include <QWidget>
?8?
?9 class SingleApplication : public QApplication {
10 ? ? ? ? Q_OBJECT
11 ? ? public:
12 ? ? ? ? SingleApplication(int &argc, char **argv);
13?
14 ? ? ? ? bool isRunning(); ? ? ? ? ? ? ? ?// 是否已經有實例在運行
15 ? ? ? ? QWidget *w; ? ? ? ? ? ? ? ? ? ? ? ?// MainWindow指針
16?
17 ? ? private slots:
18 ? ? ? ? // 有新連接時觸發
19 ? ? ? ? void _newLocalConnection();
20?
21 ? ? private:
22 ? ? ? ? // 初始化本地連接
23 ? ? ? ? void _initLocalConnection();
24 ? ? ? ? // 創建服務端
25 ? ? ? ? void _newLocalServer();
26 ? ? ? ? // 激活窗口
27 ? ? ? ? void _activateWindow();
28?
29 ? ? ? ? bool _isRunning; ? ? ? ? ? ? ? ?// 是否已經有實例在運行
30 ? ? ? ? QLocalServer *_localServer; ? ? // 本地socket Server
31 ? ? ? ? QString _serverName; ? ? ? ? ? ?// 服務名稱
32 };
33?
34 #endif // SINGLEAPPLICATION_H
復制代碼
?CPP文件:
復制代碼
?1 #include "SingleApplication.h"
?2 #include <QtNetwork/QLocalSocket>
?3 #include <QFileInfo>
?4?
?5 #define TIME_OUT ? ? ? ? ? ? ? ?(500) ? ?// 500ms
?6?
?7 SingleApplication::SingleApplication(int &argc, char **argv)
?8 ? ? : QApplication(argc, argv)
?9 ? ? , w(NULL)
10 ? ? , _isRunning(false)
11 ? ? , _localServer(NULL) {
12?
13 ? ? // 取應用程序名作為LocalServer的名字
14 ? ? _serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
15?
16 ? ? _initLocalConnection();
17 }
18?
19?
20
21 // 說明:
22 // 檢查是否已經有一個實例在運行, true - 有實例運行, false - 沒有實例運行
23
24 bool SingleApplication::isRunning() {
25 ? ? return _isRunning;
26 }
27?
28
29 // 說明:
30 // 通過socket通訊實現程序單實例運行,監聽到新的連接時觸發該函數
31
32 void SingleApplication::_newLocalConnection() {
33 ? ? QLocalSocket *socket = _localServer->nextPendingConnection();
34 ? ? if(socket) {
35 ? ? ? ? socket->waitForReadyRead(2*TIME_OUT);
36 ? ? ? ? delete socket;
37?
38 ? ? ? ? // 其他處理,如:讀取啟動參數
39?
40 ? ? ? ? _activateWindow();
41 ? ? }
42 }
43?
44
45 // 說明:
46 // 通過socket通訊實現程序單實例運行,
47 // 初始化本地連接,如果連接不上server,則創建,否則退出
48
49 void SingleApplication::_initLocalConnection() {
50 ? ? _isRunning = false; ? ?
51?
52 ? ? QLocalSocket socket;
53 ? ? socket.connectToServer(_serverName);
54 ? ? if(socket.waitForConnected(TIME_OUT)) {
55 ? ? ? ? fprintf(stderr, "%s already running.\n",
56 ? ? ? ? ? ? ? ? _serverName.toLocal8Bit().constData());
57 ? ? ? ? _isRunning = true;
58 ? ? ? ? // 其他處理,如:將啟動參數發送到服務端
59 ? ? ? ? return;
60 ? ? }
61?
62 ? ? //連接不上服務器,就創建一個
63 ? ? _newLocalServer();
64 }
65?
66
67 // 說明:
68 // 創建LocalServer
69
70 void SingleApplication::_newLocalServer() {
71 ? ? _localServer = new QLocalServer(this);
72 ? ? connect(_localServer, SIGNAL(newConnection()), this, SLOT(_newLocalConnection()));
73 ? ? if(!_localServer->listen(_serverName)) {
74 ? ? ? ? // 此時監聽失敗,可能是程序崩潰時,殘留進程服務導致的,移除之
75 ? ? ? ? if(_localServer->serverError() == QAbstractSocket::AddressInUseError) {
76 ? ? ? ? ? ? QLocalServer::removeServer(_serverName); // <-- 重點
77 ? ? ? ? ? ? _localServer->listen(_serverName); // 再次監聽
78 ? ? ? ? }
79 ? ? }
80 }
81?
82
83 // 說明:
84 // 激活主窗口
85
86 void SingleApplication::_activateWindow() {
87 ? ? if(w) {
88 ? ? ? ? w->show();
89 ? ? ? ? w->raise();
90 ? ? ? ? w->activateWindow(); // 激活窗口
91 ? ? }
92 }
復制代碼
調用示例:
復制代碼
?1 #include "MainWindow.h"
?2 #include "SingleApplication.h"
?3?
?4 int main(int argc, char *argv[]) {
?5 ? ? SingleApplication a(argc, argv);
?6 ? ? if(!a.isRunning()) {
?7 ? ? ? ? MainWindow w;
?8 ? ? ? ? a.w = &w;
?9?
10 ? ? ? ? w.show();
11?
12 ? ? ? ? return a.exec();
13 ? ? }
14 ? ? return 0;
15 }
========
神奇的qt creator 例子程序
這是qt creator第一個例子程序,名叫application,簡單的記事本一類的程序.
1.奇怪的是沒有.ui文件,資源里就一些png文件.界面怎么拼出來的?
2.MainWindow里實現了所有的關于這個記事本的操作,保存文件之類的.但是在哪里調的?為什么按那個"
保存"按鈕,就能調到這個函數,找不到調用的地方,用find reference也找不到.
.......你用過其它IDE么。。
界面上控件可以在設計器上拖上來,也可以在代碼里直接實現。
先簡單看一下教程再看例子吧
在哪個文件里?所有文件都列出來了
都在createActions函數里.
Qt編程沒說一定要ui文件,好多程序都是手敲界面的
========
Qt-簡單程序實例Hello,world
D:\Qt_Work\hello\main.c:
1 #include <QApplication>
2 #include <QWidget>
3 #include <QPushButton>
4
5 int main(int argc, char *argv[])
6 {
7 ? ?QApplication a(argc, argv);
8 ? ?QWidget MainWindow;
9 ? ?MainWindow.setMinimumSize(200, 100);
10 ? MainWindow.setMaximumSize(200, 100);
11
12 ? ?QPushButton button("Hello, World", &MainWindow);
13 ? ?button.setGeometry(20, 20, 160, 60);
14 ? ?MainWindow.show();
15 ? ?return a.exec();
16 }
分析一下程序:
main()程序入口函數。
程序首先創建了一個QApplication類對象。Qt程序中只能包含一個QApplication對象。argc和argv也用
作QApplication對象構造函數參數。
接下來新建了一個QWidget對象。QWidget可以看作一個窗口。在其上可以放置其他對象。如按鈕等。
第9行和第10行將MainWindow的最小尺寸和最大尺寸設置為一樣。這就意味著此窗口不可以調節。
第12行創建了一個按鈕對象button,并且直接調用QPushButton的一個構造函數。第一個參數告訴構造函
數將按鈕的標簽設置為"Hello, World"。第二個參數使MainWindow作為按鈕的父窗口,這意味著將按鈕
放置在 MainWindow窗口上。
第13行設置按鈕的尺寸。前兩個參數告訴按鈕的左上角在其父窗口的位置,他們相對于父窗口的左上角
。后兩個參數設置按鈕的寬度和高度(這里是160像素寬,60像素高)。
第14行調用MainWindow的show()函數。用來顯示窗口。這里不必調用button的show()函數。因為當其父
窗口被調用顯示時,button會被自動顯示。
第15行將控制權從main()函數交給Qt。在exec()函數中,Qt接受和處理用戶以及系統事件,并把這些事
件傳遞給相應的窗口。當應用程序關閉時,exec()函數返回.
========
QT 信號與槽 最簡單例子
main.cpp 和 my_head.h源碼:?
#ifndef MY_HEAD_H ?
#define MY_HEAD_H ?
#include <stdio.h> ?
#include <QObject> ?
//EastonWoo ?
??
class A : public QObject ? //QObject::connect是在QObject定義的,繼承一下。 <span?
style="color:#ff0000;">注意: 如果類A 本身就已經繼承過QObject了,就不用再繼承了,你可以這樣
查看是否已繼承過:把光標移動到類A,右鍵,選擇"Open Type Hierarchy",或直接按Ctrl+Shift+T,就
可以查看到類的繼承關系了。</span> ?
{ ?
Q_OBJECT ? ? ? ? ? ? ? //信號和槽要用到的宏,要加上 ?
??
public: ?
? ? void test() ?
? ? { ?
? ? ? ? send_msg(); ?
? ? } ?
signals: ? ? ? ? ? ? ?//信號關鍵字 ?
? ? void send_msg(); ?//發射信號函數,帶的參數必須和槽一樣。聲明一下就可以了。 ?
}; ?
??
class B : public QObject ?
{ ?
Q_OBJECT ?
??
public slots: ? ? ? ? //槽關鍵字 ?
? ? void recv_msg() ?// ?
? ? { ?
? ? ? ? printf("hello\n"); ?
? ? } ?
}; ?
//值得注意的是,凡是信號和槽的定義關鍵字都在頭文件里定義 ?
//如Q_OBJECT,signal:,public slots:,聲明如void send_msg();void recv_msg(); ?
#endif // MY_HEAD_H ?
#include "my_head.h" ?
//EastonWoo ?
int main() ?
{ ?
? ? printf("start...\n"); ?
??
? ? A send_a; ?
? ? B recv_b; ?
? ? QObject::connect(&send_a,SIGNAL(send_msg()),&recv_b,SLOT(recv_msg())); ?
??
? ? send_a.test(); ?
? ? return 0; ?
} ?
?
qmain一下:
運行結果:
/home/user/hello/hello 啟動中...
start...
hello
/home/user/hello/hello 退出,退出代碼: 0
?{1 ?}
========
QT范例解析
QT動畫
在QT自帶的demo中,有個一個2dpainting的范例,這個例子可以很好的闡述QT簡單的動畫效果機制。在
main函數中創建一個Window對象實例,這個類是從QWidget繼承來的,其構造函數中創建一個Widget類型
對象,并創建一個QTimer對象,每隔50毫秒觸發一次Widget對象的animate()槽函數。在animate中設置
一個累計計數變量elapsed,每次被觸發增加50(QTimer的觸發間隔)并膜上1000,保證這個值不超過
1000.而后調用repaint()函數觸發調用paintEvent()函數,再次進行繪制即可。
void Widget::paintEvent(QPaintEvent *event)
{
? ? //The QPainter class performs low-level painting on widgets and other paint devices
? ? //QPainter類在Widget或其他繪制設備上執行底層的繪制操作
? ? QPainter painter;
? ? painter.begin(this);//開始在設備上繪圖 一個設備上只能有一個繪制對象
? ? painter.setRenderHint(QPainter::Antialiasing);//設置反鋸齒
? ? helper->paint(&painter, event, elapsed);//繪制
? ? painter.end();
}
void Helper::paint(QPainter *painter, QPaintEvent *event, int elapsed)
{
? ? painter->fillRect(event->rect(), background);
? ? painter->translate(100, 100);//移動畫板中心 使widget的中心點為原點
? ? //設置保存點
? ? painter->save();
? ? painter->setBrush(circleBrush);//設置畫刷
? ? painter->setPen(circlePen); ? ?//設置畫筆
? ? painter->rotate(elapsed * 0.030); //按角度順時針旋轉設備 使畫面看起來是動的
? ? qreal r = elapsed / 1000.0; ?//設置微調 r的值從0到1.0循環
? ??
? ? int n = 30;
? ? //畫30個圓圈
? ? for(int i = 0; i < n; ++i){
? ? ? ? painter->rotate(30); ?//旋轉設備30度 繪制圓
? ? ? ? qreal radius = 0 + 120.0 * ((i + r) / n);
? ? ? ? qreal circleRadius = 1 + ((i + r) / n) * 20;//半徑
? ? ? ? painter->drawEllipse(QRectF(radius, -circleRadius, circleRadius * 2, circleRadius *?
2));
? ? }
? ? painter->restore();
? ? painter->setPen(textPen);
? ? painter->setFont(textFont);
? ? painter->drawText(QRect(-50, -50, 100, 100), Qt::AlignCenter, "QT");
}
QT繪圖提供了一個很好的機制,在繪制過程中,要繪制的圖具有不同位置和旋轉角度,但只需要平移和
旋轉畫板對象(繪畫設備),實現坐標映射后,在映射后的坐標的原點位置繪制圖形,從而簡化了對圖
形位置和角度的計算。
QML與類實例化
QT提供了QML機制,可用于設計界面,但qml也可以實現類對象的持久化。adding范例中定義了一個從
QObject繼承的類Person,使用Q_OBJECT宏聲明,并使用Q_PROPERTY宏定義了兩個屬性name和shoeSize.這
樣就可以使用QT的反射機制從qml中加載類的屬性了.在main函數中調用qmlRegisterType模板函數注冊
Person類并指定其版本號和qml中的庫名稱People.這樣就可以從一個合法的qml文件中加載Person類實例
了.
QML文件內容(格式類似于json):?
import People 1.0
Person{
? ? name: "Henreash"
? ? shoeSize: 12
}
注冊并創建實例:
qmlRegisterType<Person>("People", 1, 0, "Person");//將類person注冊到qml中,注冊類名為People?
在qml中使用People標簽定義person類對象
? ? QDeclarativeEngine engine;//QDeclarativeEngine為實例化QML組件提供一個環境
? ? QDeclarativeComponent component(&engine, QUrl
("qrc:/adding/example.qml"));//QDeclarativeComponent封裝了QML組件的定義,是一個數據提供者
? ? Person *person = qobject_cast<Person *>(component.create());//使用導入的qml組件創建對象
并做類型轉換
? ? if(person)
? ? ? ? qWarning() << "The person's name is " << person->name();//使用導入的對象屬性
========
相關鏈接
http://www.cnblogs.com/hicjiajia/category/350988.htmlhttp://blog.csdn.net/liang890319/article/details/7250244
總結
- 上一篇: opencv图像处理常用完整示例代码总结
- 下一篇: Access数据库操作软件研究