2017-08-14 9 views
0

ハードウェアのカスタムボタン(ファンクションキーの組み合わせにマップされています)を持つ画面で使用されるアプリケーションを作成しています。各ボタンは表示される画面を変更するために使用されるので、スタックされたウィジェットは合理的だと思っていました。キーボードイベントQMainWindow inside QMainWindow

開発する私は、これらのボタンがQPushButtonsとして、通常のメインウィンドウが埋め込まれたデバッグウィンドウを作成しました。リリースビルドで実行しているときに、これをメインウィンドウとして実行しようとしていました

これはうまく動作しますが、キープレスイベントは期待通りに伝播しません。 Qtのドキュメントを読むと、フォーカスのあるウィジェットがイベントを受け取ることを示しているので、スタックウィジェットに表示されているウィジェットはキーの押下を受け取りますが、フォーカスの設定に関係なく、常にキーイベントを受け取ります。

デバッグウィンドウ:

DebugWindow::DebugWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::GVADemo) 
{ 
    ui->setupUi(this); 

    MainWindow* main = new MainWindow(this); 
    QLayout* layout = new QHBoxLayout; 
    layout->addWidget(main); 
    layout->setContentsMargins(0,0,0,0); 
    ui->frame->setLayout(layout); 
} 

void GVADemo::keyPressEvent(QKeyEvent *event) 
{ 
    qDebug("GVADemo keyPressEvent %d", event->key()); 
} 

メインウィンドウ:

:積層ウィジェットの画面

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); 

    Screen* screen1 = new Screen(); 

    QStackedWidget* stackedWidget = new QStackedWidget(this); 

    stackedWidget->addWidget(screen1); 
    stackedWidget->setCurrentWidget(screen1); 
    setCentralWidget(stackedWidget); 
} 

void MainWindow::keyPressEvent(QKeyEvent *event) 
{ 
    qDebug("MainWindow keyPressEvent %d", event->key()); 
} 

+0

イベントが配信される前にトリガーされるイベントフィルターをインストールできることを覚えています。 (私は自分でそれをしなかった - したがって、私はこの大まかなヒントを提供することができます...) – Scheff

+0

