Overloading virtual method of widget without inheriting (PyQt)

A

Alex Gusarov

Hello, I have strong .NET background with C# and want to do some
familiar things from it with Python, but don't know how. For example,
I created form in qt designer with QCalendarWidget, translated it into
Python module and want to overload virtual method paintCell of
QCalendarWidget. In C# I can write following (abstract) code:

this.calendar.PaintCell += new PaintEventHandler(myPaintCellHandler);

void myPaintCellHandler(object sender, PaintEventArgs e) {
// some work here
}

I can't find how I can do similar thing in Python without inheriting
QCalendarWidget and overloading this method in inherited class (it's
long and I must create additional class). The only thing I done its
full replacement of handler:

calendar.paintCell = myPaintCell

def myPaintCell(self):
pass

Operator += don't work with methods. So, I can't add handler or call
standart handler from my (infinite recursion, cause my handler
replaced standart)

Please, give me some advice, I know Python must be good enough to do
such things fast and elegant.
 
A

Alex Gusarov

class MyPaintCell(PaintCell):
def paintcell(self):
PaintCell.paintcell(self)
myPaintCell(self)

(hmm, only 4 lines, I overestimated the cost. Sorry)

Yeah, that's funny..

I don't want to do it 'cause I create my form within Designer and
simply drop Calendar widget to it. Then I need to translate it
into .py file, it's OK. But if I want to use a custom derived from
Calendar class instead of it, I need after every refreshing/
translating of form replace few lines in translated file.

I just want to know about existence of other method to do this in
class, that contain instance of Calendar.

By "this" I mean:
Instead of calling original method "paintcell" alone, call it with my
custom metod.

Anyway, thanks.
 
D

Diez B. Roggisch

Alex said:
Yeah, that's funny..

I don't want to do it 'cause I create my form within Designer and
simply drop Calendar widget to it. Then I need to translate it
into .py file, it's OK. But if I want to use a custom derived from
Calendar class instead of it, I need after every refreshing/
translating of form replace few lines in translated file.

I just want to know about existence of other method to do this in
class, that contain instance of Calendar.

By "this" I mean:
Instead of calling original method "paintcell" alone, call it with my
custom metod.

You should ask this on the PyQt-mailing-list. And you can try and experiment
with the module new & the function instancemethod in there.

Diez
 
M

marek.rocki

Since the "+=" operator won't work on methods, you have to write your
own class that will simulate dispatching multiple handlers for an
event. Maybe something like the following? I don't know, though, if it
would cooperate with PyQt nicely.

class MultiHandler(object):
def __init__(self, owner, *initial_handlers):
self.owner = owner
self.handlers = list(initial_handlers)
def __iadd__(self, handler):
self.handlers.append(handler)
return self
def __call__(self, *args, **kwargs):
for handler in self.handlers:
handler(self.owner, *args, **kwargs)
return None


class Calendar(object):
def on_paint(self):
print 'i am the default handler'

def handler1(self):
print 'i am handler 1'

def handler2(self):
print 'i am handler 2'


calendar = Calendar()
calendar.on_paint = MultiHandler(calendar, Calendar.on_paint)

calendar.on_paint()
calendar.on_paint += handler1
calendar.on_paint()
calendar.on_paint += handler2
calendar.on_paint()
 
A

Alex Gusarov

class MultiHandler(object):
def __init__(self, owner, *initial_handlers):
...
...
...
calendar = Calendar()
calendar.on_paint = MultiHandler(calendar, Calendar.on_paint)

calendar.on_paint()
calendar.on_paint += handler1
calendar.on_paint()
calendar.on_paint += handler2
calendar.on_paint()

Marek, this seems exactly what I want, thanks, I will try it.
Thanks everybody. Yes, I'm newbie, so may be it was a dumb question,
don't judge me.
 
A

Alex Gusarov

I have a feeling that the form produced by Qt Designer, once converted to
code, contains references to QCalendarWidget where you really want to use a
customized calendar widget. If so, you should "promote" the calendar widget
in Qt Designer to use your widget instead, and make sure you import the
module that supplies it in your application.

David, thanks for noticing about "promoting" within designer, it helped me.
Anyway, IIRC (it's a long time since I used Qt), QT allows to connect
more than one slot with the same signal, so you should not need to
subclass or to create your own multi-dispatcher. Just doing:

calendar.paintCell.signal( SOME_SIGNAL_NAME, my_paint_method )

should work. I don't know which signal you should connect to, however.

This link gives you some detail on signal/slots in PyQT:

Thanks, but actually, paintCell is not a signal, it's simply a virtual
method of caledarwidget.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top