1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ctrl+TabでQTabWidgetのタブを切り替える

Last updated at Posted at 2024-12-19

はじめに

QTabWidget_01.png

Ctrl+Tabでタブを切り替える操作はWindowsではおなじみですが、Qtでは邪道(?)扱いされているようです。

Qt treats Ctrl+Tab as Tab and Ctrl+Shift+Tab as Shift+Tab, ... 《途中省略》
However, since some systems use Ctrl+Tab for other purposes, and many users aren't aware of Ctrl+Tab anyway, this isn't a complete solution.

[Google翻訳]

Qt は Ctrl+Tab を Tab として扱い、Ctrl+Shift+Tab を Shift+Tab として扱います。 《途中省略》
ただし、一部のシステムでは Ctrl+Tab を他の目的に使用しており、いずれにしても多くのユーザーは Ctrl+Tab を認識していないため、これは完全な解決策ではありません。

(あれ?そうなの?)そういう割に、QTabWidgetではCtrl+Tabでタブを切り替えられる場合もあって気持ちが悪いです。
冒頭の例では、QPushButtonやQCheckBoxにフォーカスがあたっている場合はタブが切り替わります。一方で、QComboBoxやQTableWidgetにフォーカスがあたっていると切り替わらないです。
そこで常にCtrl+Tabが効くようにする方策を考えてみました。

まず、カスタムウィジットを作成してイベントフィルタを組み込み、Ctrl+Tabのキーイベントを横取りして親のQTabWidgetへ転送するようにしてみました。
ところが、状態によってはサブクラスにイベントを吸い込まれてしまいました。

例1:QComboBoxのアイテム選択中 →QComboBoxListViewにイベントを吸われる
QTabWidget_03.png

例2:QTableWidgetのアイテム編集中 →QExpandingLineEditにイベントを吸われる
QTabWidget_05.png

main関数にイベントフィルタを組み込めばQComboBoxListViewやQExpandingLineEditのようなサブクラスのイベントを横取りできます。これでCtrl+Tabが常に効くようになり、すっきりしました。
ただし、組み込んだイベントフィルタは高頻度で呼ばれ、すっきりするだけのためにコストかかりすぎかもしれないです。

いちおう実装例:

main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QKeyEvent>

class MyFilter : public QObject
{
protected:
	bool eventFilter(QObject *object, QEvent *event)
	{
		if(event->type() != QEvent::KeyPress)
			return false;
		QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
		if(!(keyEvent->modifiers() & Qt::ControlModifier) ||
		   !(keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab))
			return false;
		const char *p = object->metaObject()->className();
		if(!strcmp(p, "QTableWidget") || !strcmp(p, "QExpandingLineEdit") ||
		   !strcmp(p, "QComboBox") || !strcmp(p, "QComboBoxListView")){		// 必要な場合、追加する
			QWidget *w = qobject_cast<QWidget *>(object->parent());
			while(w){
				if(!strcmp(w->metaObject()->className(), "QTabWidget")){
					qApp->sendEvent(w, event);	// QTabWidgetにキーイベントを転送する
					return true;				// イベントを破棄
				}
				w = qobject_cast<QWidget *>(w->parent());
			}
		}
		return false;
	}
};

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

	MyFilter filter;
	a.installEventFilter(&filter);

	MainWindow w;
	w.show();
	return a.exec();
}

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?