C++ 在QT窗口中进行DirectX11渲染而不丢失其他小部件
我正在使用DirectX渲染我的QT窗口,在我开始添加控件之前效果很好。然后,当directx在它们上面绘制时,它们会闪烁。 winforms中的解决方案是在表单的OnPaintBackground中进行渲染,但我在QT中没有找到等效的方法。有没有类似的方法,或者可以用更好的方法 我正在考虑渲染到纹理,然后以某种方式将其转换为pixmap,然后在paintEvent()中绘制 对我来说,能够将按钮、面板和其他控件放置在正在渲染的内容之上(实时)是很重要的 编辑 塞尔吉奥·蒙特利昂的回答几乎奏效了,摇曳的控件消失了。我在代码中更改控件的父控件,并将其设置为主窗口,而不是QFrame。但是现在如果我在控件之间快速移动鼠标,控件之间会出现一个奇怪的灰色框。 按钮后面和GroupBox上方的灰色矩形仅在几分之一秒的时间内可见。知道为什么吗 编辑2C++ 在QT窗口中进行DirectX11渲染而不丢失其他小部件,c++,qt,qt5,directx-11,C++,Qt,Qt5,Directx 11,我正在使用DirectX渲染我的QT窗口,在我开始添加控件之前效果很好。然后,当directx在它们上面绘制时,它们会闪烁。 winforms中的解决方案是在表单的OnPaintBackground中进行渲染,但我在QT中没有找到等效的方法。有没有类似的方法,或者可以用更好的方法 我正在考虑渲染到纹理,然后以某种方式将其转换为pixmap,然后在paintEvent()中绘制 对我来说,能够将按钮、面板和其他控件放置在正在渲染的内容之上(实时)是很重要的 编辑 塞尔吉奥·蒙特利昂的回答几乎奏效了
我更改了问题的主题,以描述实际问题,而不是一个解决方案。我猜您正在使用DirectX使用QWidget的本机hWnd绘图。如果是这种情况,另一个Qt控件会闪烁,因为当小部件重新绘制自身时,它也会导致完整的背景更新。然后,使用DirectX在该曲面的顶部绘制,放弃迄今为止Qt控件绘制的任何内容 那么为什么它们会闪烁而不是完全消失呢 QWidget在内部使用双缓冲(查看文档)。 所以这实际上取决于Qt back buffer何时失效
不过,您可以使用一个简单的技巧:在窗口中添加一个QFrame,将Qt控件放在它上面,然后将该帧的hWnd用作DirectX目标。此外,您可能需要将该QFrame的autoFillBackground属性设置为false。这应该允许您渲染到背景。我假定您正在使用QWidget的本机hWnd使用DirectX绘制。如果是这种情况,另一个Qt控件会闪烁,因为当小部件重新绘制自身时,它也会导致完整的背景更新。然后,使用DirectX在该曲面的顶部绘制,放弃迄今为止Qt控件绘制的任何内容 那么为什么它们会闪烁而不是完全消失呢 QWidget在内部使用双缓冲(查看文档)。 所以这实际上取决于Qt back buffer何时失效
不过,您可以使用一个简单的技巧:在窗口中添加一个QFrame,将Qt控件放在它上面,然后将该帧的hWnd用作DirectX目标。此外,您可能需要将该QFrame的autoFillBackground属性设置为false。这应该允许您渲染到背景。多亏了塞尔吉奥·蒙特利昂(Sergio Monteleon)的作品,我想出了两个我认为可以接受的解决方案。 我已将这两种方法上载到github: 方法1-有效但缓慢
- 从QFRAME而不是主窗口获取HWND
- 将DX渲染转换为纹理
- 将其转换为QBitmap并在qframe paintEvent中绘制
- qframe必须在每个帧更新
- 在qframe上渲染DX,将控件放置在qframe顶部(不在中) 如果您在按钮之间疯狂地移动鼠标,当vsync处于启用状态时,按钮之间会出现一个方框闪烁。 当VSync打开时,这种方法在我的机器上实际上速度较慢。这当然是因为什么都没有呈现出来。我没有尝试在这里进行任何重渲染,但我怀疑如果fps降至60左右,即使没有vsync,闪烁也会可见
HRESULT hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast< void** >(&pSurface));
if(hr != S_OK)
return;
context->CopyResource(renderTargetTex, pSurface);
D3D11_MAP eMapType = D3D11_MAP_READ;
D3D11_MAPPED_SUBRESOURCE mappedResource;
context->Map(renderTargetTex, 0, eMapType, NULL, &mappedResource);
BYTE* pYourBytes = (BYTE*)mappedResource.pData;
bitmap = QImage(pYourBytes, windowWidth, windowHeight, QImage::Format_RGBA8888);
context->Unmap(renderTargetTex, 0);
HRESULT hr=swapchain->GetBuffer(0,uidof(ID3D11Texture2D),重新解释强制转换(&pSurface));
如果(hr!=S_正常)
返回;
上下文->复制资源(renderTargetTex、pSurface);
D3D11_MAP eMapType=D3D11_MAP_READ;
D3D11_映射_子资源mappedResource;
上下文->映射(renderTargetTex、0、eMapType、NULL和mappedResource);
BYTE*pYourBytes=(BYTE*)mappedResource.pData;
位图=QImage(pYourBytes,windowWidth,windowHeight,QImage::Format_RGBA8888);
上下文->取消映射(renderTargetTex,0);
此代码仅用于测试该方法,它缺少大多数错误检查,可能会泄漏大量内存。多亏了Sergio Monteleon的帮助,我想出了两个我认为可以接受的解决方案。 我已将这两种方法上载到github: 方法1-有效但缓慢
- 从QFRAME而不是主窗口获取HWND
- 将DX渲染转换为纹理
- 将其转换为QBitmap并在qframe paintEvent中绘制
- qframe必须在每个帧更新
- 在qframe上渲染DX,将控件放置在qframe顶部(不在中) 如果您在按钮之间疯狂地移动鼠标,当vsync处于启用状态时,按钮之间会出现一个方框闪烁。 当VSync打开时,这种方法在我的机器上实际上速度较慢。这当然是因为什么都没有呈现出来。我没有尝试在这里进行任何重渲染,但我怀疑如果fps降至60左右,即使没有vsync,闪烁也会可见