[Kde-bindings] questions about signals and slots in qruby4

Stefano Crocco stefano.crocco at alice.it
Tue Aug 5 07:03:54 UTC 2008


On Monday 04 August 2008, Richard Dale wrote:
> On Sunday 03 August 2008 14:23:10 Stefano Crocco wrote:
> > I have a few questions about signals, slots and connections in qtruby4:
> >
> > * 'connect' if called with an explicit receiver wants a block and raises
> > an error if called in the non-block form. For example, the following code
> > works:
> >
> > require 'Qt4'
> >
> > app =  Qt::Application.new []
> > btn = Qt::PushButton.new "Sender"
> > label = Qt::Label.new "Receiver"
> > btn.connect(SIGNAL('clicked()')){label.clear}
> > btn.show
> > label.show
> > app.exec
> >
> > but if I replace the connect line with:
> >
> > btn.connect(SIGNAL('clicked()'), label, SLOT('clear()'))
> >
> > I get the following error:
> >
> > ./prova.rb:9:in `method_missing': super: no superclass method `connect'
> > (NoMethodError)
> >         from ./prova.rb:9:in `connect'
> >         from ./prova.rb:9
> >
> > (At first, I thought the error might have had been caused by calling
> > connect from the top-level object, given that it spoke about a missing
> > superclass method, but trying it inside an instance method of a
> > Qt::Widget-derived class gave the same result). Is this wanted, or is it
> > a bug? If it is wanted, is there another way to make a connection outside
> > from an instance method of a Qt::Object-derived object? In C++ (I think)
> > you can write:
> >
> > QObject::connect(...)
> >
> > In ruby this doesn't work. Is there another way?
>
> You need to call connect on the label, not on the button like this:
>
> label.connect(btn, SIGNAL('clicked()'), SLOT('clear()'))
>
> And C++ is exactly the same.

You're right. I should have checked the Qt documentation before asking, but 
the idea that it could be something like that didn't even cross my mind: given 
you can do sender.connect(SIGNAL(...)){...}, I automatically assumed 
sender.connect was also the correct way to connect signals to slots.

>
> > * It seems to be impossible to reopen predefined Qt/KDE classes to add
> > signals and slots to them, even if it is possible to add common methods.
> > For example, the following works:
> >
> > require 'Qt4'
> >
> > class Qt::PushButton
> >   def custom_method
> >     puts "custom method"
> >   end
> > end
> >
> > app = Qt::Application.new []
> > w = Qt::PushButton.new
> > w.custom_method
> >
> > Instead, if I try to add a signal, I get an error when I try to connect
> > to it:
> >
> > require 'Qt4'
> >
> > class Qt::PushButton
> >   signals 'custom_signal()'
> > end
> >
> > app = Qt::Application.new []
> > w = Qt::PushButton.new
> > w.connect(SIGNAL('custom_signal()')){puts "custom_signal"}
> >
> > The error message is:
> >
> > /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2706:in `getMetaObject':
> > undefined method `name' for nil:NilClass (NoMethodError)
> >         from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2707:in
> > `getMetaObject' from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2740:in
> > `metaObject' from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2740:in
> > `method_missing'
> >         from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2740:in `connect'
> >         from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2740:in
> > `signal_connect'
> >         from prova.rb:9:in `connect'
> >         from prova.rb:9
> >
> > The same seems to happen for slots. Again, is this simply a bug, or it
> > simply can't be done?
>
> It used to be possible, but after I fixed some other bugs the new
> implementation of the way slots/signals worked with QMetaObjects meant that
> it is now no longer possible. So I wouldn't say it is a bug, but that
> former functionality is no longer present. It may be possible to get it
> working again, but I think adding slots as blocks is a better and more
> rubyish way to achieve the same thing.

Blocks be used instead of slots, but (as far as I know) not in place of 
signals. I can't say that adding signals to standard classes is a common 
operation, but sometimes it can be useful. For example, I came across this 
issue trying to extend KTextEditor::Document with custom methods and instance 
variables. I wanted a signal to be emitted when an instance variable was 
changed, but found out it wasn't possible. Of course, this situation is quite 
exceptional. In most cases, the right thing to do is to create a new class 
subclassing the standard one and add the signal to that. In this case, 
however, I couldn't do that, since I can't instantiate a 
KTextEditor::Document-derived class using Cls.new. In the end, I decided to 
encapsulate the KTextEditor::Document inside a custom class.

Thanks for your answer

Stefano



More information about the Kde-bindings mailing list