Qt docをご覧ください。 [イベントフィルタ](http://doc.qt.io/qt-5/eventsandfilters.html#event-filters)これは有望に見えます。 'QEvent :: KeyPress'のサンプルコードも少しあります... – Scheff

+0

もう一つのオプションは、ショートカット(「アクセラレータキー」とも呼ばれるQt世界を超えています)です... [SO:ボタンにショートカットキーを割り当てる - Qt C++ ](https://stackoverflow.com/q/4629629/7478597)、[SO:カスタムキーボードショートカットをプログラミングする方法](https://stackoverflow.com/questions/17631601/how-to-program-custom-keyboard-ショートカット)。 (奇妙なことに、これは私の最初のアイデアではない...) – Scheff

答えて

1

ショートカットキーを使用すると、意図した効果が得られます(実際は非常に簡単です)。

私が質問に記載されたものと同様のMCVEを準備:

// Qt header: 
#include <QtWidgets> 

int main(int argc, char **argv) 
{ 
    qDebug() << "Qt Version: " << QT_VERSION_STR; 
    // main application 
#undef qApp // undef macro qApp out of the way 
    QApplication qApp(argc, argv); 
    // setup GUI 
    QWidget qWin; 
    QGridLayout qGrid; 
    enum { N = 5 }; 
    QStackedLayout qStack; 
    struct Pane { 
    QWidget qWidget; 
    QVBoxLayout qVBox; 
    QLabel qLbl; 
    QLineEdit qTxt; 
    } panes[N]; 
    for (int i = 0; i < N; ++i) { 
    Pane &pane = panes[i]; 
    pane.qLbl.setText(QString::fromUtf8("<b>Pane %0</b>").arg(i + 1)); 
    pane.qLbl.setTextFormat(Qt::RichText); 
    pane.qVBox.addWidget(&pane.qLbl, 1, Qt::AlignCenter); 
    pane.qVBox.addWidget(&pane.qTxt); 
    pane.qWidget.setLayout(&pane.qVBox); 
    qStack.addWidget(&pane.qWidget); 
    } 
    qGrid.addLayout(&qStack, 0, 0, 1, N); 
    qGrid.setRowStretch(0, 1); 
    QPushButton qBtns[N]; 
    for (int i = 0; i < N; ++i) { 
    QPushButton &qBtn = qBtns[i]; 
    qBtn.setText(QString::fromUtf8("F%0").arg(i + 1)); 
    qBtn.setShortcut(Qt::Key_F1 + i); 
    qGrid.addWidget(&qBtn, 1, i); 
    } 
    qWin.setLayout(&qGrid); 
    qWin.show(); 
    // install signal handlers 
    for (int i = 0; i < N; ++i) { 
    QPushButton &qBtn = qBtns[i]; 
    QObject::connect(&qBtn, &QPushButton::clicked, 
     [&qStack, i](bool) { qStack.setCurrentIndex(i); }); 
    } 
    // run application 
    return qApp.exec(); 
} 

私は、Windows 10でのVS2013とQt5.6(64ビット)でコンパイルとテスト:

Snapshot of MCVE

注:

ボタンをクリックしたり、対応するファンクションキーを使用してテストしました。それで、私はQLineEditに焦点を当て、現在フォーカスされているウィジェットとは独立して動作することを確認します。


更新:OPで

、ボタンはハードウェアボタンです。したがって、サンプルの最初のバージョンをQPushButtonを使わずに修正しました。 Windowsの10(64ビット)で

// Qt header: 
#include <QtWidgets> 

int main(int argc, char **argv) 
{ 
    qDebug() << "Qt Version: " << QT_VERSION_STR; 
    // main application 
#undef qApp // undef macro qApp out of the way 
    QApplication qApp(argc, argv); 
    // setup GUI 
    QWidget qWin; 
    QGridLayout qGrid; 
    enum { N = 5 }; 
    QStackedLayout qStack; 
    struct Pane { 
    QWidget qWidget; 
    QVBoxLayout qVBox; 
    QLabel qLbl; 
    QLineEdit qTxt; 
    } panes[N]; 
    for (int i = 0; i < N; ++i) { 
    Pane &pane = panes[i]; 
    pane.qLbl.setText(QString::fromUtf8("<b>Pane %0</b>").arg(i + 1)); 
    pane.qLbl.setTextFormat(Qt::RichText); 
    pane.qVBox.addWidget(&pane.qLbl, 1, Qt::AlignCenter); 
    pane.qVBox.addWidget(&pane.qTxt); 
    pane.qWidget.setLayout(&pane.qVBox); 
    qStack.addWidget(&pane.qWidget); 
    } 
    qGrid.addLayout(&qStack, 0, 0, 1, N); 
    qGrid.setRowStretch(0, 1); 
    QLabel qLbls[N]; 
    for (int i = 0; i < N; ++i) { 
    QLabel &qLbl = qLbls[i]; 
    qLbl.setText(QString::fromUtf8("F%0").arg(i + 1)); 
    qGrid.addWidget(&qLbl, 1, i); 
    } 
    qWin.setLayout(&qGrid); 
    QAction *pQCmds[N]; 
    for (int i = 0; i < N; ++i) { 
    QAction *pQCmd = pQCmds[i] = new QAction(&qWin); 
    pQCmd->setShortcut(Qt::Key_F1 + i); 
    qWin.addAction(pQCmd); 
    } 
    qWin.show(); 
    // install signal handlers 
    for (int i = 0; i < N; ++i) { 
    QObject::connect(pQCmds[i], &QAction::triggered, 
     [&qStack, i](bool) { qStack.setCurrentIndex(i); }); 
    } 
    // run application 
    return qApp.exec(); 
} 

IコンパイルおよびVS2013とQt5.6再び試験:同様の効果が直接メインウィンドウに追加されQAction S(QWidget::addAction()を使用)を用いて達成することができる

Snapshot of MCVE (V2)

注:ファンクションキーがQStackLayoutの現在のインデックスを切り替えるために使用されてきたが

QLineEdit sは(デフォルトでは)集中しています。

+0

@Firedragon質問の "ハードウェアボタン"割り当てを記憶している 'QPushButton'の代わりに' QAction'が使われた2番目のバージョンを追加しました。 – Scheff

関連する問題