Qt5.3 で SIGNALの振り分け

ボタングループを用いて排他的なボタンを作成することに成功したのですが、ボタンを押す毎に、そのボタンに応じた個別の処理をしたいのです。それにはもちろん Qt Framework独自の SIGNAL/SLOTを用いるのですが、これがなかかな難しい このページには詳細な解説があり、数通りのやり方があるようですが、内容が難しいのです 一番理解し易い sender()を用いることにしました

#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H

#include <QMainWindow>
#include <QtGui>
#include <QtWidgets>

class MyMainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MyMainWindow(QWidget *parent = 0);
    ~MyMainWindow();
    QCheckBox *chk[4];
public slots:
    void dispatch();
};

#endif // MYMAINWINDOW_H

そしてこれに応じた .cpp fileです

#include "mymainwindow.h"

MyMainWindow::MyMainWindow(QWidget *parent): QMainWindow(parent)
{
    this->resize(400,400);
    QVBoxLayout *layout = new QVBoxLayout();
    QVBoxLayout *layout1 = new QVBoxLayout();
    QGroupBox *group = new QGroupBox(this);
    group->resize(300,300);
    group->setLayout(layout);
    group->setAlignment(Qt::AlignHCenter);
    group->setCheckable(true);
    QButtonGroup *bg = new QButtonGroup(this);
    chk[1] = new QCheckBox();chk[1]->setText("CAG");
    chk[2] = new QCheckBox("PCI", this);
    chk[3] = new QCheckBox("TAVI", this);
    bg->addButton(chk[1]);
    bg->addButton(chk[2]);
    bg->addButton(chk[3]);
    group->setTitle("Cardiology");
    layout1->addWidget(group);
    layout->addWidget(chk[1]);
    layout->addWidget(chk[2]);
    layout->addWidget(chk[3]);
    group->setStyleSheet("*{background-color:rgb(0, 0, 255); padding: 7px ; color:red;}");
    this->setStyleSheet("*{background-color:rgb(150,147,88); padding: 7px ; color:brown}");
    for (int i=1; i<4; i++) {
        connect(chk[i], SIGNAL(clicked()), this, SLOT(dispatch()));
    }
}

MyMainWindow::~MyMainWindow()
{

}

void MyMainWindow::dispatch() {
    QCheckBox *checkbox = (QCheckBox *)sender();
    QString msg = QString::fromStdString(checkbox->text().toStdString());
    msg += " was pushed!";
    QMessageBox *mb = new QMessageBox("Button", msg, QMessageBox::Critical, QMessageBox::Ok
                                      ||QMessageBox::Default, QMessageBox::Cancel||QMessageBox::Escape, 0);
    mb->show();

}

これにより以下のようにボタンに応じた messageboxを表示することができました 正直スマートではなく、ダサい感じしますが、何より動作することが重要ですPCIボタンが押されたTAVIボタンが押された

なあんだ Qt5.3で QButtonGroupと QGroupBoxを用いてタイトルつきボタン組をつくる

ついに解決しました 以下のようにすれば良かったのです

MyMainWindow::MyMainWindow(QWidget *parent): QMainWindow(parent)
{
    this->resize(300,300);
    QVBoxLayout *layout = new QVBoxLayout();
    QVBoxLayout *layout1 = new QVBoxLayout();
    QGroupBox *group = new QGroupBox(this);
    group->resize(300,200);
    group->setLayout(layout);
    group->setAlignment(Qt::AlignHCenter);
    group->setCheckable(true);
    QButtonGroup *bg = new QButtonGroup(this);
    QCheckBox *chk1 = new QCheckBox("CAG");
    QCheckBox *chk2 = new QCheckBox("PCI");
    QCheckBox *chk3 = new QCheckBox("TAVI");
    bg->addButton(chk1);
    bg->addButton(chk2);
    bg->addButton(chk3);
    group->setTitle("Cardiology");
    layout1->addWidget(group);
    layout->addWidget(chk1);
    layout->addWidget(chk2);
    layout->addWidget(chk3);
    group->setStyleSheet("*{background-color:rgb(0, 0, 255); padding: 7px ; color:red;}");
    this->setStyleSheet("*{background-color:rgb(150,147,88); padding: 7px ; color:rgb(255,255,255)}");
}

これで排他的ボタングルーブをタイトルつきで表示および機能させることに成功しました ざっとこんな感じです
Qt5.3 Button Group

