Results 1 to 1 of 1

Thread: Key presses get lost after starting external process via QProcess in QWidget

  1. #1
    Join Date
    Jul 2015
    Posts
    22
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Key presses get lost after starting external process via QProcess in QWidget

    Dear all,

    to show my problem I have a minimal working example with a mainwindow that basically consists of
    1) a label on the left that receives key presses
    2) a widget on the right side that opens SumatraPDF.exe (I am on Windows10) via QProcess and displays a PDF
    3) a status bar that displays the number of key presses received on the label and the current focus widget of the QApplication
    In order to run the MWE you need to have SumatraPDF.exe in the QCoreApplication::applicationDirPath()
    Before SumatraPDF has started the label on the left receives all key presses. After it is started I am facing the problem, that the label on the left does not receive key presses any more even if it is the current focus widget. I have added the info to the status bar (as indicated in 3) above) because using breakpoints instead would make it virtually impossible to debug it in any meaningful way.
    Mouse presses do not seem to be affected at all.

    I am using Qt5.15 and QtCreator 4.13.2

    The problem disappears if I switch to Qt4.8!

    Qt Code:
    1. # My .pro file
    2. QT += core gui
    3.  
    4. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    5.  
    6. CONFIG += c++11
    7.  
    8. # You can make your code fail to compile if it uses deprecated APIs.
    9. # In order to do so, uncomment the following line.
    10. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
    11.  
    12. SOURCES += main.cpp \
    13. cpp.cpp
    14.  
    15. HEADERS += h.h
    16.  
    17.  
    18. # Default rules for deployment.
    19. qnx: target.path = /tmp/$${TARGET}/bin
    20. else: unix:!android: target.path = /opt/$${TARGET}/bin
    21. !isEmpty(target.path): INSTALLS += target
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. My main.cpp
    2. #include "h.h"
    3.  
    4. #include <QApplication>
    5.  
    6. int main(int argc, char *argv[])
    7. {
    8. QApplication a(argc, argv);
    9. MainWindow w;
    10. w.show();
    11.  
    12. return a.exec();
    13. }
    To copy to clipboard, switch view to plain text mode 



    Qt Code:
    1. // My h.h
    2. //#ifndef MAINWINDOW_H
    3. //#define MAINWINDOW_H
    4.  
    5. #include <QMainWindow>
    6.  
    7.  
    8. class MainWindow : public QMainWindow
    9. {
    10. Q_OBJECT
    11.  
    12. public:
    13. MainWindow(QWidget *parent = nullptr);
    14. ~MainWindow();
    15. private:
    16. void setupUi();
    17. QString updateMessage();
    18.  
    19. signals:
    20. void updateStatusBar(const QString&, int );
    21.  
    22. private slots:
    23. //void change
    24.  
    25. void applicationFocusChanged(QWidget* old, QWidget* current);
    26. void keyPressOnLabel(int updateCount);
    27.  
    28.  
    29. private:
    30. int labelKeypressCount;
    31. };
    32. //#endif // MAINWINDOW_H
    33.  
    34.  
    35. //#ifndef EXTERNALAPPLICATIONWIDGET_H
    36. //#define EXTERNALAPPLICATIONWIDGET_H
    37.  
    38. #include <QWidget>
    39. #include <QProcess>
    40.  
    41. class QLabel;
    42.  
    43. class ExternalApplicationWidget : public QWidget
    44. {
    45. Q_OBJECT
    46. public:
    47. explicit ExternalApplicationWidget(QWidget *parent = nullptr);
    48. void loadUrl( const QString &fileName);
    49.  
    50. private:
    51. void startProcess(const QString & program, const QStringList & arguments);
    52.  
    53. private slots:
    54. void openPDF();
    55.  
    56. private:
    57. QLabel* filepathLabel;
    58. QWidget *pdfWidget;
    59. HWND hwnd;
    60.  
    61. signals:
    62.  
    63. };
    64.  
    65. //#endif // EXTERNALAPPLICATIONWIDGET_H
    66.  
    67. //#ifndef MYCUSTOMLABEL_H
    68. //#define MYCUSTOMLABEL_H
    69.  
    70. #include <QLabel>
    71. //#include <QDesignerCustomWidgetInterface>
    72. //#include <QtUiPlugin/QDesignerCustomWidgetInterface>
    73.  
    74. class MyCustomLabel : public QLabel
    75. {
    76. Q_OBJECT
    77. public:
    78. explicit MyCustomLabel(QWidget *parent = nullptr);
    79.  
    80. signals:
    81. //void keyPressed(const QString&, int timeout = 0);
    82. void keyPressed(int count);
    83.  
    84. protected:
    85. void mousePressEvent(QMouseEvent *ev) override;
    86. void keyPressEvent(QKeyEvent *ev) override;
    87.  
    88. private:
    89. int countKeypresses;
    90.  
    91. };
    92.  
    93. //#endif // MYCUSTOMLABEL_H
    To copy to clipboard, switch view to plain text mode 


    Qt Code:
    1. // My cpp.cpp
    2. #include "h.h"
    3.  
    4. #include <QApplication>
    5. #include <QFileInfo>
    6. #include <QMessageBox>
    7. #include <QLabel>
    8. #include <QVBoxLayout>
    9. #include <QHBoxLayout>
    10. #include <QPushButton>
    11. #include <QFileDialog>
    12.  
    13.  
    14.  
    15. ExternalApplicationWidget::ExternalApplicationWidget(QWidget *parent) : QWidget(parent)
    16. {
    17. QVBoxLayout* vbox = new QVBoxLayout(this);
    18.  
    19. QWidget* selectPDFWidget = new QWidget(this);
    20. selectPDFWidget->setObjectName("selectPDFWidget");
    21. QHBoxLayout* hbox = new QHBoxLayout(selectPDFWidget);
    22. filepathLabel = new QLabel(this);
    23. filepathLabel->setObjectName("filepathLabel");
    24. hbox->addWidget(filepathLabel);
    25. QPushButton* button = new QPushButton("Select PDF", this);
    26. button->setObjectName("button");
    27. hbox->addWidget(button);
    28. connect(button, SIGNAL(clicked()), this, SLOT(openPDF()));
    29.  
    30. pdfWidget = new QWidget(this);
    31. pdfWidget->setAutoFillBackground( false );
    32. pdfWidget->setAttribute(Qt::WA_NoSystemBackground, true);
    33. pdfWidget->setAttribute(Qt::WA_OpaquePaintEvent, true);
    34. pdfWidget->setObjectName("pdfWidget");
    35. vbox->addWidget(selectPDFWidget, 1);
    36. vbox->addWidget(pdfWidget, 5);
    37. }
    38.  
    39.  
    40. void ExternalApplicationWidget::loadUrl( const QString &fileName)
    41. {
    42. if( !QFileInfo(fileName).exists() ) {
    43. return;
    44. }
    45.  
    46. QString pth = qApp->applicationDirPath() + "/SumatraPDF.exe";
    47. if( !QFile::exists(pth) ) {
    48. QMessageBox::critical(this, "Red alert!",tr("SumatraPDF.exe could not be loaded!"),tr("&Ok"));
    49. return;
    50. }
    51. QString pdf_filepath = QFileInfo(fileName).absoluteFilePath();
    52. filepathLabel->setText(pdf_filepath);
    53.  
    54. args << "-zoom" << "fit page";
    55. args << pdf_filepath;
    56. args << "-plugin" << QString::number((qulonglong)pdfWidget->winId());
    57. startProcess("SumatraPDF.exe",args);
    58. }
    59.  
    60. void ExternalApplicationWidget::startProcess(const QString &program, const QStringList &arguments)
    61. {
    62. p = new QProcess(this); //OK
    63. p->start(program, arguments); // steals "focus" !!!
    64. p->waitForStarted();
    65. }
    66.  
    67. void ExternalApplicationWidget::openPDF()
    68. {
    69. QString fileName = QFileDialog::getOpenFileName(this, tr("Open PDF"), "C:/temp", tr("PDF Files (*.pdf)"));
    70. if( fileName.isEmpty() ) {
    71. return;
    72. }
    73. loadUrl(fileName);
    74. }
    75.  
    76.  
    77. #include <QHBoxLayout>
    78. #include <QMenuBar>
    79. #include <QStatusBar>
    80. #include <QApplication>
    81.  
    82.  
    83. MainWindow::MainWindow(QWidget *parent)
    84. : QMainWindow(parent)
    85. ,labelKeypressCount(0)
    86. {
    87. setupUi();
    88. }
    89.  
    90. MainWindow::~MainWindow()
    91. {
    92. }
    93.  
    94.  
    95. void MainWindow::setupUi()
    96. {
    97. int width = 1400;
    98. int height = 1500;
    99. QWidget* centralwidget = new QWidget(this);
    100. centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
    101. QWidget* horizontalLayoutWidget = new QWidget(centralwidget);
    102. horizontalLayoutWidget->setObjectName(QString::fromUtf8("horizontalLayoutWidget"));
    103. horizontalLayoutWidget->setGeometry(QRect(59, 29, width, height));
    104. QHBoxLayout* horizontalLayout = new QHBoxLayout(horizontalLayoutWidget);
    105. horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
    106. horizontalLayout->setContentsMargins(0, 0, 0, 0);
    107. MyCustomLabel* labelWidget = new MyCustomLabel(horizontalLayoutWidget);
    108. labelWidget->setObjectName(QString::fromUtf8("MyCustomLabel"));
    109. labelWidget->setText("The status bar counts key presses on this label!");
    110.  
    111. horizontalLayout->addWidget(labelWidget);
    112.  
    113. ExternalApplicationWidget* externalApplicationWidget= new ExternalApplicationWidget(horizontalLayoutWidget);
    114. externalApplicationWidget->setObjectName(QString::fromUtf8("ExternalApplicationWidget"));
    115.  
    116. horizontalLayout->addWidget(externalApplicationWidget);
    117. setCentralWidget(centralwidget);
    118. QStatusBar* statusbar = new QStatusBar(this);
    119. statusbar->setObjectName(QString::fromUtf8("statusbar"));
    120. setStatusBar(statusbar);
    121.  
    122. connect(labelWidget, SIGNAL(keyPressed(int)), this, SLOT(keyPressOnLabel(int )));
    123. connect(this, SIGNAL(updateStatusBar(const QString& ,int)), statusbar, SLOT(showMessage(const QString&, int )));
    124.  
    125. if( qApp ) {
    126. connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)), this, SLOT(applicationFocusChanged(QWidget*, QWidget*)));
    127. }
    128.  
    129. resize(width+100, height+100);
    130. }
    131.  
    132.  
    133. QString MainWindow::updateMessage()
    134. {
    135.  
    136. QString msg = "Current focus widget is ";
    137. if( QApplication::focusWidget() ) {
    138. QString name = QApplication::focusWidget()->objectName();
    139. msg += "'";
    140. msg += name ;
    141. msg += "'";
    142. } else {
    143. msg += "NONE";
    144. }
    145. msg += " --- ";
    146. msg += "\n";
    147. msg += "Number of key presses = ";
    148. msg += QString::number(labelKeypressCount);
    149. return msg;
    150. }
    151.  
    152.  
    153. void MainWindow::applicationFocusChanged(QWidget* old, QWidget* current)
    154. {
    155. emit updateStatusBar(updateMessage(), 0);
    156. }
    157.  
    158. void MainWindow::keyPressOnLabel(int updateCount)
    159. {
    160. labelKeypressCount=updateCount;
    161. emit updateStatusBar(updateMessage(), 0);
    162. }
    163.  
    164.  
    165.  
    166. #include <QDebug>
    167.  
    168. MyCustomLabel::MyCustomLabel(QWidget *parent) : QLabel(parent), countKeypresses(0)
    169. {
    170. setWordWrap(true);
    171. }
    172.  
    173. void MyCustomLabel::mousePressEvent(QMouseEvent *ev)
    174. {
    175. qDebug() << "label clicked";
    176. setFocus();
    177. }
    178.  
    179. void MyCustomLabel::keyPressEvent(QKeyEvent *ev)
    180. {
    181. qDebug() << "label: key pressed";
    182. countKeypresses++;
    183. emit keyPressed(countKeypresses);
    184. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by donelron; 18th June 2021 at 14:45.

Similar Threads

  1. Replies: 2
    Last Post: 18th December 2010, 23:13
  2. Replies: 0
    Last Post: 26th August 2010, 11:44
  3. Replies: 0
    Last Post: 11th May 2010, 11:21
  4. problems starting process
    By parsito in forum Qt Programming
    Replies: 8
    Last Post: 11th May 2007, 22:32
  5. Lost line with QProcess
    By starrl in forum Newbie
    Replies: 2
    Last Post: 18th May 2006, 11:45

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.