Module gtkindiclient
[show private | hide private]
[frames | no frames]

Module gtkindiclient

An INDI GUI Library using GTK

It provides functions to connect INDI objects with GTK objects.

Each time an INDI object is received the connected GTK element is updated. Some widgets can be changed by the user. In this case an optional handler can be installed that will send the INDI object to the server each time the user changes widget. The main applications are: Supported platforms are:

Connecting INDI objects to GTK widgets

Connecting in this sense means, that the widget will be updated with the data from its associated INDIobject each time it the INDI object is received. The way how it is updated depends on the type of widget and the type of the INDIobject course. The philosophy used for this update is, to set as many parameters of the widget as possible. A nice example is the Spinbutton. The following parameters of the widget are changed according to the information contained in an indinumber: The advantage of this approach is that you don't have to configure these things. The disadvantage is that you can not customise these parameters of the widget anymore. The methods to connect widgets are listed below: Example:
>>> indi.add_spinbutton(dev,"CCDPREVIEW_CTRL","WIDTH",self.width)

Bidirectional Connections

The add_* functions mentioned in section Connecting INDI objects to GTK widgets return a handler object. If the widget can be changed by the user, the handler object has got a gui_indi_object_handler.set_bidirectional method. If you call it, the handler will link to GTK such a way that it sends an indiobject to the server each time the user changes the widget.

>>> indi.add_spinbutton(dev,"CCDPREVIEW_CTRL","WIDTH",self.width).set_bidirectional()
This works fine as long as GTK provides a the button-release-event key-release-event signals for the widget in question. If not (which is currently only the case for gtkindiclient.add_comboboxentry) we use the changed signal. But this can cause a very unpleasant loopback. We correct for this. The details of this correction are documented in indiclient.gui_indi_object_handler

Building a GUI manually

We strongly recommend to use Glade instead of this approach (see section Building a GUI in a visual way). The example below demonstrates how to build a gui manually.

Important: indiserver must running tutorial_two in order to use this example):
>>> from gtkindiclient import *
>>> import gtk
>>> try:
>>>     def on_delete(*args):
>>>             global running
>>>             running=False
>>> global running
>>> running=True
>>> indi=gtkindiclient("localhost",7624)
>>> mainwindow = gtk.Window(gtk.WINDOW_TOPLEVEL)
>>> mainwindow.connect("delete_event", on_delete)
>>> label=gtk.Label()
>>> indi.add_label("Telescope Simulator","EQUATORIAL_COORD","RA",label)
>>> mainwindow.add(label)
>>> while running:
>>>     indi.process_events()
>>>     while gtk.events_pending():
>>>             gtk.main_iteration_do(False)
>>>     time.sleep(0.01)
>>> indi.quit()
This results in a window showing a sexagesimal number: the right ascension. (see screenshot)

Building a GUI in a visual way

With Glade you can design the GUI of your application in a visual way. Glade produces a .glade file. SimpleGladeApp generates the basic Python code for your GUI writing a .py file, providing callbacks to be implemented by you. You can edit this .py file writing your custom code. If you add a new callback in Glade you can run SimpleGladeApp and the new callback will be added to the .py file and the changes you already made to the .py file will be preserved. In these callbacks you can add the connections between INDIobjects and GTKwidgets. An example for these callbacks is given below. The complete example is given in the file Important: The indiserver must be running tutorial_ccdpreview in order to run this example.

We need to include some files:
>>> # Put your modules and data here
>>> import gtk
>>> from SimpleGladeApp import SimpleGladeApp
>>> from gtkindiclient import *
>>> # From here through main() codegen inserts/updates a class for
>>> # every top-level widget in the .glade file.
We need to implement two callbacks
>>> class Testccd(SimpleGladeApp):
>>> def __init__(self, path="", root="testccd", domain=None, **kwargs):
>>>     path = os.path.join(glade_dir, path)
>>>     SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
>>> def new(self):
>>>     #context {
>>>     indi.add_spinbutton(dev,"CCDPREVIEW_CTRL","WIDTH",self.width).set_bidirectional()
>>>     indi.add_spinbutton(dev,"CCDPREVIEW_CTRL","HEIGHT",self.height).set_bidirectional()
>>>     indi.add_spinbutton(dev,"CCDPREVIEW_CTRL","MAXGOODDATA",self.mgd).set_bidirectional()
>>>     indi.add_spinbutton(dev,"CCDPREVIEW_CTRL","BYTEORDER",
>>>     indi.add_spinbutton(dev,"CCDPREVIEW_CTRL","BYTESPERPIXEL",self.bpp).set_bidirectional()
>>>     indi.add_label(dev,"CCD_INFO","CCD_FWHM_PIXEL",self.fwhm)
>>>     indi.add_label(dev,"CCD_INFO","CCD_PIXEL_SIZE",self.pixsize)
>>>             indi.add_spinbutton(dev,"Telescope","Focus",self.focus).set_bidirectional()
>>>     list=[self.startbutton,self.stopbutton]
>>>     indi.add_togglebuttons(dev,"readout",list).set_bidirectional()                  
>>>     indi.add_ccdpreview(dev,self.drawingarea,self.brightness,self.contrast,self.gamma)      
>>>     #context }
>>> def on_testccd_delete_event(self, widget, *args):
>>>     #context Testccd.on_testccd_delete_event {
>>>     global running
>>>     running=False
>>>     return True
>>>     #context Testccd.on_testccd_delete_event }
And the main method needs to be changed like this:
>>> def main():
>>>     global indi
>>>     global dev
>>>     global running
>>>     try:
>>>             dev="Device with Data Transfer"
>>>             indi=gtkindiclient("localhost",7624)
>>>             indi.enable_blob()
>>>             testccd = Testccd()
>>>             running=True
>>>             while running:
>>>                     indi.process_events()
>>>                     while gtk.events_pending():
>>>                             gtk.main_iteration_do(False)
>>>                     time.sleep(0.01)
>>>             indi.quit()
>>>     except:
>>>             a,b,c =sys.exc_info()
>>>             sys.excepthook(  a,b,c  )
>>>             indi.quit()

And thats it. The GUI is ready to use. (see screenshot) It is very important to keep the #context statement as they are and to implement you code only between the respective #context statements as SimpleGladeApp uses them to determine where your code started and ended, in order to avoid overwriting it.

There are three import commands to call: Have a lot of fun

Version: 0.13

Author: Dirk Huenniger

Contact: dhun (at) astro (dot) uni-bonn (dot) de

Organization: "Hoher List" observatory Daun (Germany)

License: GNU General Public License as published by the Free Software Foundation, version 2


Generated by Epydoc 2.1 on Sat Sep 10 10:26:06 2005