Qt5.3で QGroupBoxを用いてボタングルーブを作成する

この方法がスタンダードなようですが、問題は排他的ボタングループを作れず、いくつもチェックできてしまうのです

QVBoxLayout *layout = new QVBoxLayout();
QVBoxLayout *layout1 = new QVBoxLayout();
QGroupBox *group = new QGroupBox(this);
group->resize(300,200);
group->setLayout(layout);
group->setAlignment(Qt::AlignHCenter);
group->setCheckable(true);

QCheckBox *chk1 = new QCheckBox("CAG");
QCheckBox *chk2 = new QCheckBox("PCI");
QCheckBox *chk3 = new QCheckBox("TAVI");
group->setTitle("Cardiology");
layout1->addWidget(group);
layout->addWidget(chk1);
layout->addWidget(chk2);
layout->addWidget(chk3);
this->setStyleSheet("*{background-color:rgb(150,147,88); padding: 7px ; color:rgb(255,255,255)}");

これを用いれば以下のようにいくつものボタンをチェックできてしまいます 排他的ボタンにするメソッドはありませんでした
QGroupBox

Qt5.3でButtonGroupにタイトルをつけるには

Qt4.0以降、QButtonGroupは QWidget派生クラスではなくなったため、QButtonGroup(const *char, *parent=0); というコンストラクタが無くなりました

このため、Qt3まででは簡単にボタングルーブにタイトルつけれたのに、それができなくなったのです これは僕らにしてみれば非常に使いにくくなりました すったもんだの末以下のようにして何とかタイトルつけれるようになりました

    QVBoxLayout *layout = new QVBoxLayout();
    QGroupBox *group = new QGroupBox(this);
    group->resize(200, 100);
    group->setLayout(layout2);
    group->setTitle(tr("Cardiology Fields"));
    group->setCheckable(false);
    this->setStyleSheet("*{background-color:rgb(150,147,88); padding: 7px ; color:rgb(255,255,255)}");

    QButtonGroup *bg = new QButtonGroup(this);
    bg->setExclusive(true);
    QCheckBox *b1 = new QCheckBox(tr("CAG"), this);
    QCheckBox *b2 = new QCheckBox(tr("PCI"), this);
    b1->move(10, 20);
    b2->move(10, 50);
    bg->addButton(b1);
    bg->addButton(b2);

これを実行すると次のようになります なお、QButtonGroupを用いないと排他的ボタングルーブ(どれか一つしかチェックできないもの)を作るのは大変なのですQButtonGroup in Qt5.3

Qt5.3 button group

これも苦労しましたがこれで可能です

MyMainWindow::MyMainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setGeometry(100, 100, 150, 140);
    group = new QButtonGroup(this);
    b1 = new QCheckBox("Check1", this);
    b1->move(20, 20);
    b2 = new QCheckBox("Check2", this);
    b2->move(20, 50);
    b3 = new QCheckBox("Check3", this);
    b3->move(20, 80);
    group->addButton(b1);
    group->addButton(b2);
    group->addButton(b3);
}

これで以下のようなボタングルーブが作成され、排他的に選択可能となります
button group

Qt 4.0より廃止

Qtプログラミング 24時間集中講座という2001年発売の訳書を読んでいます なかなか良い内容なのですが、何しろ10年以上前の内容なので なかなか大変です

そこでは普通に書かれている setMainWindow()という関数が現在使用していする Qt5.3ではエラーになります Googleしてみると、どうやらこの関数は Qt 3.0までで、4.0以降は廃止されたらしいのです だって当たり前に main windowとなるので不要、という考えのようです というわけで簡単なプログラムボタンを押せばこのプログラムが終了するというものがかけました

#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H

#include <QMainWindow>
#include <QtWidgets>
#include <QtGui>

class MyMainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MyMainWindow(QWidget *parent = 0);
    ~MyMainWindow();
private:
    QPushButton *b1;
};

#endif // MYMAINWINDOW_H


#include "mymainwindow.h"

MyMainWindow::MyMainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setGeometry(10, 100, 200, 120);
    b1 = new QPushButton("This is a Button", this);
    b1->setGeometry(20, 20, 160, 80);
    b1->setFont(QFont("Times", 24, QFont::Bold));
    connect(b1, SIGNAL(clicked()), qApp, SLOT(quit()));
}

MyMainWindow::~MyMainWindow()
{

}


