Qt4の最近のブログ記事

Qt4 QList の覚え書き

Qt4 の QList クラスを使うときのサンプル。
delete はここでは考慮してない。

#include 
#include 

class XY {
public:
	int x;
	int y;

	XY() { x=y=0; }
	XY(int _x, int _y) { x=_x; y=_y; }
	~XY() {}
	void dump() {
		qDebug() << x << ',' << y << endl;
	}
};


int main(int argc, char *argv[])
{
    QList< XY > list;
    XY a;
    a.x = 1;
    a.y = 2;
    list.append(a);

    XY b(2, 22);
    list.append(b);

    list.append(*new XY(3,333));

    QList< XY >::iterator i = list.begin();
    while (i != list.end()) {
    	XY& xy = (*i);
    	(*i).dump();
        ++i;
    }

    return 0;
}

Qt4 自前のsignalの作り方

自分勝手な sugnal の定義方のメモ

例:フォーカスを持ったボタンでキーが押されたときにシグナルを発生させる。

(1) シグナルのセクションを用意する。
signals: というのを class の中に追加。
public、private、protected のどれでもいいのか?
内容的には private か protected だろうな。

(2) シグナルとなるメソッドを追加する。
void signal_key_pressed( int ); としてみた。
シグナルには引数をつけることができる。
押されたキーを引数に渡すことをもくろみ int にしてみる。

(3) シグナルを発生させる処理を実装する。
virtual void keyPressEvent(QKeyEvent *event) をオーバーライドし、
emit signal_key_pressed( event->key() );
でシグナルを発生させる。

(4) シグナル受け取る側のスロットを用意する。
セクション slots: を追加。

(5) スロットのメソッドを宣言する。
void slot_key_pressed(int) とした。

(6) QObject::connect() を用いてスロットにつなぐ。

(7) スロットを実装する。


--- シグナルを送るクラス
class someButton : public QPushButton
{
    Q_OBJECT

private:
    void _init() {  ... }

public:
    someButton (QWidget * parent =0) : QPushButton(parent) {
        _init();
        ...
    }
    ~someButton () { ... };

signals:	// (1)
    void signal_key_pressed( int );	// (2)

protected:
    virtual void keyPressEvent(QKeyEvent *event) {
        emit signal_key_pressed( event->key() );	// (3)
    }
};

--- シグナルを受けるクラス
class someWidget : public QWidget
{
    Q_OBJECT

public:
    someWidget (QWidget *parent = 0)   : QWidget(parent) {
        _init(this);
        ....
    }
    ~someWidget () {}

    someButton* button;

private:
    void _init() {
        button = new someButton();
        QObject::connect(button,SIGNAL(signal_key_pressed(int)),
            this, SLOT(slot_key_pressed(int)));	// (6)
    }

private slots:	// (4)
    void slot_key_pressed(int);	// (5)
}

void someWidget::slot_key_pressed(int key)	// (7)
{
    switch(key)
    {
    ...
    }
}

sudoku

数独のソース

用意するもの、
Eclispe
CDT
Qt4
Qt4 Eclipse Integration
ソースとバイナリ http://cid-e844b718ee02a287.skydrive.live.com/self.aspx/.Public/examples/sudoku.zip

[main.cpp]

#include "qs2.h" #include <QtGui> #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); QsudokuClass w; w.show(); return a.exec(); }

[qs2.h]

#ifndef QS2_H #define QS2_H #include <QtCore/QVariant> #include <QtGui/QAction> #include <QtGui/QApplication> #include <QtGui/QButtonGroup> #include <QtGui/QGridLayout> #include <QtGui/QHeaderView> #include <QtGui/QPushButton> #include <QtGui/QWidget> #include <QKeyEvent> #include <QThread> #include "ui_qs2.h" class sudokuCell : public QPushButton { private: void _init() { num = 0; QSizePolicy policy(QSizePolicy::Minimum, QSizePolicy::Minimum); policy.setHorizontalStretch(0); policy.setVerticalStretch(0); policy.setHeightForWidth( this->sizePolicy().hasHeightForWidth()); this->setSizePolicy(policy); this->setMaximumSize(QSize(35, 35)); this->setFlat(false); this->setCheckable(true); } public: int num; char label[8]; sudokuCell(QWidget * parent =0) : QPushButton(parent) { _init(); } sudokuCell(const QString & text, QWidget * parent = 0) : QPushButton(text, parent) { _init(); } sudokuCell(const QIcon & icon, const QString & text, QWidget * parent = 0 ) : QPushButton(icon, text, parent) { _init(); } ~sudokuCell() {}; int Number (void) { return num; } void Number (int new_num) { num = new_num; } void Display(int num =-1) { label[0] = 0; if (num<0) num = this->num; if (num) sprintf(label, "%d", num); setText(label); } protected: virtual void keyPressEvent(QKeyEvent *event) { int key; switch (event->key()) { case Qt::Key_Left: key = Qt::Key_S; break; case Qt::Key_Right: key = Qt::Key_D; break; case Qt::Key_Up: key = Qt::Key_E; break; case Qt::Key_Down: key = Qt::Key_X; break; case Qt::Key_Space: key = Qt::Key_0; break; default: key = event->key(); break; } QApplication::postEvent(parentWidget(), new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier)); }; }; class QKeyEvent; class QsudokuClass : public QWidget { Q_OBJECT int x; int y; bool cancel; public: QWidget *gridLayoutWidget; QGridLayout *gridLayout; sudokuCell *cell[9][9]; bool chk[9][9]; QThread *probe; QsudokuClass(QWidget *parent = 0) : QWidget(parent) { setupUi(this); x = -1; y = -1; for (int i=0; i<9; i++) for (int j=0; j<9; j++) chk[i][j] = 0; } ~QsudokuClass() {} void Number (int num) { if (x >= 0 && y >= 0) cell[y][x]->Number(num); } int Number (void) { return (x >= 0 && y >= 0) ? cell[y][x]->Number() : -1; } void Display(int v, int h, int num =-1) { cell[v][h]->Display(num); } void Display(); void emuClick(int x, int y); void setupUi(QWidget *widget) { if (widget->objectName().isEmpty()) widget->setObjectName(QString::fromUtf8("QsudokuClass")); widget->resize(350, 350); gridLayoutWidget = new QWidget(widget); gridLayoutWidget->setObjectName( QString::fromUtf8("gridLayoutWidget")); gridLayoutWidget->setGeometry(QRect(5, 5, 340, 340)); gridLayout = new QGridLayout(gridLayoutWidget); gridLayout->setSpacing(1); gridLayout->setMargin(1); gridLayout->setObjectName(QString::fromUtf8("gridLayout")); gridLayout->setSizeConstraint(QLayout::SetDefaultConstraint); gridLayout->setContentsMargins(0, 0, 0, 0); widget->setWindowTitle(QApplication::translate("QsudokuClass", "Sudoku?", 0, QApplication::UnicodeUTF8)); for (int y=0; y<9; y++) { for (int x=0; x<9; x++) { QString name,label; name.sprintf("CELL_%d%d",y,x); cell[y][x] = new sudokuCell(name,gridLayoutWidget); cell[y][x]->setText(""); gridLayout->addWidget(cell[y][x], y, x, 1, 1); QObject::connect(cell[y][x], SIGNAL(clicked()), widget, SLOT(sel_change())); } } QMetaObject::connectSlotsByName(widget); probe = NULL; } private: // Ui::QS2Class ui; private slots: void sel_change(); protected: virtual void keyPressEvent(QKeyEvent *event); }; #endif // QS2_H

[qs2.cpp]

#include "qs2.h" #include "sudokuThread.h" void QsudokuClass::sel_change() { if (x > -1 && y > -1) cell[y][x]->setChecked(false); for (int i=0; i<9; i++) for (int j=0; j<9; j++) if (cell[i][j]->isChecked()) { x = j; y = i; Display(i,j); } } void QsudokuClass::Display() { bool complete = (probe) ? ((sudokuThread*)probe)->complete:false; for (int i=0; i<9; i++) for (int j=0; j<9; j++) { QFont font; if (complete || chk[i][j]) { font.setPointSize(12); font.setBold(true); } else { font.setPointSize(8); font.setBold(false); } cell[i][j]->setFont(font); cell[i][j]->Display(); } } void QsudokuClass::emuClick(int h, int v) { cell[v][h]->setChecked(true); sel_change(); } void QsudokuClass::keyPressEvent(QKeyEvent *event) { if (x < 0 || y < 0) return; switch (event->key()) { case Qt::Key_Space: cell[y][x]->Number(0); break; case Qt::Key_0: cell[y][x]->Number(0); break; case Qt::Key_1: cell[y][x]->Number(1); break; case Qt::Key_2: cell[y][x]->Number(2); break; case Qt::Key_3: cell[y][x]->Number(3); break; case Qt::Key_4: cell[y][x]->Number(4); break; case Qt::Key_5: cell[y][x]->Number(5); break; case Qt::Key_6: cell[y][x]->Number(6); break; case Qt::Key_7: cell[y][x]->Number(7); break; case Qt::Key_8: cell[y][x]->Number(8); break; case Qt::Key_9: cell[y][x]->Number(9); break; case Qt::Key_S: emuClick((x+8)%9,y); return; case Qt::Key_D: emuClick((x+1)%9,y); return; case Qt::Key_E: emuClick(x,(y+8)%9); return; case Qt::Key_X: emuClick(x,(y+1)%9); return; case Qt::Key_R: Display(); return; default: { int dummy; dummy = 0; } return; } chk[y][x] = cell[y][x]->Number(); if (probe) { ((sudokuThread*)probe)->cancel(); probe->terminate(); delete probe; probe = NULL; } for (int i=0; i<9; i++) for (int j=0; j<9; j++) if (!chk[i][j]) cell[i][j]->Number(0); Display(); probe = new sudokuThread(this); probe->start(); }

[sudokThread.h]

/* * sudokuThread.h * * Created on: 2009/06/25 * Author: Tenshi */ #ifndef SUDOKUTHREAD_H_ #define SUDOKUTHREAD_H_ #include "qs2.h" class sudokuThread : public QThread { Q_OBJECT protected: QsudokuClass* sudoku; int num(int v, int h) { return (sudoku) ? sudoku->cell[v][h]->Number() : -1; } void setNum(int v, int h, int num) { if (!sudoku) return; else sudoku->cell[v][h]->Number(num); } void probe(int loc); void run() { while (!cancel_flag) { ans = 0; probe(0); if (ans == 1) { complete = true; wait(); } } exit (); } public: int ans; bool complete; bool cancel_flag; sudokuThread(QObject *parent = 0) { sudoku = (QsudokuClass*)parent; cancel_flag = false; complete = false; } virtual ~sudokuThread() { } void cancel() { cancel_flag = true; } }; #endif /* SUDOKUTHREAD_H_ */

[sudokuThread.cpp]

/* * sudokuThread.cpp * * Created on: 2009/06/25 * Author: Tenshi */ #include "ui_qs2.h" #include "sudokuThread.h" void sudokuThread::probe(int loc) { if (cancel_flag) return; if (loc==81) { ans ++; QApplication::postEvent(sudoku, new QKeyEvent(QEvent::KeyPress, Qt::Key_R, Qt::NoModifier)); msleep(300); } else { int x = loc % 9; int y = loc / 9; int bx = (x/3)*3; int by = (y/3)*3; if (num(y,x)!=0) { probe(loc+1); } else { for (int n=1; n<=9; n++) { bool used = false; int ix,iy; for (ix=0; !used && ix<9; ix++) if (num(y,ix)==n) used=true; for (iy=0; !used && iy<9; iy++) if (num(iy,x)==n) used=true; for (iy=by; !used && iy<by+3; iy++) for (ix=bx; !used && ix<bx+3; ix++) if (num(iy,ix)==n) used=true; if (used) continue; setNum(y,x,n); probe(loc+1); setNum(y,x,0); } } } }

eclipse + qt4.5

Vista SP2 にインストール。

用意したもの、以下のとおり。はっきりいってよくわかっていない。
eclipse-cpp-ganymede-SR2-win32.zip ... (1)
qt-sdk-win-opensource-2009.02.1.exe ...(2)
qt-eclipse-integration-win32-1.5.1.exe ... (3)

次も一応ダウンロードだけしといた。
qt-win-opensource-4.5.1-mingw.exe ... (4)
qt-creator-win-opensource-1.1.1.exe ... (5)

(1) を展開。 c:\opt\eclipse\ に置く。
このディレクトリにはほかのバージョンの eclipse も置かれているので
実行ファイル(exlipse.exe)の位置は"C:\opt\eclipse\eclipse\eclipse.exe"

(2) を実行。 c:\opt\Qt\2009.02 にインストール。
C:\Program files\ 以下にインストールするのがいいんだろうけどなんとなく変えてみた。

(3) を実行。 C:\opt\Trolltech\Eclipse にインストール。
Eclipse のインストレーションは C:\opt\eclipse\eclipse
MinGW のインストレーションは C:\opt\Qt\2009.02\mingw\bin
をそれぞれ指定。

(4),(5) は今日は使わなかった。

Eclipse を起動。
パスを追加する。メニュー(Window) (Preference) [QT]
Bin Path: C:\opt\Qt\2009.02\qt\bin
Include Path: C:\opt\Qt\2009.02\qt\include

で、コンパイルはできるけどデバッグと実行ができない。
なにが足らないんだろ。。。

--- 1時間後、
パス(C:\opt\Qt\2009.02\qt\bin)を通したらエクスプローラから直接実行はできた。
でもまだデバッグできない。

--- さらに1時間後、
http://lists.trolltech.com/qt-interest/2008-06/msg00543.html
を見つけてプロパティをいじる。
[ Debugger Tab - Main Tab ]のデバッガのパス変更と、
C:\opt\Qt\2009.02\mingw\bin\gdb.exe
[ Debugger Tab - Shared Libraries Tab ]のライブラリの追加。
C:\opt\Qt\2009.02\lib
で何とか動いたみたい。

連絡先

nakanohito