Fix painting logic in wxQt wxClientDC implementation

The original drawing mechanism was generating lots of QWarning messages
when running samples (e.g. htlbox, caret, etc.) and in some cases was
not actually completely drawing every element of the sample. The issue
was that the QPicture was being shared incorrectly between wxWindow and
wxClientDC and attempts to start painting, update, etc. were generating
console warnings.

Closes https://github.com/wxWidgets/wxWidgets/pull/1152
This commit is contained in:
chris2oph
2019-01-31 09:49:11 +00:00
committed by Vadim Zeitlin
parent 7d2e6e805f
commit f8c345ca95
4 changed files with 51 additions and 13 deletions

View File

@@ -10,6 +10,10 @@
#include "wx/qt/dc.h"
#include "wx/scopedptr.h"
class QPicture;
class WXDLLIMPEXP_CORE wxWindowDCImpl : public wxQtDCImpl
{
public:
@@ -35,6 +39,8 @@ public:
~wxClientDCImpl();
private:
wxScopedPtr<QPicture> m_pict;
wxDECLARE_CLASS(wxClientDCImpl);
wxDECLARE_NO_COPY_CLASS(wxClientDCImpl);
};

View File

@@ -145,7 +145,8 @@ public:
// wxQt implementation internals:
virtual QPicture *QtGetPicture() const;
// Caller maintains ownership of pict - window will NOT delete it
void QtSetPicture( QPicture* pict );
QPainter *QtGetPainter();

View File

@@ -27,6 +27,30 @@
//##############################################################################
namespace
{
class QtPictureSetter
{
public:
QtPictureSetter(wxWindow *window, QPicture *pict)
: m_window( window )
{
m_window->QtSetPicture( pict );
}
~QtPictureSetter()
{
m_window->QtSetPicture( NULL );
}
private:
wxWindow* const m_window;
wxDECLARE_NO_COPY_CLASS(QtPictureSetter);
};
}
wxIMPLEMENT_CLASS(wxWindowDCImpl,wxQtDCImpl);
wxWindowDCImpl::wxWindowDCImpl( wxDC *owner )
@@ -54,7 +78,7 @@ wxWindowDCImpl::~wxWindowDCImpl()
}
if ( m_window )
{
// do not destroy as it is owned by the window
// do not destroy in base class as it is owned by the window
m_qtPainter = NULL;
}
}
@@ -67,6 +91,7 @@ wxClientDCImpl::wxClientDCImpl( wxDC *owner )
: wxWindowDCImpl( owner )
{
m_window = NULL;
m_qtPainter = NULL;
}
wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *win )
@@ -74,8 +99,11 @@ wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *win )
{
m_window = win;
QPicture *pic = win->QtGetPicture();
m_ok = m_qtPainter->begin( pic );
m_qtPainter = new QPainter();
m_pict.reset(new QPicture());
m_ok = m_qtPainter->begin( m_pict.get() );
QtPreparePainter();
}
@@ -88,10 +116,11 @@ wxClientDCImpl::~wxClientDCImpl()
{
m_qtPainter->end();
m_ok = false;
QPicture *pict = m_window->QtGetPicture();
if ( m_window != NULL )
{
QtPictureSetter pictureSetter(m_window, m_pict.get());
// get the inner widget in scroll areas:
QWidget *widget;
if ( m_window->QtGetScrollBarsContainer() )
@@ -102,8 +131,8 @@ wxClientDCImpl::~wxClientDCImpl()
}
// force paint event if there is something to replay and
// if not currently inside a paint event (to avoid recursion)
QRect rect = pict->boundingRect();
if ( !pict->isNull() && !widget->paintingActive() && !rect.isEmpty() )
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 );
@@ -111,12 +140,15 @@ wxClientDCImpl::~wxClientDCImpl()
else
{
// Not drawing anything, reset picture to avoid issues in handler
pict->setData( NULL, 0 );
m_pict->setData( NULL, 0 );
}
// let destroy the m_qtPainter (see inherited classes destructors)
m_window = NULL;
}
}
// Painter will be deleted by base class
}
//##############################################################################

View File

@@ -210,7 +210,7 @@ void wxWindowQt::Init()
m_horzScrollBar = NULL;
m_vertScrollBar = NULL;
m_qtPicture = new QPicture();
m_qtPicture = NULL;
m_qtPainter = new QPainter();
m_mouseInside = false;
@@ -251,7 +251,6 @@ wxWindowQt::~wxWindowQt()
DestroyChildren(); // This also destroys scrollbars
delete m_qtPicture;
delete m_qtPainter;
#if wxUSE_ACCEL
@@ -1126,7 +1125,7 @@ bool wxWindowQt::QtHandlePaintEvent ( QWidget *handler, QPaintEvent *event )
{
bool handled;
if ( m_qtPicture->isNull() )
if ( m_qtPicture == NULL )
{
// Real paint event (not for wxClientDC), prepare the background
switch ( GetBackgroundStyle() )
@@ -1558,9 +1557,9 @@ QScrollArea *wxWindowQt::QtGetScrollBarsContainer() const
return m_qtContainer;
}
QPicture *wxWindowQt::QtGetPicture() const
void wxWindowQt::QtSetPicture( QPicture* pict )
{
return m_qtPicture;
m_qtPicture = pict;
}
QPainter *wxWindowQt::QtGetPainter()