Marble/MarblePythonSignalsSlots

    From KDE TechBase
    Revision as of 13:32, 24 November 2013 by Benjaminkaiser (talk | contribs) (Initial creation. Minus the screenshot.)
    (diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
    Basic interaction with MarbleWidget
    Tutorial Series   Marble C++ Tutorial
    Previous   [Projects/Marble/MarblePythonMarbleWidget
    What's Next   Tutorial 4 - Loading KML files into MarbleWidget
    Further Reading   n/a


    Creating a window with controls

    Quick Note: the documentation for the Marble Python bindings are currently not available online. They can instead be found in the source code at the location: src/bindings/python/html/marble/Marble.html.

    We'd like to add other widgets to our Marble window: A zoom slider and a label that shows the current zoom level of the map.

    In order to achieve this we need to create a vertical layout. The layout must be added as the central widget to the application, and have the map, slider and label added to it. Also we zoom the globe to the slider's default value using the MarbleWidget.zoomView(int) method.

    We want to center our globe onto South America. So we create a new GeoDataCoordinates object that takes the longitude and the latitude as a parameter and we call MarbleWidget.centerOn(location).

    As you might have realized already GeoDataCoordinates is the geodetic "sister" of QPoint. They share a very similar API. Additionally GeoDataCoordinates features a nice set of string conversion methods (GeoDataCoordinates.fromString(), GeoDataCoordinates.lonToString() and GeoDataCoordinates.latToString()). They are used in various places inside Marble such as the signal MarbleWidget.mouseMoveGeoPosition(string) .

    Finally we connect the signals and slots that MarbleWidget offers to the signals and slots of the slider and the label (and the label, through a custom method that prefixes the string 'Zoom Level:'):

    #!/usr/bin/env python
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    from PyKDE4.kdeui import *
    from PyKDE4.kdecore import *
    from PyKDE4.marble import *
    import sys
    
    class MainWin (KMainWindow):
        def __init__ (self, *args):
            KMainWindow.__init__ (self)
    	# create the marble widget
            self.marble = Marble.MarbleWidget(self)
            
            # Load the OpenStreetMap map
            self.marble.setMapThemeId("earth/plain/plain.dgml")
            
            # Enable the cloud cover and enable the country borders
            self.marble.setShowClouds(True)
            self.marble.setShowBorders(True)
            
            # Hide the FloatItems: Compass and StatusBar
            self.marble.setShowOverviewMap(False)
            self.marble.setShowScaleBar(False)
            self.marble.setShowCompass(False)
          
            # Change the map to center on Australia
            home = Marble.GeoDataCoordinates(135.0, -25.0, 0.0, Marble.GeoDataCoordinates.Degree)
            self.marble.centerOn(home);
            
            # create the slider
            self.zoomSlider = QSlider(Qt.Horizontal)
            # set the limits of the slider
            self.zoomSlider.setMinimum(1000)
            self.zoomSlider.setMaximum(2400)
            # set a default zoom value
            self.zoomSlider.setValue(1200)
            
            # zoom 
            self.marble.zoomView(self.zoomSlider.value())
            
            # create the position label
            self.zoomLabel = QLabel()
            # show the current zoom level
            self.setZoomLabel(self.zoomSlider.value())
            
            # make elements size correctly
            self.zoomLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
            
            # create the layout
            self.layout_placeholder = QWidget()
            self.layout = QVBoxLayout()
            
            # add all the components
            self.layout.addWidget(self.marble)
            self.layout.addWidget(self.zoomSlider)
            self.layout.addWidget(self.zoomLabel)
            
            # add all the widgets to the layout placeholder
            self.layout_placeholder.setLayout(self.layout)
            # make the layout placeholder the central widget
            self.setCentralWidget(self.layout_placeholder)
            
            # connect slider value to map zoom via signal slots
            self.connect(self.zoomSlider, SIGNAL('valueChanged(int)'), self.marble.zoomView)
            
            # display the zoom level on the label, but pass it though the
            # custom self.setZoomLabel function to add prefix text
            self.connect(self.marble, SIGNAL('zoomChanged(int)'), self.setZoomLabel)
            
            # resize the window
            self.resize(600, 400)
            
            # display the app
            self.show()
        def setZoomLabel(self, value):
          self.zoomLabel.setText("Zoom Level: " + str(value))
            
    
    def main():
        # defaults needed for the KApplication to be initialized
        appName     = "marble_map_widget_controls"
        catalog     = ""
        programName = ki18n ("Marble Map with Controls")
        version     = "1.0"
        description = ki18n ("Using Marble API to control map zoom with a slider.")
        license     = KAboutData.License_GPL
        copyright   = ki18n ("(c) 2008 Your Name")
        text        = ki18n ("none")
        homePage    = "www.example.com"
        bugEmail    = "[email protected]"
    
        aboutData   = KAboutData (appName, catalog, programName, version, description,
                                  license, copyright, text, homePage, bugEmail)
    
        KCmdLineArgs.init(sys.argv, aboutData)
        
        app = KApplication()
        # initialize our window, which will call the MainWindow.__init__ function above
        mainWindow = MainWin(None, "main window")
        # quit the application when the last window closes
        app.connect(app, SIGNAL ("lastWindowClosed ()"), app.quit)
        # run the app
        app.exec_()
    
    main()
    

    Save the code above as marble_controls.py and run it:

    python marble_controls.py
    

    If things go fine, you end up with a map application that displays clouds on top of a flat map with clouds over it (you may need to zoom out):