我有一个显示图像的wxWidgets C ++应用程序。当图像被另一个窗口遮挡,并且我非常缓慢地拖动另一个窗口以露出图像时,图像经常会显示未被绘制的背景颜色条带。
图像位于位图中,并在滚动窗格中呈现。 OnPaint功能尽可能简单。无论我使用true还是false作为DrawBitmap(“use_mask”)的最后一个参数,行为都是相同的。
void OnPaint(wxPaintEvent &) {
wxPaintDC dc(this);
PrepareDC(dc);
dc.DrawBitmap(bitmap, 0,0, false);
}
我尝试使用wxBufferedPaintDC。问题仍然存在。我该怎么办?
在下图中,我刚刚将Firefox窗口向右缓慢拖动, 透露我的应用程序的图片。
我正在Windows 7,Service Pack 1上进行测试.AMD A6-3620 APU带有Radeon(tm)HD Graphics 2.2 GHz。 VC ++ 2012. wxWidgets 2.9.4。
答案 0 :(得分:1)
禁用擦除背景事件。当wxWidgets想要更新显示时,它会发出两个事件:擦除背景事件和绘制事件。您必须为擦除背景事件实现一个空方法(换句话说:拦截EVT_ERASE_BACKGROUND事件并且不要调用event.Skip())。
由于您的位图覆盖整个面板,因此您无需删除背景。
使用wxClientDC的原因是因为“在EVT_PAINT()处理程序中使用wxPaintDC会自动将剪切区域设置为窗口的受损区域。不会出现在此区域外绘制的尝试。”
由于裁剪区域存在问题,忽略裁剪区域“解决”了问题。
wxPaintDC和wxClientDC类参考文档的详细说明部分对此进行了介绍。
这是一个“更好”答案的草图。这比定时器和重绘所有解决方案要复杂得多,但从某种意义上来说它更好用于系统资源,因此您的应用程序将变得更具响应性。
需要做两件事。
更快速地显示位图
仅重绘位图的损坏区域。
(注意:在wxPaintDC上使用DrawBitmap实际上处理整个位图,然后剪切输出)
为了加快位图部分的显示速度,需要将位图绘制到内存DC中,并将其保存在某处(此解决方案对内存不节俭,但这不是现代计算机的问题; )这样你就可以将你需要的部分插入到wxPaintDC中。
wxMemoryDC memdc;
memdc.SelectObject(bitmap);
dc.Blit( ...
以下是Blit参数http://docs.wxwidgets.org/2.8/wx_wxdc.html#wxdcblit
的说明要仅处理受损区域,您需要调用GetUpdateRegion并使用区域迭代器进行重新运算。我看到你正在使用滚动面板,所以你必须允许这样做,因为更新区域是根据窗口中的客户区域而不是位图中的逻辑区域。
wxRegionIterator upd(GetUpdateRegion());
while ( upd )
{ wxRect rect(upd,GetRect());
// calculate damaged rectangle in terms of your complete bitmap
...
// blit the calculated rectangle from bitmap in memoryDC to damaged recatngle in wxPaintDC
...
upd++;
{
答案 1 :(得分:1)
这是版本2.9.4中的错误。它在先前的稳定版本中没有出现,2.8.12。它似乎只影响滚动的窗口。
目前最好的解决方案可能是使用build 2.8.12。如果这不切实际,您可以使用wxClientDC绘制整个图像来解决问题。最好只偶尔这样做。我想出了一种启发式方法,用于确定条纹可能错过的时间。它基于保留更新区域的近期历史。它会得到假阳性,但不会导致闪烁,至少在我的机器上是这样。
当我知道更多时,我会发布更多内容。
更新Eric Jensen报告说,另一种解决方法是覆盖OnDraw方法来进行绘制,而根本不使用on-paint处理程序。
更新使用Windows Aero主题时,问题不会显现。