2017-08-14 63 views
0

我正在編寫一個應用程序,該應用程序將在具有一些硬件自定義按鈕(映射到功能鍵組合)的屏幕上使用。每個按鈕用於更改顯示的屏幕,所以我認爲堆疊的小部件似乎是合理的。QMainWindow中的鍵盤事件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文檔。 [事件過濾器](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

Snapshot of 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(64位)編譯和VS2013和Qt5.6測試

注意:

我測試過點擊按鈕以及使用相應的功能鍵。因此,我將重點放在QLineEdit上,以確保它獨立於當前關注的小部件工作。


更新:

在OP,按鈕是硬件按鈕。因此,我修改了樣本的第一個版本,但沒有使用QPushButton s。相同的效果可與QAction S的直接加入到主窗口(使用QWidget::addAction())來實現:

// 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(); 
} 

予編譯和VS2013和Qt5.6再次測試在Windows 10(64位):

Snapshot of MCVE (V2)

注:

QLineEdit s的聚焦(每默認),而功能鍵已被用於切換QStackLayout的當前索引。

+0

@Firedragon我加入其中'QAction'是用來代替'QPushButton'記住在你的問題的「硬件按鈕」分配的第二個版本。 – Scheff