Trolltech Home | Qt-jambi-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-jambi-interest Archive, September 2007
Mapping an interface class with signals to Java


Message 1 in thread

Hello,

I have successfully mapped a custom QWidget subclass written with Qt 4.3.1 to 
Java using Qt Jambi. Everything works well in that regard.

What I now need to do is map the (pure virtual) interface class that the 
widget inherits (together with QWidget) on the C++ side to Java. There will 
be different implementations of the widget which all need to be hidden behind 
the interface class.

The issue is that the interface contains signals. In C++ declaring signals in 
the interface works with or without it subclassing QObject. The code 
generated by QtJambi however does not compile in either case.
If the interface is not subclassed from any Qt class the compiler complains 
about not being able to allocate an object with pure virtual functions 
in 'qtjambishell_XXX.cpp'.
If the interface is subclassed from QObject the compiler complains about 
QObject being an ambiguous base in 'qtjambishell_XXX.cpp'.

What is the correct way of implementing this?
There seems to be no documentation about ambiguous subclassing in the QtJambi 
typesystem documentation.

Thanks for any help.

-- 
 [ signature omitted ] 

Message 2 in thread

Hi, Markus.

Markus wrote:
> The issue is that the interface contains signals. In C++ declaring signals in 
> the interface works with or without it subclassing QObject. The code 
> generated by QtJambi however does not compile in either case.
> If the interface is not subclassed from any Qt class the compiler complains 
> about not being able to allocate an object with pure virtual functions 
> in 'qtjambishell_XXX.cpp'.
> If the interface is subclassed from QObject the compiler complains about 
> QObject being an ambiguous base in 'qtjambishell_XXX.cpp'.
>   

Please excuse if I'm misreading this, but Qt does not support multiple 
inheritance from two subclasses of QObject, as described here:

    
http://doc.trolltech.com/4.3/moc.html#multiple-inheritance-requires-qobject-to-be-first

This means that, if you are actually inheriting both QWidget and another 
QObject subclass, you will unfortunately need to alter the structure of 
your code in order for it to work (for C++ I'm guessing it might be 
feasible to make virtual functions in a non-QObject interface class and 
then override them with signals in your QWidget.) If you detach your 
interface from QObject, you should be able to map it to Java using the 
<interface-type> tag in the type system, as described here:

    
http://doc.trolltech.com/qtjambi-4.3.1_01/com/trolltech/qt/qtjambi-typesystem.html#interface-type

You mention something about declaring signals in the interface without 
it subclassing QObject. My guess is that you mean the "signals" keyword 
still compiles even if it is placed inside a non-QObject-class. This is 
true because the signals-keyword is a macro which expands to "protected" 
which is a valid keyword in any class. Your class will not have signals 
unless it's a QObject subclass, though, because the moc will not produce 
any meta object for the class and your connect statements will not 
recognize the class. Hence, though this seems to work in C++, it really 
doesn't.

Good luck!

-- Eskil


Message 3 in thread

Hello Eskil,

thanks for the reply.

On Monday 03 September 2007 08:39:19 Eskil Abrahamsen Blomfeldt wrote:
> Please excuse if I'm misreading this, but Qt does not support multiple
> inheritance from two subclasses of QObject, as described here:
>
>
> http://doc.trolltech.com/4.3/moc.html#multiple-inheritance-requires-qobject
>-to-be-first
>
> This means that, if you are actually inheriting both QWidget and another
> QObject subclass, you will unfortunately need to alter the structure of
> your code in order for it to work (for C++ I'm guessing it might be
> feasible to make virtual functions in a non-QObject interface class and
> then override them with signals in your QWidget.)
I have been using a virtual non-QObject interface class up to now in C++. 
Checking my code again, I found out that connecting to instances of such a 
QWidget+Interface subclass does not work when cast to the interface. I had 
assumed I was connecting to the instance through the interface but in reality 
I was connecting to the instance cast to the subclass. Sorry for the 
confusion.
Just to clarify, having real signals defined in a virtual interface class is 
thus not possible in (C++) Qt if the implementing class also inherits from 
another QObject (super)class?

> If you detach your 
> interface from QObject, you should be able to map it to Java using the
> <interface-type> tag in the type system, as described here:
This has been working for me if I remove the 'signals' keyword from the C++ 
interface definition.

As a workaround to my issue, would it be possible to (manually) move the 
complete interface definition to the Java side and have real signals in its 
signature there? I could then wrap the converted widgets in a small extra 
class that adds the Java interface to them. In the end I would like to have 
these custom widgets available through a Java interface including signals.

Regards,
-- 
 [ signature omitted ] 

Message 4 in thread

Hi, Markus.

Markus wrote:
> Just to clarify, having real signals defined in a virtual interface class is 
> thus not possible in (C++) Qt if the implementing class also inherits from 
> another QObject (super)class?
>   

That's about right. Only QObject subclasses can contain signals and 
slots in C++, and inheritance of several QObject classes is not 
supported, so having an interface containing signals is not possible. 
You will need to restructure your application so that the signal 
declarations appear in the QObject subclass.

>   
>> If you detach your 
>> interface from QObject, you should be able to map it to Java using the
>> <interface-type> tag in the type system, as described here:
>>     
> This has been working for me if I remove the 'signals' keyword from the C++ 
> interface definition.
>
> As a workaround to my issue, would it be possible to (manually) move the 
> complete interface definition to the Java side and have real signals in its 
> signature there? I could then wrap the converted widgets in a small extra 
> class that adds the Java interface to them. In the end I would like to have 
> these custom widgets available through a Java interface including signals.
>   

In order to have signals in Qt Jambi, you need to subclass 
com.trolltech.qt.QSignalEmitter, so while there are some fewer 
limitations in Qt Jambi than in Qt for C++, you still cannot have 
signals in interfaces. If you are writing all Java code, it would 
probably be possible to have methods in the interface that return the 
signal objects, if that helps. E.g. (code not compile tested or anything =)

    public interface MyInterface {
       public QSignalEmitter.Signal0 mySignal();
    }

    public class MyImplementation extends QSignalEmitter implements 
MyInterface {
       public Signal0 mySignal = new Signal0();
      
       public Signal0 mySignal() { return mySignal; }
    }

-- Eskil


Message 5 in thread

Hello Eskil,

thanks for the tip below. I haven't had time to test it yet but it looks like 
it might work.

Regards,
Markus

On Tuesday 04 September 2007 13:13:14 Eskil Abrahamsen Blomfeldt wrote:
> In order to have signals in Qt Jambi, you need to subclass
> com.trolltech.qt.QSignalEmitter, so while there are some fewer
> limitations in Qt Jambi than in Qt for C++, you still cannot have
> signals in interfaces. If you are writing all Java code, it would
> probably be possible to have methods in the interface that return the
> signal objects, if that helps. E.g. (code not compile tested or anything =)
>
>     public interface MyInterface {
>        public QSignalEmitter.Signal0 mySignal();
>     }
>
>     public class MyImplementation extends QSignalEmitter implements
> MyInterface {
>        public Signal0 mySignal = new Signal0();
>
>        public Signal0 mySignal() { return mySignal; }
>     }





-- 
 [ signature omitted ]