Qt習作之圖片顯示

押切蓮介__黃昏特攻隊

照例,練習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習作之圖片顯示” ;

張貼留言