如何使用 Qt 将可折叠元素(QMenu、QComboBox)渲染到位图缓冲区?

Posted

技术标签:

【中文标题】如何使用 Qt 将可折叠元素(QMenu、QComboBox)渲染到位图缓冲区?【英文标题】:How can collapsible elements (QMenu, QComboBox) be rendered to a bitmap buffer with Qt? 【发布时间】:2017-09-03 16:30:15 【问题描述】:

在 Qt 中有多种方法可以将 QWidgets 渲染到位图缓冲区(例如 QImage) 这些方法可以是:

QWidget.render(QPainter, ...)
QWidget.grab()
QPixmap::grabWidget(QWidget)
QPixmap::grabWindow( ID )

有很多可能的变体。但是,它们似乎都没有呈现可折叠元素,例如(子)菜单或组合框。

我还在 Qt 中发现了一个可能与之相关的错误报告 QTBUG-10683(如果这是一个错误)

那么,如何将扩展的 QComboBox 或 QMenu 等元素呈现为 QImage 或任何其他位图形式,如 Byte-Array。它应该适用于渲染不可见的屏幕外内容,因此不能通过操作系统捕获当前桌面。我很高兴收到所有提示,不管是 C++、Python 还是只是解释这里发生的事情的文字。

【问题讨论】:

【参考方案1】:

这里的问题是:弹出窗口是独立的窗口。

您可以迭代子窗口并捕获所有子窗口。然后将它们混合成最终图像或只是放入列表中。

要查找小部件是否为独立窗口,您可以使用isWindow 函数。

要捕获隐藏的 UI 元素,您可以使用 qt 元系统:

void captureHiddenItems(QWidget* widget, QList<QImage>& list) 
  if(auto* comboBox = qobject_cast<QComboBox*>(widget)) 
    comboBox->showPopup();
    captureChildWindows(comboBox, list);
    comboBox->hidePopup();
   else if(auto* menubar  = qobject_cast<QMenuBar*>(widget) ) 
    capturePopUpMenus(menubar->actions(), list);
  


void capturePopUpMenus(QList<QAction*> actions, QList<QImage>& list) 
  for(auto* action : actions) 
    if(auto* menu = action->menu()) 
      captureWidget(menu, list);
      capturePopUpMenus(menu->actions(), list);
    
  

【讨论】:

感谢您到目前为止的帮助 - 知道如何确定子窗口的正确相对渲染位置吗? '父位置加父高度'适用于 QComboBox,但我想在 QMenuBar 子菜单中也有更优雅的工作方式?

以上是关于如何使用 Qt 将可折叠元素(QMenu、QComboBox)渲染到位图缓冲区?的主要内容,如果未能解决你的问题,请参考以下文章

Qt 5.4 OS X 如何在 QMenu 和 QToolBar 中使用 QAction,但仅在 QToolbar 中显示图标

如何在 Qt Designer 中删除 QMenu 分隔符?

Qt:删除MainWindow后QMenu似乎没有被删除

QPushButton.setMenu (self, QMenu menu) 使用从 Qt Designer 生成的代码

Qt Connect 触发 QMenu 的 SIGNAL

怎么判断串口已发送完毕?(qt5, c++)