#! /usr/bin/env python3 # -*- coding: utf-8 -*- from tkinter import tix as Tix from FlightGear import FlightGear import os import socket import sys PROGNAME = os.path.basename(sys.argv[0]) class PropertyField: def __init__(self, parent, prop, label): self.prop = prop self.field = Tix.LabelEntry( parent, label=label, options=''' label.width 30 label.anchor e entry.width 30 ''' ) self.field.pack( side=Tix.TOP, padx=20, pady=2 ) def update_field(self,fgfs): val = fgfs[self.prop] self.field.entry.delete(0,'end') self.field.entry.insert(0, val) class PropertyPage(Tix.Frame): def __init__(self,parent,fgfs): Tix.Frame.__init__(self,parent) self.fgfs = fgfs self.pack( side=Tix.TOP, padx=2, pady=2, fill=Tix.BOTH, expand=1 ) self.fields = [] def addField(self, prop, label): f = PropertyField(self, prop, label) self.fields.append(f) def update_fields(self): for f in self.fields: f.update_field(self.fgfs) Tix.Frame.update(self) class FGFSDemo(Tix.Frame): def __init__(self,fgfs,root=None): Tix.Frame.__init__(self,root) z = root.winfo_toplevel() z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd()) self.fgfs = fgfs self.pack() self.pages = {} self.after_id = None self.createWidgets() self.update() def createWidgets(self): self.nb = Tix.NoteBook(self) self.nb.add( 'sim', label='Simulation', raisecmd= lambda self=self: self.update_page() ) self.nb.add( 'view', label='View', raisecmd= lambda self=self: self.update_page() ) self.nb.add( 'loc', label='Location', raisecmd= lambda self=self: self.update_page() ) self.nb.add( 'weather', label='Weather', raisecmd= lambda self=self: self.update_page() ) self.nb.add( 'clouds', label='Clouds', raisecmd= lambda self=self: self.update_page() ) self.nb.add( 'velocities', label='Velocities', raisecmd= lambda self=self: self.update_page() ) page = PropertyPage( self.nb.sim, self.fgfs ) self.pages['sim'] = page page.addField( '/sim/aircraft', 'Aircraft:') page.addField( '/sim/presets/airport-id', 'Airport ID:') page.addField( '/sim/time/gmt', 'Current time (GMT):') page.addField( '/sim/presets/trim', 'Trim on ground (true/false):') page.addField( '/sim/sound/enabled', 'Sound enabled (true/false):') page.addField( '/sim/startup/browser-app', 'Web browser:') page = PropertyPage( self.nb.view, self.fgfs ) self.pages['view'] = page page.addField( '/sim/view-mode', 'View mode:') page.addField( "/sim/current-view/field-of-view", "Field of view (deg):" ) page.addField( "/sim/current-view/pitch-offset-deg", "View pitch offset (deg):" ) page.addField( "/sim/current-view/heading-offset-deg", "View heading offset (deg):" ) page = PropertyPage( self.nb.loc, self.fgfs ) self.pages['loc'] = page page.addField( "/position/altitude-ft", "Altitude (ft):" ) page.addField( "/position/longitude-deg", "Longitude (deg):" ) page.addField( "/position/latitude-deg", "Latitude (deg):" ) page.addField( "/orientation/roll-deg", "Roll (deg):" ) page.addField( "/orientation/pitch-deg", "Pitch (deg):" ) page.addField( "/orientation/heading-deg", "Heading (deg):" ) page = PropertyPage( self.nb.weather, self.fgfs ) self.pages['weather'] = page page.addField("/environment/wind-from-heading-deg", "Wind direction (deg FROM):") page.addField("/environment/metar/base-wind-speed-kt", "Wind speed (kt):") page.addField("/environment/metar/gust-wind-speed-kt", "Maximum gust (kt):") page.addField("/environment/wind-from-down-fps", "Updraft (fps):") page.addField("/environment/temperature-degc", "Temperature (degC):") page.addField("/environment/dewpoint-degc", "Dewpoint (degC):") page.addField("/environment/pressure-sea-level-inhg", "Altimeter setting (inHG):") page = PropertyPage( self.nb.clouds, self.fgfs ) self.pages['clouds'] = page page.addField("/environment/clouds/layer[0]/layer-type", "Layer 0 type:") page.addField("/environment/clouds/layer[0]/elevation-ft", "Layer 0 height (ft):") page.addField("/environment/clouds/layer[0]/thickness-ft", "Layer 0 thickness (ft):") page.addField("/environment/clouds/layer[1]/layer-type", "Layer 1 type:") page.addField("/environment/clouds/layer[1]/elevation-ft", "Layer 1 height (ft):") page.addField("/environment/clouds/layer[1]/thickness-ft", "Layer 1 thickness (ft):") page.addField("/environment/clouds/layer[2]/layer-type", "Layer 2 type:") page.addField("/environment/clouds/layer[2]/elevation-ft", "Layer 2 height (ft):") page.addField("/environment/clouds/layer[2]/thickness-ft", "Layer 2 thickness (ft):") page.addField("/environment/clouds/layer[3]/layer-type", "Layer 3 type:") page.addField("/environment/clouds/layer[3]/elevation-ft", "Layer 3 height (ft):") page.addField("/environment/clouds/layer[3]/thickness-ft", "Layer 3 thickness (ft):") page.addField("/environment/clouds/layer[4]/layer-type", "Layer 4 type:") page.addField("/environment/clouds/layer[4]/elevation-ft", "Layer 4 height (ft):") page.addField("/environment/clouds/layer[4]/thickness-ft", "Layer 4 thickness (ft):") page = PropertyPage( self.nb.velocities, self.fgfs ) self.pages['velocities'] = page page.addField("/velocities/airspeed-kt", "Airspeed (kt):") page.addField("/velocities/speed-down-fps", "Descent speed (fps):") self.nb.pack( expand=1, fill=Tix.BOTH, padx=5, pady=5, side=Tix.TOP ) self.QUIT = Tix.Button(self) self.QUIT['text'] = 'Quit' self.QUIT['command'] = self.quitcmd self.QUIT.pack({"side": "bottom"}) def quitcmd(self): if self.after_id: self.after_cancel(self.after_id) #self.quit() self.destroy() def update_page(self): page = self.pages[ self.nb.raised() ] page.update_fields() self.update() self.after_id = self.after( 1000, lambda self=self: self.update_page() ) def main(): if len(sys.argv) != 3: print('Usage: {} host port'.format(PROGNAME)) sys.exit(1) host = sys.argv[1] try: port = int( sys.argv[2] ) except ValueError: print('Error: expected a number for the port argument, not {!r}' .format(sys.argv[2])) sys.exit(1) fgfs = None try: fgfs = FlightGear( host, port ) except socket.error as msg: print('Error connecting to flightgear:', msg.strerror) sys.exit(1) root = Tix.Tk() app = FGFSDemo( fgfs, root ) app.mainloop() if __name__ == '__main__': main()