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:
ali kettab 2023-11-22 23:04:15 +01:00
parent 01959690cd
commit 41e9fc9a9a
3 changed files with 22 additions and 52 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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()