-------- Original Message -------- Subject: Re: [Tutor] Need Help Modifying a wxPython GUI (scrolling display and logging) Date: Thu, 13 Jun 2013 00:17:44 -0400 From: Matt D <md...@nycap.rr.com> To: Dave Angel <da...@davea.name> On 06/12/2013 09:44 PM, Dave Angel wrote: > On 06/12/2013 09:23 PM, Matt D wrote: >> >>> There are other ways a script might change the current directory. For >>> example, some naive scripts use os.chdir() >>> >>> But how is it you don't know what the current directory was when the >>> code ran? A simply pwd can tell you, if your prompt doesn't already >>> reveal it. >>> >>> >> hey i found the logfile. just took a few minutes of looking round. the >> file is logged all out of order > > Do you have more than one thread? Perhaps you have a race condition. > >> so i have some work to do on that >> formatting issue. if you have a sec can you take a look at my code >> please? >> >> def update(self, field_values): > >> >> # logger code--------------- >> # first write the CURRENT date/time >> self.logfile.write('%s,'%(str(strftime("%Y-%m-%d %H:%M:%S", >> gmtime())))) > > The return value of strftime is already a str, so why do you call str() > on it? > >> # loop through each of the TextCtrl objects >> for k,v in self.fields.items(): > > items() returns an unordered list; what order did you actually want? > >> # get the value of the current TextCtrl field >> f = field_values.get(k, None) >> if f: >> #output the value with trailing comma >> self.logfile.write('%s,'%(str(f))) >> self.logfile.write('\n') > > That looks like a newline, not a comma > >> #end logger code ---------------- >> >> #if the field 'duid' == 'hdu', then clear all the fields >> if field_values['duid'] == 'hdu': >> self.clear() >> #loop through all TextCtrl fields storing the key/value pairs >> in k, v >> for k,v in self.fields.items(): > > Same ordering problem here. If you have a specific order in mind, > you'll need to preserve it in a list, not in a dict. > >> # get the pickle value for this text control >> f = field_values.get(k, None) >> # if the value is empty then set the new value >> if f: >> v.SetValue(f) >> >> >> When i open the .csv file the fields are all out of order. what i want >> is have them all in one row beginning with the date/time. and idea? >> Thanks! >> >> > > A dictionary is unsorted, so those two are probably your problem. As I > mentioned above, you can't count on the items() order. > > Of course, self.items might not really be a dict. This fragment doesn't > prove that one way or another. > > yes the .py file has TextCtrl fields that get there values from a pickled dictionary. Another peice of the code watches a thread for the pickle. this is why i didnt use a list. I have been unable to find a nice way to just make a list with the items i need. would be nice to have that simplicity. What you said is true, the the list is unordered. More importantly the new line comes in at the wrong point. I want all the values in a row starting with time. from there i will look for a way to remove some unwanted items and ordering the others. I attached the .py file for you to see the whole thing hoping this is not too presumptuous. Thanks.
#!/usr/bin/env python # -*- coding: utf-8 -*- # # op25_traffic_panel.py # # Copyright 2013 Balint Seeber <balint@crawfish> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # # the import statements; very similar to #include in c++ # this is the stuff for getting the current time from time import gmtime, strftime import wx import cPickle as pickle import gnuradio.gr.gr_threading as _threading # wx is the gui class. it implements a version of "events" -- objects that sit and wait for some data to change, and call a specified function when the change happens wxDATA_EVENT = wx.NewEventType() # this is a function that *sets* what happens when the event is triggered. it takes in an event (win) and a function (func) (and yes, functions can be passed around just like any other variable in python). def EVT_DATA_EVENT(win, func): win.Connect(-1, -1, wxDATA_EVENT, func) # the dataevent class -- stores the data that gets transmitted when the event occurs. in this case, it is # basically just the data in text fields (stored in self.data as a dictionary, which is basically a c++ map or a c# dictionary). One of these classes gets created whenever an event occurs. class DataEvent(wx.PyEvent): # the values of the text fields get passed into the constructor inside of data def __init__(self, data): wx.PyEvent.__init__(self) # this line *binds* this class to a certain type of event, wxDATA_EVENT self.SetEventType (wxDATA_EVENT) # and this is the actual data self.data = data # clone is a python function to make a "deep" copy of an object; that is, actually copy all the values inside of the object and not just references to them. def Clone (self): self.__class__ (self.GetId()) # the thread that just sits and waits for new data to be received. when it is, the event is triggered, and the new data is passed along. In Python, inheritance is done with parentheses after the class name -- so this class inherits from the standard Python class _threading.Thread. class traffic_watcher_thread(_threading.Thread): def __init__(self, rcvd_pktq, event_receiver): # variables are standard values required to set up a thread _threading.Thread.__init__(self) self.setDaemon(1) self.rcvd_pktq = rcvd_pktq self.event_receiver = event_receiver self.keep_running = True self.start() def stop(self): self.keep_running = False def run(self): while self.keep_running: msg = self.rcvd_pktq.delete_head() # this is the part that is unique to this -- once data is received, an event is "Posted" with PostEvent. This is where the DataEvent object gets created de = DataEvent (msg) wx.PostEvent (self.event_receiver, de) del de # A snapshot of important fields in current traffic # this inherits from the gui class Panel (required for all gui programs) class TrafficPane(wx.Panel): # Initializer # the class constructor def __init__(self, parent, msgq): wx.Panel.__init__(self, parent) self.msgq = msgq #open a file named "logfile.csv" in "w" -- writing -- mode. this will create the file if it doesn't exist. self.logfile = open('logfile.csv', 'w') #layout of the panel. 10 px gap on each side of TextCtrls. panel is a grid, texctrls and lables are placed at grid positions like (1,1), (2,1) etc. sizer = wx.GridBagSizer(hgap=10, vgap=10) # defines a dictionary ({} = empty dictionary), to hold the text control values self.fields = {} #TextCtrl recipe: #creates the first label static text on gui panel label = wx.StaticText(self, -1, "DUID:") #position on the gui panel grid, top left sizer.Add(label, pos=(1,1)) #create the textCtrl field, give it a size, make it read-only field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY) #sticks TextCrtl to grid right of label sizer.Add(field, pos=(1,2)) #add the field for this TextCtrl to the dictionary self.fields["duid"] = field; #same recipe as above for all TextCtrls label = wx.StaticText(self, -1, "NAC:") sizer.Add(label, pos=(2,1)) field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(2,2)) self.fields["nac"] = field; label = wx.StaticText(self, -1, "Source:") sizer.Add(label, pos=(3,1)) field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(3,2)) self.fields["source"] = field; label = wx.StaticText(self, -1, "Destination:") sizer.Add(label, pos=(4,1)) field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(4,2)) self.fields["dest"] = field; label = wx.StaticText(self, -1, "MFID:") sizer.Add(label, pos=(1,4)) field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(1,5)) self.fields["mfid"] = field; label = wx.StaticText(self, -1, "ALGID:") sizer.Add(label, pos=(2,4)) field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(2,5)) self.fields["algid"] = field; label = wx.StaticText(self, -1, "KID:") sizer.Add(label, pos=(3,4)) field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(3,5)) self.fields["kid"] = field; label = wx.StaticText(self, -1, "MI:") sizer.Add(label, pos=(4,4)) field = wx.TextCtrl(self, -1, "", size=(216, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(4,5)) self.fields["mi"] = field; label = wx.StaticText(self, -1, "TGID:") sizer.Add(label, pos=(5,4)) field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(5,5)) self.fields["tgid"] = field; #set the panel layout self.SetSizer(sizer) #makes the gui system fit all the controls onto the panel and figure out absolute positions for all of them based on the sizes and grid positions you've specified self.Fit() EVT_DATA_EVENT(self, self.display_data) self.watcher = traffic_watcher_thread(self.msgq, self) # Clear the field values # def clear(self): #loops through each value in the dictionary -- values are actually text control objects for v in self.fields.values(): # clear the text control value v.Clear() def display_data(self,event): #gets the "message" into the event object -- message is equal to the "data" parameter in the "DataEvent" class message = event.data # unpickle the string pickled_dict = message.to_string() #separate the string into values for each text control (attrs is a pickle object) attrs = pickle.loads(pickled_dict) #pass this pickle object into update self.update(attrs) # Update the field values # def update(self, field_values): # logger code--------------- # first write the CURRENT date/time self.logfile.write('%s,'%(str(strftime("%Y-%m-%d %H:%M:%S", gmtime())))) # loop through each of the TextCtrl objects for k,v in self.fields.items(): # get the value of the current TextCtrl field f = field_values.get(k, None) if f: #output the value with trailing comma self.logfile.write('%s,'%(str(f))) self.logfile.write('\n') #end logger code ---------------- #if the field 'duid' == 'hdu', then clear all the fields if field_values['duid'] == 'hdu': self.clear() #loop through all TextCtrl fields storing the key/value pairs in k, v for k,v in self.fields.items(): # get the pickle value for this text control f = field_values.get(k, None) # if the value is empty then set the new value if f: v.SetValue(f) def main(): return 0 if __name__ == '__main__': main()
_______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor