-------- 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

Reply via email to