照例,練習GUI Framework都先從顯示圖片開始著手。
稍微碰了一下Qt,感覺上很多細節都很人性化,譬如說不用指定window,一個label或一個pushButton都可以自己形成視窗,所以一個最簡單的Hello World可以只有短短四行程式碼,的確正如廣告說的,需要輸入的程式碼變少了。
所編繹出來的檔案大小也夠精練,小程式都可控制在100k以內,與GTK+相比不遑多讓,執行速度更比GTK+快上許多,兼具精簡與效能,難怪會成為目前GUI Framework中的大熱門,名氣得來一點都不僥倖。
目前對Qt的印象非常良好,以後就專門拿它來練習C++。
若真的要挑剔,那大概只能說Qt的Signal/Slot機制並沒有那麼直覺,其中Signal的程式碼還需要qmake生成才能順利編譯。相比於GTK+簡單明瞭的callback函式,實在複雜許多。當然這只是一時的感想,之後若更進一步認識,或許就會改變看法了。
這支小程式實作過程中,參考了Qt4學習筆記其中的幾個範例程式,真的得說,這個教學網站對我幫助很大,若沒有它,恐怕沒辦法這個快理出頭緒來,感謝哪。
More...
main.cpp:
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
// 圖片顯示小程式 #include <QApplication> #include <QBitmap> #include <QLabel> #include <QPushButton> #include <QVBoxLayout> #include "ButtonClicked.h" QString toUnicode( char *strText ) // 使之可以顯示中文(big5轉unicode) { return QString::fromLocal8Bit( strText ) ; } int main( int argc, char *argv[] ) { QApplication app(argc, argv); QWidget *window = new QWidget; window->setWindowTitle( toUnicode( "圖片顯示小程式" ) ); QLabel *labelText = new QLabel( toUnicode( "圖片地址" ) ) ; QLabel *labelImage = new QLabel( "" ) ; QPushButton *btn = new QPushButton( toUnicode( "開啟檔案" ) ) ; QVBoxLayout *vBoxLayout = new QVBoxLayout; window->setLayout(vBoxLayout); vBoxLayout->addWidget(btn); vBoxLayout->addWidget(labelText); vBoxLayout->addWidget(labelImage); ButtonClicked bc ; // Signal與Slot的類別 bc.setWidget( window ) ; // 用來修改window視窗大小與標題 // 將btn->clicked()的訊號送往bc.clicked() QObject::connect( btn, SIGNAL( clicked() ), &bc, SLOT( clicked() ) ) ; // 將bc.fileNameChanged()的訊號送往label.setText() QObject::connect( &bc, SIGNAL( fileNameChanged( QString ) ), labelText, SLOT( setText( QString ) ) ) ; // 將bc.pixmapChanged()的訊號送往labelImage.setPixmap() QObject::connect( &bc, SIGNAL( pixmapChanged( QPixmap ) ), labelImage, SLOT( setPixmap( QPixmap ) ) ) ; window->resize( 200, 100 ); window->show(); return app.exec(); }
ButtonClicked.h:
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
#ifndef BUTTON_CLICKED_H #define BUTTON_CLICKED_H #include <QObject> #include <QString> #include <QFileDialog> #include <QWidget> QString toUnicode( char *strText ) ; // big5編碼轉為unicode class ButtonClicked : public QObject { Q_OBJECT public: // 成員初始列(member initialization list),效率高於傳統賦值 ButtonClicked() : m_fileName( "" ), m_widget( NULL ) { } public slots: void clicked(); void setWidget( QWidget *widget ) { m_widget = widget ; } signals: void fileNameChanged( QString fileName ) ; // 傳回新的檔案名稱 void pixmapChanged( QPixmap pic ) ; // 傳回新的圖片檔 private: QString m_fileName ; QWidget *m_widget ; }; #endif
ButtonClicked.cpp:
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
#include "ButtonClicked.h" void ButtonClicked::clicked() { // 跳出開啟檔案視窗 // 目錄以m_fileName作為參數,作用是可以保存上一次的讀取目錄。 m_fileName = QFileDialog::getOpenFileName( 0, "Open Image", m_fileName, "Image Files (*.png *.xpm *.jpg *.bmp) ") ; QPixmap pic( m_fileName ) ; // 隨圖片大小而改變視窗大小,但不知為何無法及時反應,需等下一次開檔才能重設大小 // 使用update(), repaint(), hide()+show(), showMinimized()+showNormal()都沒有用... m_widget->resize( pic.width(), pic.height()+50 ) ; m_widget->setWindowTitle( toUnicode( "圖片尺寸 : 長度:" ) + QString::number( pic.height() ) + toUnicode( " , 寬度:" ) + QString::number( pic.width() ) ); // Qt的label認得html標籤,可直接使用於字串當中。 emit fileNameChanged( "<center><h1><font color=blue>" + m_fileName + "</font></h1></center>" ) ; emit pixmapChanged( pic ) ; }
moc_ButtonClicked.cpp:(由編譯器自己生成的程式碼)
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | /**************************************************************************** ** Meta object code from reading C++ file 'ButtonClicked.h' ** ** Created: Sun Jun 13 00:28:56 2010 ** by: The Qt Meta Object Compiler version 59 (Qt 4.3.3) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ #include "ButtonClicked.h" #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'ButtonClicked.h' doesn't include <QObject>." #elif Q_MOC_OUTPUT_REVISION != 59 #error "This file was generated using the moc from 4.3.3. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif static const uint qt_meta_data_ButtonClicked[] = { // content: 1, // revision 0, // classname 0, 0, // classinfo 3, 10, // methods 0, 0, // properties 0, 0, // enums/sets // signals: signature, parameters, type, tag, flags 24, 15, 14, 14, 0x05, 53, 49, 14, 14, 0x05, // slots: signature, parameters, type, tag, flags 76, 14, 14, 14, 0x0a, 0 // eod }; static const char qt_meta_stringdata_ButtonClicked[] = { "ButtonClicked\0\0fileName\0" "fileNameChanged(QString)\0pic\0" "pixmapChanged(QPixmap)\0clicked()\0" }; const QMetaObject ButtonClicked::staticMetaObject = { { &QObject::staticMetaObject, qt_meta_stringdata_ButtonClicked, qt_meta_data_ButtonClicked, 0 } }; const QMetaObject *ButtonClicked::metaObject() const { return &staticMetaObject; } void *ButtonClicked::qt_metacast(const char *_clname) { if (!_clname) return 0; if (!strcmp(_clname, qt_meta_stringdata_ButtonClicked)) return static_cast<void*>(const_cast< ButtonClicked*>(this)); return QObject::qt_metacast(_clname); } int ButtonClicked::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: fileNameChanged((*reinterpret_cast< QString(*)>(_a[1]))); break; case 1: pixmapChanged((*reinterpret_cast< QPixmap(*)>(_a[1]))); break; case 2: clicked(); break; } _id -= 3; } return _id; } // SIGNAL 0 void ButtonClicked::fileNameChanged(QString _t1) { void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) }; QMetaObject::activate(this, &staticMetaObject, 0, _a); } // SIGNAL 1 void ButtonClicked::pixmapChanged(QPixmap _t1) { void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) }; QMetaObject::activate(this, &staticMetaObject, 1, _a); } |
No response to “Qt習作之圖片顯示” ;
張貼留言