Mega Code Archive

 
Categories / Delphi / Examples
 

Understanding VisualCLX

Title: Understanding VisualCLX Question: Beginning with Kylix needs some understanding between signals and slots, the way Linux/Qt deals with events and the Qt-library Answer: VisualCLX is the part of CLX that represents the Visual Components that would noramlly reside in the TWinControl hierarchy in the VCL. VisualCLX framework is a set of classes that represent Visual Controls but have to work (if possible) on both MS Windows and X in Linux. The controls represented by the VisualCLX components are implemented by a C++ class library called Qt and widgets, from the Norwegian development company called Trolltech. Qt is also available on Windows. - The VCL TWinControl class is called TWidgetControl Qt is a C++ class library, cause of differences in C++ and OP (ObjectPascal)details, an OP program cannot directly manipulate Qt widgets. Instead, VisualCLX makes use of an additional library, called the Qt interface library (written in C++ as libqtintf.so) which exports all the Qt functionality in a manner that is accessible to OP code. The import unit for this interface library is called Qt.pas but this means that rather than being declared as classes, the Qt widget methods are all imported as flat methods or strictly speaking functions. We define a flat method as a method of a class that is declared as a standalone subroutine or function. However, since at the C++ side they are indeed classes, almost every flat method takes one extra parameter, which is the reference to the Qt widget. You think this might slow applications but most of the time you won't measure any difference in run-time behaviour. So what's the difference in a architectural manner: In a known OP application, you call methods via object references, e.g.: myButton.setBounds(15, 15, 65, 35); Turning the method into a flat method, the object reference is passed as the first parameter so the method code knows which instance it should be invoking. Here is a "it goes almost like this" example flat method, which is equivalent to the method just used: QButton_SetBounds(myButton, 15, 15, 65, 35); or in a Kylix Qt-manipulation: uses Qt, QTypes; var Btn: QButtonH; Btn := QButton_create(Handle, PChar('Btn')); QButton_setGeometry(Btn, 15, 15, 65, 35); Of course you would normally have no need to write code like this as a QButton does it all for you, but it serves as a simplified example of how CLX components do their thing by using the CLXDisplayAPI. What's the CLXDisplayAPI ------------------------- The CLXDisplay API is the official name for the Qt.pas unit that ships with Kylix and also with Delphi6 or later. It acts as an import unit for the Qt widget library used by VisualCLX. So things in life are a bit more complicated than this. Qt is a C++ class library, and OP cannot direct manipulate C++ classes. Because of this, Borland wrote an additional library to lay between a CLX application and the Qt library. This extra library is called libqtintf.so (the Qt interface library), and Qt.pas is actually the import unit for this interface library. TWidgetControl---Qt.pas-libintf.so---Qt_Widget_Classes Understanding Signal/Slot mechanism ------------------------------------ A hook object is a simple C++ object that exists in the Qt interface library as we said as an intermediary. So you want to customise the reaction of a widget like in windows with eventhandlers, signal/slot play the role: - A signal (event) from a widget - A slot (event handler) responds to a signal So we learnt, it's not possible to have the slot written directly in OP, means the Qt interface library defines a hook class for each widget class. The hook class implements a simple slot for each available widget signal, whose sole job is to call some code in our Kylix application. More on signal / slot and the Way Kylix does: --------------------------------------------- So it seems that messages (callback functions) are not the CLX way of doing things, it means not that CLX provides no support of messages, but it's not the Kylix way of doing things so. We suggest, e.g. mouse movements, that you let CLX respond to the mouse and simply override the methods that CLX uses for those events. Creating a component and need to catch the mouse messages, you can use the following method: procedure MouseMove(shift: TShiftState; X, Y: integer); override; The way we have to think is that in Qt, developers do not respond directly to messages. Instead they work with a signal / slot mechanism and the connect function like QObject::connect(timer, SIGNAL(timeout)), SLOT(timerSlot())); timer - start(1000); or another example to get acustomed to: QObject::connect(myslider, SIGNAL(sliderMoved(in )), mylcdNumber, SLOT(display(in ))); There is nothing special about the sliderMoved and display methods. Just ordinary C++ methods that are marked as signals and slots, just as some Kylix methods are marked as being virtual. QObject is the base class in Qt, just as TObject is the base class in OP (ObjectPascal). QObject has a class or static method named connect. An OP class method is the same thing as a C++ or Java static method. In particular, you can call a class or static method without first creating an instance of the object to which it belongs. And where's the event-loop in Kylix? Here is the event loop that lies at the center of CLX applications: procedure TApplication.HandleMessage; Hooks again and Overview --------------------------- Fact: So you learned that Qt uses a signal and slot mechanism, and CLX uses an event mechanism. It's not so important how the two are connected, it might be valuable some time later, but here is an overview: Qt has a signal and slot mechanism. CLX has an event mechanism. To translate Qt signals and slots into CLX events, the Kylix team created a mechanism known as hooks. Each CLX object type has a hook object. This hook object converts the signals and slot events associated with a particular object into CLX events. It then sends these events to the appropriate CLX control. In particular, there is a CLX method of TWidgetControl named EventFilter that receives the majority of these events. You can find more on this topic on the Kylix2 CompanionTool CD: sams_publishing/kdgch07.pdf chapter 7 CLX architecture & Visual Development or Code Central Entry ID #16795 ---------------------------------------------------------------- Here an impressive extract: If you feel the urge to go beyond the usual CLX API, then here is one of the methods that you want to override: function TWidgetControl.EventFilter(Sender: QObjectH; Event: QEventH): Boolean; This one is the big Kahuna. EventFilter gets most of the events that Qt and the OS throws at it. Just opening up QControls and looking at the 500+ lines that form the implementation of this method is enough to send any sane programmer running for the safety of the standard CLX APIs. However, some people like to live on the edge. They claim that the air is thinner but cleaner out there. function TWidgetControl.MainEventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; var Form: TCustmForm; begin try if csDesigning in ComponentState then begin Form := GetParentForm(Self); if (Form nil) and (Form.DesignerHook nil) and Form.DesignerHook.IsDesignEvent(Self, Sender, Event) then begin Result := True; Exit; end; end; Result := EventFilter(Sender, Event); except Application.HandleException(Self); Result := False; end; end;