2017-08-14 4 views
0

Ich schreibe eine Anwendung, die auf einem Bildschirm verwendet wird, der über einige benutzerdefinierte Hardware-Schaltflächen verfügt (die Funktionstastenkombinationen zugeordnet sind). Jede Schaltfläche wird verwendet, um den angezeigten Bildschirm zu ändern. Daher dachte ich, dass ein gestapeltes Widget sinnvoll erscheint.Tastaturereignisse QMainWindow in QMainWindow

Um zu entwickeln Ich habe ein Debug-Fenster erstellt, das diese Schaltflächen als QPushButtons hat, mit dem "normalen" Hauptfenster eingebettet. Bei der Ausführung in Release-Build wollte ich dies als Hauptfenster ausführen

Dies funktioniert alles gut, aber Tasten drücken Ereignisse werden nicht wie erwartet verbreitet. Wenn ich die Qt-Dokumentation lese, würde dies bedeuten, dass das Widget mit dem Fokus die Ereignisse erhalten würde. Ich hatte also angenommen, dass das im gestapelten Widget angezeigte Widget den Tastendruck erhält, aber das Debug-Fenster immer die Schlüsselereignisse erhält, unabhängig von der Fokus-Richtlinie

Debug-Fenster:

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

Hauptfenster:

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

Beispiel-Bildschirm für gestapelte widget:

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

void SAScreen::keyPressEvent(QKeyEvent *event) 
{ 
    qDebug("Screen keyPressEvent %d", event->key()); 
} 
+0

Ich erinnere mich, dass Sie Ereignisfilter installieren können, die ausgelöst werden, bevor ein Ereignis "geliefert" wird. (Ich habe es nicht selbst gemacht - daher kann ich nur diesen groben Hinweis geben ...) – Scheff

+0

Bitte werfen Sie einen Blick auf Qt doc. [Ereignisfilter] (http://doc.qt.io/qt-5/eventsandfilters.html#event-filters). Das sieht vielversprechend aus. Es gibt sogar einen kleinen Beispielcode für 'QEvent :: KeyPress' ... – Scheff

+0

Eine andere Option können Verknüpfungen sein (jenseits der Qt-Welt auch" Accelerator Keys "genannt) ... [SO: Tastenkombinationen zu Tasten zuweisen - Qt C++ ] (https://stackoverflow.com/q/4629629/7478597), [SO: So programmieren Sie benutzerdefinierte Tastaturkürzel] (https://stackoverflow.com/questions/17631601/how-to-program-custom-keyboard- Verknüpfungen). (Seltsam, dass das nicht meine erste Idee war ...) – Scheff

Antwort

1

Der beabsichtigte Effekt kann mit Tastenkürzeln erreicht werden (eigentlich sehr einfach).

ich bereit, eine MCVE ähnlich dem, was in der Frage beschrieben wurde:

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

I zusammengestellt und getestet mit VS2013 und Qt5.6 in Windows 10 (64 Bit):

Snapshot of MCVE

Hinweis:

Ich habe das Klicken der Tasten sowie die Verwendung der entsprechenden Funktionstasten getestet. Dabei setze ich den Fokus auf die QLineEdit, um sicher zu gehen, dass es unabhängig vom aktuell fokussierten Widget funktioniert.


Update:

Im OP sind die Tasten Hardware-Tasten. So habe ich die erste Version der Probe so modifiziert, dass sie ohne QPushButton s funktioniert. Der gleiche Effekt kann mit QAction s erreicht werden, die in das Hauptfenster direkt hinzugefügt werden (mit 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(); 
} 

ich zusammengestellt und getestet wieder mit VS2013 und Qt5.6 in Windows 10 (64 Bit):

Snapshot of MCVE (V2)

Hinweis:

die QLineEdit s fokussiert sind (standardmäßig), während die Funktionstasten verwendet worden, den aktuellen Index der QStackLayout zu wechseln.

+0

@Firedragon Ich habe eine zweite Version hinzugefügt, in der 'QAction' anstelle von' QPushButton' verwendet wird, in Erinnerung an die "Hardware Buttons" Zuweisung in Ihrer Frage. – Scheff

Verwandte Themen