#include "mymainwindow.h"
#include <QApplication>
#include <QtWidgets>
#include <QtGui>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyMainWindow w;

    w.show();

    return a.exec();
}

Rubyの初歩

未だまだ初歩ですが、Rubyについて勉強していて学んだことを忘れないように記載します

Rubyでは徹底的なオブジェクト指向が使われています それは整数や文字列についてもそうであり、それぞれ整数オブジェクトクラスや文字列オブジェクトクラスに属しています だから以下のような C/C++では考えられないことが普通に最初から行われます

puts 5
puts 5.to_i
puts 5.to_f

puts "SAITO"
puts "SAITO".reverse

この出力結果は

5
5
5.0
SAITO
OTIAS

となります つまり、何も自分では定義していないにもかかわらず最初から、整数クラスや文字列クラスが保持しているメソッドを読み出すことができます つまり、to_i (整数に変換する)、to_f (浮動小数点に変換する)、reverse (文字列を逆順にする)というメソッドを呼び出したのです

それでは自分で定義したクラスではどうでしょうか

class Animal
	def say
		puts "Nyaon Nyaon"
	end
end

animal = Animal.new
animal.say

この出力は

Nyaon Nyaon

となります このまでは C++などでもともとオブジェクト指向プログラムをしている私としては簡単に普通に理解できます

しかし、ふと思いました これを C++で書くとどうなるか?

class Animal {
public:
  Animal() {}
  ~Animal() {}
  void say() {
    std::cout << "Nyaon NYaon" << std::endl;
  }
};

int main() {
  Animal cat * new Animal();
  cat->say();
  delete cat;
}

このようになります ここで、catという変数名はその変数のアドレスを指しています そして、新たにnewで生成したならば、最後にdeleteしなければ、メモリーリークが発生します これに対して、Rubyではもともと言語にゴミ集め (ガベージコレクション)の機能が備わっているので、いちいち deleteせずともメモリーリークは発生しません ここいら辺は JAVAや BASICなどと同じです 本質的なことは、Rubyでは変数名というのは、全て変数のアドレスつまりポインタだということなのです たとえば C++で今のcatという変数生成を以下のようにした場合にはどうなるでしょうか

int main() {
  Animal cat();
  cat.say();
}

このようになり、矢印によるメソッド指定ではなく、ピリオドによる指定となります そして、この場合にはcatという変数そのものを指していて、アドレスを指しているのではありません そして、このcatというのは newで生成した場合には、HEAP領域に作られますが、このように直接生成した場合には、STACK領域に取られるのです つまり、もしもこの catというものの実態が非常にメモリーを浪費するものであったとすれば、一挙に Stackを消費尽くしてしまい、プログラムは破壊され システムも障害を受けるでしょう

Rubyの場合変数であれ、何であれ全て(多分) HEAP領域に確保され、そこに対するポインターのみが存在するのです これは新たに知った大きな知識でした

Qt5.1で QSoundを使用するには?

Qtに関しては日本語の情報が少く苦労します

QSoundというコンポーネントがありますが、どうしてもQt 5.1でこれをinludeできませんでした

色々調べると ここに正解がありました

これによれば まず、

.proに QT += multimedia を追加する

そうすると #include <QSount>が働きます

次に、qmakeを実行して クリーンとする これはあくまでもリンカーの問題であり、クリーン・ビルドではありません

そのようにすれば、includeできます

OSXで描画に再挑戦

今朝も札幌に入っています 何を思ったか飛行機の中で、突然 暫く投げていた OpenGLに再挑戦する気になったのです そして、パラパラ調べ、暫く触っていなかった XCode 5.1.1を取り出し、プログラムを書いたのです

 

そして そして 下記のような画像を出すことに成功しました これを発展させて、OSXでも DICOM Viewerを作成するのだ

OpenGL

これから帰国

心配していた雪が本日も降り、ワシントンDCは雪一面となりました ホテルにはタクシーがなかなか来ず、タクシー待ちだけで 40分かかりました 途中の高速も渋滞しましたが、無事ダラス空港に到着しました 飛行機は、30分遅れで飛び立てそうです

ところで、このアメリカ滞在中に、MacBook Proを徐々に本来の OSXとして用いるように移行しています まずは、懸案の Outlookの使用を停止しました 次の作業は Officeの使用停止でしょうか

となると、Windows7側では何をやるか? という問題が出てきますが、さしあたっては C++ programmingくらいでしょうか・・・