[Kde-java] Signals and Slots implemented in Java

Richard Dale Richard_Dale at tipitina.demon.co.uk
Fri Oct 10 17:16:31 CEST 2003


On Thursday 09 October 2003 19:47, Marco Ladermann wrote:
> Because I don't like the signal-slot mechanism, where all the signals and
> slots are identified by strings, I thought about the possibility of a pure
> Java implementation of it. I don't know if the results are of any use for
> QtJava, but maybe someone finds them interesting anyway.
Yes, I found it interesting. But QtJava has to work with existing C++ 
slots/signals as well as java ones, and users wouldn't expect a different 
syntax for C++ vs. java slots - I'm not sure if it's possible to make C++ 
look like your java approach.

> Here is the outcome of my meditation:
>
> 1) Signals can be represented by interfaces extending a tagging interface
> (Signal) and declaring exaclty one method: the signal itself.
I don't like the idea of lots of classes much, I'd rather have all the signal 
type signatures in a single interface.

> 2) Slots are objects of an anonymous class extending a tagging class (Slot)
> that define a single method: the slot.
This looks quite nice, but you are defining the slot as an isolated thing. It 
isn't a void method of MyWidget or whatever, and so it won't have access to 
any of the instance variables etc in the MyWidget environment.

    Slot ClickReceiver = new Slot() {
        void receiveClicks(int clicks) {
            print(clicks);
        }
    };
    
Maybe this?

Slot ClickReceiver = new Slot(target) {
        void receiveClicks(int clicks) {
            target.print(clicks);
        }
    };

You have 'callMethod_in_enclosing_Object' below, but I don't know where it 
would come from.

> 3) Signals and slots are connected by source object, signal class and
> target slot object.
I might have missed something, but I couldn't see the source object being 
used. It looks to me as though the emit() could be called from anywhere, and 
not associated with a specific source object. You need to be able to connect 
signals to signals too. 

> 4) Signals are emitted by first calling the emit method with the signal as
> parameter, which returns a proxy object implementing the signal's
> interface. On this proxy object the signal method can be called, that
> propagates all parameters to the connected slot objects.
I like this idea of emit() returning a Proxy, and the signal being a call on 
that. But I would prefer emit() to be an instance method of QObject and 
subclasses, which would return a Proxy that you could cast to the Signals 
interface you wanted to use:

Eg:
(MyWidgetSignals emit()).clicked(5);

Instead of this in the current QtJava:
emit("clicked", 5);

> Pros:
> Signals and slot are made explicit. They can be found in the javadoc.
> Access modifiers are naturally respected.
> Signal and slot names can't be misspelled, IDE or javac will detect that.
That is certainly a problem with the current implementation in QtJava - if you 
mispell 'clicked()' as 'clacked()', the runtime assumes you meant a java 
signal rather than the intended C++ one. Your target slot is never invoked 
and it isn't obvious why.

There are already <classname>Signals.java interfaces generated for the Qt 
signals, but they aren't actually used to do any type checking on the 
signals. Slots could be represented as an interface too, but even without any 
slot interfaces the connect() call could do a runtime check via reflection to 
confirm there was a void method matching the slot in the string passed to 
connect().

> Cons:
> Syntax is different from C++ Qt
I suppose it comes down to deciding whether we're trying to create a new java 
api as 'javalike' as possible, or to make java code look as much like the 
original Qt C++ style as possible. 

I think one of the big problems with Swing is that you have to keep defining 
loads of clunky little event listeners classes all over the place, whereas 
you don't need to do that with the standard Qt approach. Java would be better 
off with delegates - but that's just my opinion. Lots of small classes with a 
single method to emulate delegates would probably result in cluttered looking 
code.

> Runtime issues because of Proxy usage?
Proxies are fine! I'm a fan..

>
> An example:
>
> Declare the signal in one class and emit it:
>
> class Foo extends Qt {
> ...
>   public interface MySignal extends Signal {
>      void sendOut(String hello);
>   }
>   ...
>      ((MySignal) emit(MySignal.class)).sendOut("Hello, Slots!");
>   ...
> }
>
> Define a slot in another class:
>
> class Bar extends Qt {
> ...
>    public Slot mySlot = new Slot() {
>       void receive(String str) {
>          System.out.println(str);
>          callMethod_in_enclosing_Object(str);
>       }
>    }
> ...
> }
>
> Now in a third class connect signal and slot:
>
> Foo f = new Foo();
> Bar b = new Bar();
>
> connect(f, Foo.MySignal.class, b.mySlot);
>
>
> Okay, that's it. Find enclosed the source and a little test. If it is worth
> a comment, please, comment it!
>
> Marco


More information about the Kde-java mailing list