ホーム

OFF-SOFT.net

OFF-SOFT.net

ウェブやソフトウェアに関するサポート&情報サイトです。サイト構築からソフトウェアの作成、利用まであなたの助けになるかも・・・・しれません。たぶん・・。

Qt (B2) QTableWidgetで複数行のテキスト入力

公開日| 2009年06月18日 | コメントはまだありません。
QStyledItemDelegateの継承を利用する
Delegateとは、直訳すると"委任する"という感じでしょうか。
つまりは、一部の基幹制御を委託されるクラスということにでしょうか。 ここで使用するQStyledItemDelegateは、QTableWidgetにも使用できますが、 QTreeWidgetにも使用できます。全く同じクラスが、再利用できるのです。

では、QStyledItemDelegateを継承して、クラスを作成してみましょう。

[multidelegate.h]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <QStyledItemDelegate>
 
class MultiDelegate : public QStyledItemDelegate
{
	Q_OBJECT
 
public:
	MultiDelegate(QWidget *parent = 0);
 
	virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
	                      const QModelIndex &index) const;
	virtual void setEditorData(QWidget *editor, const QModelIndex &index) const;
	virtual void setModelData(QWidget *editor, QAbstractItemModel *model,
	                  const QModelIndex &index) const;
}

[multidelegate.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
#include <QtGui>
 
#include "MultiDelegate.h"
 
MultiDelegate::MultiDelegate(QWidget *parent) 
	: QStyledItemDelegate(parent) 
{
}
 
QWidget *MultiDelegate::createEditor(QWidget *parent,
                                    const QStyleOptionViewItem & /*option*/,
                                    const QModelIndex &/*index*/) const
 
{
	QPlainTextEdit *editor = new QPlainTextEdit(parent);
	return editor;
}
 
void MultiDelegate::setEditorData(QWidget *editor,
                                 const QModelIndex &index) const
{
	QPlainTextEdit *mEditor = qobject_cast<QPlainTextEdit *>(editor);
	mEditor->setPlainText(index.data().toString());
}
 
void MultiDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                const QModelIndex &index) const
{
	QPlainTextEdit *mEditor = qobject_cast<QPlainTextEdit *>(editor);
	model->setData(index, mEditor->toPlainText());
}

これは、3つの仮想関数をオーバーライドして、それぞれで、QPlainTextEditの制御を行っています。

  • createEditor
    -- このメソッドは、入力可能な状態になるときにコールされ、このメソッドで渡されたQWidgetが そのまま入力画面として表示されます。

  • setEditorData
    -- このメソッドは、入力画面の初期設定を行うときにコールされます。 ここでは、現在のQTableWidgetのセルの情報を初期値として設定しています。

  • setModelData
    -- このメソッドは、入力画面が編集を終えたときにコールされます。 ここでは、入力情報を現在のQTableWidgetのセルへ出力しています。


では、main.cppの変更をもて見ましょう。

[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
#include <QtGui>
#include "MultiDelegate.h"
 
 
int main(int argc, char *argv[])
{
	QApplication app(argc, argv);
 
	QTableWidget tableWidget(3, 3);
	tableWidget.setItemDelegate(new MultiDelegate);
	//	set edit trigger event
	tableWidget.setEditTriggers(QAbstractItemView::DoubleClicked
	                            | QAbstractItemView::SelectedClicked
								| QAbstractItemView::EditKeyPressed );
 
	//	set title
	QStringList headerLabels;
	headerLabels << "Name" << "Attribute" << "Comment";
	tableWidget.setHorizontalHeaderLabels(headerLabels);
 
	QTableWidgetItem *item[3];
	//	set sample data values.
	for (int nrow = 0; nrow<3; nrow++ ) {
		item[0] = new QTableWidgetItem(QString("sample item name #%1").arg(nrow+1));
		item[1] = new QTableWidgetItem(QString("att #%1").arg(nrow+1));
		item[2] = new QTableWidgetItem(QString("comment #%1\nreturn ").arg(nrow+1));
 
		for(int ncol=0;ncol<3;ncol++){
			tableWidget.setItem(nrow, ncol, item[ncol]);
 
		}
	}
 
	//	fit of column size at contents.
	tableWidget.resizeColumnsToContents();
	tableWidget.resize(500, 300);
 
	//	table show.
	tableWidget.show();
 
	return app.exec();
}

10行目に、setItemDelegateで、Delegateクラスとの関連付けを行っているだけです。

これをコンパイルして、実行すると、以下のような画面が表示されます。



動作も、マウスのダブルクリックなどで、入力状態になり、期待通りの画面動作です。
実際に操作を試してみあると、残念ながら、"Enter"を入力すると入力画面が閉じてしまいます。

QPlainTextEditでなくQTextEditを使うと、"Enter"を入力しても入力画面は閉じません。

これを閉じなくするためには、eventFilterをオーバーライドして、キー入力イベントを 横取りすれば良いです。
例えば、以下のように、追加します。

[multidelegate.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
bool MultiDelegate::eventFilter ( QObject * editor, QEvent * oevent )
{
	QPlainTextEdit *mEditor = qobject_cast<QPlainTextEdit *>(editor);
	if (!mEditor || !oevent)
		return false;
 
 
	int nevent_type=oevent->type();
	if (
		nevent_type== QEvent::KeyPress ||
		nevent_type== QEvent::KeyRelease
		) {
		QKeyEvent *keyevt=static_cast<QKeyEvent *>(oevent);
		if(keyevt){
			switch(keyevt->key()){
			case Qt::Key_Enter:
			case Qt::Key_Return:
				if(nevent_type==QEvent::KeyRelease){
					return true;
				}
				mEditor->insertPlainText("\n");
				return true;
				break;
			default:
				break;
			}
		}
	}
	return QStyledItemDelegate::eventFilter( editor,oevent );
}

eventFilterで入ってきたイベントが、キーイベントで、"Enter"キー入力の場合、 QPlainTextEditへ改行情報を追加して、処理を終了しています。

戻り値にtrueを指定すると、ここで、イベントが処理されたことを意味しますので、 このイベントh、破棄されます。

これをコンパイルして、実行すると、改行を入力しても入力画面が閉じなくなると思います。


今回は、QTableWidgetの入力のカスタマイズ処理を行いました。 上記を更にEXCELのようにCtrl+Enterで改行するようにもできます。(サンプルソースに含まれています)

また、QPlainTextEditをQComboBoxの置き換えて使用することもできます。(基本的にQWidgetの派生クラスであれば、独自のクラスでも使えます) QTableWidgetは、良く使うクラスですので、色々と応用範囲は広がると思います。

このようなやり方は、ドキュメントをよく読んだ方には、当たり前のことです。 ただ、筆者のようにマニュアルを走り読みしている者には、意外と、はまってしまうのかもしれません。

何かお気づきの点があれば、コメントいただければ幸いです。

もっと、Qt関連について詳しく知りたい方は、以下の本なども良いと思います。
Qtに関する日本語の本が少ないですね。「入門書」は、さすがに、このページを読まれるくらいの方は不要だと思います。
やっぱり、本+ネット+試してみる!!の3本柱でやっていく以外にないように思います。


コメント

コメントをどうぞ







  • はてなブックマークへ追加する
  • Facebookでシェアする
  • twitter でつぶやく
  • Google Plusでシェアする
  • Pocketでシェアする
ページトップへ