Fix wxClientDC not working under wxQt
The problem was: wxClientDC draws in a QPicture owned by the DC. In the destructor, QtPictureSetter sets the picture to be used by the associated window and generates a paint event, then resets the picture when it goes out of scope before the paint handler has a chance to replay the image. In this commit, this setup is changed so that window owns the picture instead and is responsible for deleting it when it is actually used.
This commit is contained in:
parent
01959690cd
commit
41e9fc9a9a
3 changed files with 22 additions and 52 deletions
|
|
@ -152,7 +152,7 @@ public:
|
|||
|
||||
// wxQt implementation internals:
|
||||
|
||||
// Caller maintains ownership of pict - window will NOT delete it
|
||||
// Takes ownership of pict - window will delete it
|
||||
void QtSetPicture( QPicture* pict );
|
||||
|
||||
QPainter *QtGetPainter();
|
||||
|
|
@ -244,7 +244,7 @@ private:
|
|||
|
||||
bool QtSetBackgroundStyle();
|
||||
|
||||
QPicture *m_qtPicture; // not owned
|
||||
std::unique_ptr<QPicture> m_qtPicture; // owned by this window
|
||||
std::unique_ptr<QPainter> m_qtPainter; // always allocated
|
||||
|
||||
bool m_mouseInside;
|
||||
|
|
|
|||
|
|
@ -18,36 +18,13 @@
|
|||
|
||||
#include "wx/dcclient.h"
|
||||
#include "wx/qt/dcclient.h"
|
||||
#include "wx/qt/private/converter.h"
|
||||
|
||||
#include <QtWidgets/QScrollArea>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
//##############################################################################
|
||||
|
||||
namespace
|
||||
{
|
||||
class QtPictureSetter
|
||||
{
|
||||
public:
|
||||
QtPictureSetter(wxWindow *window, QPicture *pict)
|
||||
: m_window( window )
|
||||
{
|
||||
m_window->QtSetPicture( pict );
|
||||
}
|
||||
|
||||
~QtPictureSetter()
|
||||
{
|
||||
m_window->QtSetPicture( nullptr );
|
||||
}
|
||||
|
||||
private:
|
||||
wxWindow* const m_window;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(QtPictureSetter);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
wxIMPLEMENT_CLASS(wxWindowDCImpl,wxQtDCImpl);
|
||||
|
||||
wxWindowDCImpl::wxWindowDCImpl( wxDC *owner )
|
||||
|
|
@ -110,30 +87,24 @@ wxClientDCImpl::~wxClientDCImpl()
|
|||
m_qtPainter->end();
|
||||
m_ok = false;
|
||||
|
||||
if ( m_window != nullptr )
|
||||
if ( m_window )
|
||||
{
|
||||
QtPictureSetter pictureSetter(m_window, m_pict.get());
|
||||
|
||||
// get the inner widget in scroll areas:
|
||||
QWidget *widget;
|
||||
if ( m_window->QtGetScrollBarsContainer() )
|
||||
if ( m_pict && !m_pict->isNull() )
|
||||
{
|
||||
widget = m_window->QtGetScrollBarsContainer()->viewport();
|
||||
} else {
|
||||
widget = m_window->GetHandle();
|
||||
}
|
||||
// force paint event if there is something to replay and
|
||||
// if not currently inside a paint event (to avoid recursion)
|
||||
QRect rect = m_pict->boundingRect();
|
||||
if ( !m_pict->isNull() && !widget->paintingActive() && !rect.isEmpty() )
|
||||
{
|
||||
// only force the update of the rect affected by the DC
|
||||
widget->update( rect );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not drawing anything, reset picture to avoid issues in handler
|
||||
m_pict->setData( nullptr, 0 );
|
||||
// force paint event if there is something to replay and
|
||||
// if not currently inside a paint event (to avoid recursion)
|
||||
wxRect rect = wxQtConvertRect(m_pict->boundingRect());
|
||||
if ( !m_window->GetHandle()->paintingActive() && !rect.IsEmpty() )
|
||||
{
|
||||
m_window->QtSetPicture( m_pict.release() );
|
||||
// only force the update of the rect affected by the DC
|
||||
m_window->Refresh(true, &rect);
|
||||
}
|
||||
else // Do we really need the else branch? we are in the dtor anyhow!
|
||||
{
|
||||
// Not drawing anything, reset picture to avoid issues in handler
|
||||
m_pict.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// let destroy the m_qtPainter (see inherited classes destructors)
|
||||
|
|
|
|||
|
|
@ -276,7 +276,6 @@ void wxWindowQt::Init()
|
|||
m_horzScrollBar = nullptr;
|
||||
m_vertScrollBar = nullptr;
|
||||
|
||||
m_qtPicture = nullptr;
|
||||
m_qtPainter.reset(new QPainter());
|
||||
|
||||
m_mouseInside = false;
|
||||
|
|
@ -1315,7 +1314,7 @@ bool wxWindowQt::QtHandlePaintEvent ( QWidget *handler, QPaintEvent *event )
|
|||
{
|
||||
bool handled;
|
||||
|
||||
if ( m_qtPicture == nullptr )
|
||||
if ( !m_qtPicture )
|
||||
{
|
||||
// Real paint event (not for wxClientDC), prepare the background
|
||||
switch ( GetBackgroundStyle() )
|
||||
|
|
@ -1382,7 +1381,7 @@ bool wxWindowQt::QtHandlePaintEvent ( QWidget *handler, QPaintEvent *event )
|
|||
// Data from wxClientDC, paint it
|
||||
m_qtPicture->play( m_qtPainter.get() );
|
||||
// Reset picture
|
||||
m_qtPicture->setData( nullptr, 0 );
|
||||
m_qtPicture.reset();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
|
|
@ -1788,7 +1787,7 @@ QScrollArea *wxWindowQt::QtGetScrollBarsContainer() const
|
|||
|
||||
void wxWindowQt::QtSetPicture( QPicture* pict )
|
||||
{
|
||||
m_qtPicture = pict;
|
||||
m_qtPicture.reset(pict);
|
||||
}
|
||||
|
||||
QPainter *wxWindowQt::QtGetPainter()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue