The problem
I want to create, in Ruby, a new widget called RasterMapView. The strategy for this widget would be to extend the already existing Vizkit ImageView widget.
This is not doable directly, from Alex answer on the ML:
This is not going to work because the ImageView class is not known to ruby. You can only instantiate an instance of the ImageView class which behaves like a QWidget class on the ruby side. Unfortunately all events from the ImageView class are not redirected to the ruby instance so you cannot extend the instance to implement a new behavior. To get this running you have to write qt bindings.
However, due to how Ruby widgets are registered in Vizkit, there actually is a workaround.
The idea is to create a module (not class) that implements the parts that are specific to RasterMapView, and customize the instanciation of RasterMapView when registering it
Code wise, it looks like:
module RasterMapView # Loads the GDAL file at +path+ and displays it in the imageview def load(path) end # This statement does the necessary configuration for this module # to be usable with the UiLoader vizkit_subclass_of 'ImageView' # RasterMapView-specific configuration. vizkit_subclass_of will call this # everytime RasterMapView is used to extend a widget def self.setup(widget) widget.setAspectRatio(true) end end Vizkit::UILoader.register_ruby_widget 'RasterMapView', RasterMapView.method(:new)
Et voila ! One can now do
require 'envire/raster_map_view' Vizkit.default_loader.RasterMapView
Unfortunately, it is not (yet) compatible with loading .ui files. To have a RasterMapView in a qtdesigner UI, you need to add an ImageView and do:
widget = Vizkit.load('widget.ui') widget.image_view.extend RasterMapView
See ruby/envire/raster_map_view.rb in slam/envire for the complete code