В верхней части - 5 комбо-боксов
Ниже - собственно сама интерактивная карта метро.
Что происходит при запуске в файле metromap.py ?
1 Сначала инициализируются такие переменные ,
как каталог программы
2 Инициализация класса ReadMap (ReadMap.py),
который прочитает информацию из файла Metro.ini ,
лежащего в подкаталоге /data/.
В нем собрана информация о 13 (для Москвы) линиях метро
с набором станций , геометрическими параметрами из вывода
на экран - координатами , цветом и т.д.
3 Инициализация класса FindPath (FindPath.py) -
обратите внимание на метод waves_accurate ,
который будет срабатывать каждый раз при смене фокуса
в комбобоксах станций .
4 Инициализация класса MapDisplay (MapDisplay.py) ,
который отвечает за GTK GUI
5 Инициализация класса Interface (Interface.py) ,
который отвечает за реализацию этого GUI при всевозможных событиях
6 В вашем домашнем каталоге создается файл ./metromap/rc ,
где сохраняются такие параметры ,как city=Moscow ,xsize=1024,ysize=695
7 Инициализируется список для комбобокса городов
8 Создается обьект класса Interface с параметрами конструктора :
Iface = Interface.Interface(PROGRAM, None, None, citylist = citylist,
citynow = citylist.index(CITY),
xsize = XSIZE, ysize = YSIZE)
и вызываются его методы :
Iface.win.connect('destroy', atexit)
Iface.set_path_cb(list_selected)
Iface.set_station_cb(station_selected)
Iface.set_city_cb(city_changed)
Iface.set_dtime_cb(dtime_changed)
8 Вызывается метод city_changed , в котором читается Metro.ini -
MetroMap = ReadMap(DATAPATH + CITY + '/' + MAPINI)
вывод на экран -
MD = MapDisplay(MetroMap.StCoordinates, MetroMap.StCoordinatesAdd,
MetroMap.LineCoordinates,
img = DATAPATH + CITY + '/' + MetroMap.Map['image'])
обработка телодвижений и поиск кратчайшего пути между выбранными станциями -
Iface.set_path_list([])
Iface.set_da(MD.da)
Iface.set_st_list(snames)
Iface.set_dtime(dtime)
Finder = FindPath(MetroMap.Graph)
Далее приведен сам код start-up - файла metromap.py .
Прошу обратить внимание на грамматику питона :
метод начинается с ключевого слова def ,
а вот заканчивается неочевидно - когда у очередной строки
в начале отсутствует символ табуляции :-)
import pygtk
pygtk.require('2.0')
import gtk
import gobject
import os
import sys
import time
PROGRAM = 'metromap'
MAPENCODING = 'koi8-r'
MAPINI = 'Metro.ini'
MD = None
MDTYPE = "da"
dtime = 0
h = time.localtime()[3]
if h >= 21 or h <= 7:
dtime = 1
CITY = None
XSIZE = None
YSIZE = None
import gettext
binpath = os.path.realpath(os.path.dirname(sys.argv[0]))
if binpath.endswith('/bin'): #FHS
PREFIX = binpath[:binpath.rfind('/bin')]
DATAPATH = PREFIX + '/share/' + PROGRAM + '/data/'
MODULEPATH = PREFIX + '/share/' + PROGRAM + '/modules/'
gettext.bindtextdomain(PROGRAM, PREFIX + '/share/locale/')
else:
PREFIX = binpath
DATAPATH = PREFIX + '/data/'
MODULEPATH = PREFIX + '/modules/'
gettext.bindtextdomain(PROGRAM, PREFIX + '/locale/')
sys.path.insert(1, MODULEPATH)
gettext.textdomain(PROGRAM)
_ = gettext.gettext
from ReadMap import ReadMap
from FindPath import FindPath
if MDTYPE == "da":
from MapDisplay import MapDisplay
else:
from MapDisplayGC import MapDisplay
import Interface
Interface._ = _
RCDIR = os.environ.get('HOME') + "/." + PROGRAM
if not os.path.isdir(RCDIR):
try:
os.mkdir(RCDIR)
except:
pass
if os.path.isfile(RCDIR + "/rc"):
f = file(RCDIR + "/rc", 'r')
done = False
while not done:
s = f.readline()
if not s:
break
p = s.split('=')
if len(p) == 2:
if p[0] == 'city':
CITY = p[1].rstrip()
elif p[0] == 'xsize':
XSIZE = int(p[1].rstrip())
elif p[0] == 'ysize':
YSIZE = int(p[1].rstrip())
f.close()
def atexit(foo):
try:
f = file(RCDIR + "/rc", 'w')
f.write('city=' + CITY + '\n')
f.write('xsize=' + str(Iface.xsize) + '\n')
f.write('ysize=' + str(Iface.ysize) + '\n')
f.close()
except:
pass
gtk.main_quit()
st_start = None
st_end = None
path_list = list()
citylist = filter(lambda a: os.path.isdir(DATAPATH + a), os.listdir(DATAPATH))
if len(citylist) == 0:
print _('No data files found, please install some.')
sys.exit(0)
if not CITY or not CITY in citylist:
if "Moscow" in citylist:
CITY = "Moscow"
else:
CITY = citylist[0]
def station_selected(station, isstart):
global st_start, st_end, path_list
if st_start != station and st_end != station:
if isstart:
st_start = station
Iface.set_from(station)
MD.set_start_station(station)
else:
st_end = station
Iface.set_to(station)
MD.set_stop_station(station)
if st_start != None and st_end != None:
path_list = Finder.waves_accurate(st_start, st_end, MetroMap.WaitLen)
path_list.sort()
if len(path_list):
MD.set_path_list(path_list[0][2:])
else:
MD.set_path_list(None)
Iface.set_path_list(map(lambda a:
_("Minutes: %d Changes: %d") % (a[0], a[1]), path_list))
def list_selected(num):
global path_list
if path_list and num < len(path_list):
MD.set_path_list(path_list[num][2:])
def city_changed(name):
global st_start, st_end, path_list, MetroMap,
MAPENCODING, snames, MD, Finder, prefs, CITY, dtime
CITY = name
st_start = None
st_end = None
path_list = list()
MetroMap = ReadMap(DATAPATH + CITY + '/' + MAPINI)
if not MetroMap.inited:
print _('File ') + DATAPATH + CITY + '/' + MAPINI + _(' corrupt?')
sys.exit(0)
MetroMap.SetDelayTime(dtime)
MAPENCODING = MetroMap.MapEncoding
snames = map(lambda a: [unicode(MetroMap.StNames[a][0] + \
' (' + MetroMap.LineNames[MetroMap.StNames[a][1]] + ')', MAPENCODING), a],
MetroMap.StCoordinates.keys())
snames.sort()
if MD:
del MD
MD = MapDisplay(MetroMap.StCoordinates, MetroMap.StCoordinatesAdd,
MetroMap.LineCoordinates,
img = DATAPATH + CITY + '/' + MetroMap.Map['image'])
Iface.set_path_list([])
Iface.set_da(MD.da)
Iface.set_st_list(snames)
Iface.set_dtime(dtime)
Finder = FindPath(MetroMap.Graph)
MD.set_selection_cb(station_selected)
def dtime_changed(num):
global MetroMap, dtime, st_start
if num != dtime:
dtime = num
MetroMap.SetDelayTime(dtime)
if st_start: #recalculate path's
station = st_start
st_start = None
station_selected(station, True)
Iface = Interface.Interface(PROGRAM, None, None, citylist = citylist,
citynow = citylist.index(CITY),
xsize = XSIZE, ysize = YSIZE)
Iface.win.connect('destroy', atexit)
Iface.set_path_cb(list_selected)
Iface.set_station_cb(station_selected)
Iface.set_city_cb(city_changed)
Iface.set_dtime_cb(dtime_changed)
city_changed(CITY)
gtk.main()
|