Qt - 从 QMainWindow 向 GLWidget 发送按键事件

Posted

技术标签:

【中文标题】Qt - 从 QMainWindow 向 GLWidget 发送按键事件【英文标题】:Qt - Send key press event to GLWidget from a QMainWindow 【发布时间】:2013-09-28 11:12:07 【问题描述】:

我有一个 Qt/OpenGL/OpenCL 应用程序,其 QMainWindow 包含一个 GLWidget 子类小部件。我想从 QMainWindow 的菜单中为 GLWidget 添加缩放功能(通过按键)。

最初,我直接从 GLWidget 放大/缩小如下(GLWidget.cpp):

void GLWidget::keyPressEvent(QKeyEvent* event) 

  switch(event->key()) 
    case Qt::Key_W:
      zoomScale(zoomFactor_in);
      zoomGlobal = 1.0f / zoomFactor_in;
      break;
    case Qt::Key_X:
      zoomScale(zoomFactor_out);
      zoomGlobal = 1.0f / zoomFactor_out;
      break;        
    default:
      event->ignore();
      break;
  

因此,为了从 QMainWindow 菜单的操作中添加此功能,我创建了信号/插槽 (MainWindow.cpp):

void Ui_MainWindow::createSignals()
 
...
  connect(actionZoom_In, SIGNAL(triggered()), this, SLOT(zoomIn()));     
  connect(actionZoom_Out, SIGNAL(triggered()), this, SLOT(zoomOut()));  


使用以下插槽(我尝试通过这种方式将按键信号发送到 GLwidget“widget_2”):

void Ui_MainWindow::zoomIn()

  QKeyEvent event1 = QKeyEvent(QEvent::KeyPress, Qt::Key_W, Qt::NoModifier);
  QApplication::sendEvent(widget_2, &event1);  


void Ui_MainWindow::zoomOut()

  QKeyEvent event2 = QKeyEvent(QEvent::KeyPress, Qt::Key_X, Qt::NoModifier);
  QApplication::sendEvent(widget_2, &event2);

widget_2 是我为其发送 KeyPress 'X' 或 'W' 的 GLWidget_2。

很遗憾,这不起作用。当我按“X”或“W”时,出现段错误,我不明白为什么?

这是回溯:

(gdb) bt
#0  0x00007ffff6c70e80 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#1  0x00007ffff6c7127f in QMainWindow::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#2  0x00007ffff685d70c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#3  0x00007ffff6862704 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#4  0x00007ffff6328b5e in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#5  0x00007ffff688f8cc in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#6  0x00007ffff6863869 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#7  0x00007ffff6328b5e in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#8  0x000000000047af4e in Ui_MainWindow::zoomIn() ()
#9  0x00007ffff633e54f in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#10 0x00007ffff6857502 in QAction::triggered(bool) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#11 0x00007ffff68576f0 in QAction::activate(QAction::ActionEvent) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#12 0x00007ffff6857857 in QAction::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#13 0x00007ffff685d70c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#14 0x00007ffff6861b8a in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#15 0x00007ffff6328b5e in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#16 0x00007ffff688e474 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#17 0x00007ffff688f983 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#18 0x00007ffff6863869 in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#19 0x00007ffff6328b5e in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#20 0x000000000047af4e in Ui_MainWindow::zoomIn() ()
#21 0x00007ffff633e54f in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#22 0x00007ffff6857502 in QAction::triggered(bool) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#23 0x00007ffff68576f0 in QAction::activate(QAction::ActionEvent) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#24 0x00007ffff6857857 in QAction::event(QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#25 0x00007ffff685d70c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#26 0x00007ffff6861b8a in QApplication::notify(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#27 0x00007ffff6328b5e in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#28 0x00007ffff688e474 in ?? () from /usr/lib/x86_64-linux-gnu/libQtGui.so.4

...

当我从 MainWindow 菜单中单击 actionZoom_In/Out 时同样的问题,除了在第二次单击时发生段错误。

任何人都可以看到有什么问题吗?

【问题讨论】:

为什么不直接调用插槽而不是尝试发送人工事件? 【参考方案1】:

不要自己发送关键事件;让系统完成它的工作。

创建两个插槽:一个用于放大,一个用于缩小。通过主窗口的连接直接从 keyPressEvent 调用它们。

【讨论】:

【参考方案2】:

始终检查事件(任何指针 tbh)是否为 nullptr。甚至 event->ignore() 也会导致 nullptr 上的段错误。 (是的,它确实发生了。Qt 中的函数有时会通过 nullptr 事件调用)

【讨论】:

以上是关于Qt - 从 QMainWindow 向 GLWidget 发送按键事件的主要内容,如果未能解决你的问题,请参考以下文章

C ++ QT如何从QMainWindow布局访问QWidget的公共类成员

Qt:: 如何消除 qmainwindow 中小部件和工具栏之间的间隙

QT中QWidgetQDialog及QMainWindow的区别

(转)QT中QWidgetQDialog及QMainWindow的区别

从 QMainWindow 和 Ui_MainWindow 继承 MainWindow 类

QT:在其他窗口中显示QMainWindow