From: Kevin A. <al...@se...> - 2001-09-03 16:50:08
|
Below is the start of some documentation for the Button widget. Feel free to make suggestions on wording, layout, etc. I'm not good at documenation, so your suggestions can't be any worse than what I've done. Button is the simplest widget, but most of the other widgets share its attributes and events, so if we can get the Button documenation to a point that we are happy with, we can put the text into an HTML layout and then document the remaining widgets following the same style. I don't have time today, but tomorrow I'm going to look at some other reference works and see if there is a more appropriate format. You can look at spec.py and widget.py to see the specification the framework actually uses and the actual Button class and its methods. ka --- Button Attributes: backgroundColor color: tuple (r, g, b), "named color", or hex color string "#FF00FF" color is always returned as an rgb tuple command string enabled boolean font Font foregroundColor color: tuple (r, g, b), "named color", or hex color string "#FF00FF" color is always returned as an rgb tuple label (mandatory) string name (mandatory, read-only) string position tuple (x, y) specifying -1 for either x or y will use the default x or y position size tuple (width, height) specifying -1 for either width or height will use the default width or height toolTip string visible boolean # I need to revise some of the widget.py code before documenting the 'methods' completely. This section is more of a note to myself than what would go into the online docs. Methods: getId() this should be a read-only attribute The following are also methods, but I think they will be changed. In the case of addEventListener and notifyEventListeners you won't see them anymore, because they will start with a leading underscore and I think setFocus() will just be another attribute. setFocus() see if this works as an attribute focus = 1 or 0 addEventListener, notifyEventListeners should start with an underscore Events: gainFocus loseFocus mouseClick mouseContextDoubleClick mouseContextDown mouseContextUp mouseDoubleClick mouseDown mouseDrag mouseEnter mouseLeave mouseMiddleDoubleClick mouseMiddleDown mouseMiddleUp mouseMove mouseUp Handling events: Events are handled by defining a method handler in the background class. The method name takes the form of 'on_widgetName_event'. For example, to handle a 'mouseClick' for a Button widget with a name of 'button1' you would create a method: def on_button1_mouseClick(self, target, event): print 'hello ' + target.name Which outputs: >>> hello button1 Event order: gainFocus, mouseDown, mouseUp, mouseClick The best way to see events in action is to just start a sample like 'proof' with the Message Watcher (-m command-line option), then uncheck the "Hide unused" checkbox. For example, here is a sequence copied from the Message Watcher, after clicking on 'Button 1' I moved the mouse and clicked on 'Button 2': mouseClick : button1 (mouseMove : button1) (mouseMove : button1) (mouseMove : button1) (mouseLeave : button1) (mouseEnter : button2) (mouseMove : button2) (mouseMove : button2) (mouseMove : button2) (mouseMove : button2) (mouseMove : button2) (mouseMove : button2) (mouseMove : button2) (mouseMove : button2) (mouseMove : button2) (mouseMove : button2) (loseFocus : button1) (gainFocus : button2) (mouseDown : button2) (mouseUp : button2) (mouseClick : button2) (mouseMove : button2) The messages in parenthesis are messages (events) not handled by a method (handler) in the background, so only the 'mouseClick' for 'button1' had a handler in the example above. Example initialization string in a resource (.rsrc.py) file: {'type':'Button', 'name':'button1', 'position':(10, 10), 'label':'Button 1' } |
From: Ronald D S. <rd...@ea...> - 2001-09-03 19:26:03
|
Well, my first Python script or applet was a simple weighted average type of program to help in making decisions that can be analyzed by comparing various options for various criteria, weighted by importance for each criteria, and scored by calculating a simple weighted average for each option and then comparing the scores for various options, with higher scores representing better options. This program is a commnad line Python program that runs OK in IDLE or Pythonwin. My goal is to make it work with a gui user interface. My thinking is that this will be a good learning exercise for me in learning PythonCard. I have previosuly tried to code a gui version of this in Tkinter, but I became frustrated before I had a working version. I think PythonCard is already up to the task of coding a version of my Decision Analysis. Am I right or is it too early for this? I realize that I will need to start from scratch and re-code this completely, since the gui version is so much different; although I welcome any comments to the contrary. I am thinking of using sliders for data entry, although I could use other forms of data input, obviously. If any one has any comments, or general suggetions before I get too far along on this project, please let me know. Since I am a newbie and busy with a full time job, this task may take me awhile, so don't expect immediate results. But once I do get it, maybe the results will be of use somehow. I doubt it would be usefull enough to include in the samples of PythonCard, but anyway, here I go....it's all about learning at this point. I caught on to Python easier than I expected, and I was pleased to be able to do this simple program. But learning gui event driven programming has been hard for me (I suppose learning to really use classes, OOP, gui's and event driven programming all at once is causing me confusion ;-)))). Anyway, I am determined to stick it out with PythonCard though. Ron Stephens # # This is a decision analysis program that was my first real Python program, based on weighted # averages of scores on several criteria for various questions that need to be decided. # There is a general program for any kind of decision, allowing user input of options # to be decided amongst and criteria to use for decisions; and then there are a few # examples of specific options to be decided amongst with pre-coded "values' or scores # for the various options for various criteria. # It is my goal to code this program using PythonCard. print "A General Decision Analysis Program." print print "Have You Ever Had to Make Up Your Mind?" print import sys def get_number(prompt, lower=sys.maxint * -1, upper=sys.maxint): """ get_number(prompt) -> float This function prompts for a number. If the user enters bad input, such as 'cat' or '3l', it will prompt again. Now checks for upper and lower bounds. """ res = None while res is None: try: res = float(raw_input(prompt)) try: assert lower <= res <= upper except AssertionError: print "Value must be between", lower, \ "and", upper res = None except ValueError: pass return res def get_list(heading, prompt): print heading print print "(enter a blank line to end the list)" ret = [] i = 1 while 1: line = raw_input(prompt % i) if not line: break ret.append(line) i=i+1 print return ret def get_user_rankings(criteria): # Next, get the user to rank his criteria. I use a system where higher # is better, so that an undesirable characteristic can be given a negative # weight. # # {} is a dictionary, it can be indexed by (nearly) any expression, # and we will index it with the names of the criteria. rankings = {} print print "Enter relative importance of criteria (higher is more important)" print for c in criteria: rankings[c] = get_number("Criterion %s: " % c) return rankings def get_user_scores(options, criteria): # Next, get the user to score each option on all the criteria. # Scores are stored as a two-dimensional dictionary, like so: # {'option1': {'criteria1': 100, 'criteria2': 10}, # 'option2': {'criteria1': 50, 'criteria2': 10} # } scores = {} print print "Enter score for each option on each criterion" print for o in options: scores[o] = {} print print "Scores for option %s" % o print for c in criteria: scores[o][c] = get_number("Criterion %s: " % c) return scores def calculate_results(options, scores, rankings): # Calculate the resulting score for each option. This equation # is different from Rod Stephen's original program, because I # make more important criteria have higher rankings, and even let # bad criteria have negative rankings. # The "result" dictionary is indexed with the names of the options. result = {} # Criteria can be found automatically, doesn't need to be # passed as an argument. criteria = scores[options[0]].keys() for o in options: value = 0 for c in criteria: # print o, c, rankings[c], scores[o][c] value = value + rankings[c] * scores[o][c] result[o] = value return result def ranked_list(results): # Now, I want to take the dictionary result, and turn it into a ranked list results = results.items() # A list of tuples (key, value) results.sort(lambda x, y: -cmp(x[1], y[1])) # Sort the list using the reverse of the # "value" of the entry, so that higher # values come first return results def generic_decision_analyzer(options, criteria): pass def decisionanalysis(): # This code is placed in the public domain print print "This is a general decision program, and you can define your choices and criteria." print print "When prompted, please enter the options or choices that you need to decide amongst." print print "Then, when prompted, enter the criteria for making this decision." # First, ask the user to enter the lists options = get_list("Enter your options:", "Option %d: ") criteria = get_list("Now, enter your criteria:", "Criterion %d: ") print "A program to help you make decisions." rankings = get_user_rankings(criteria) scores = get_user_scores(options, criteria) results = ranked_list(calculate_results(options, scores, rankings)) print print "Results, in order from highest to lowest score" print print "%5s\t%s" % ("Score", "Option") # Take the pairs out of results in order, and print them out for option, result in results: print "%5s\t%s" % (result, option) # Here's the scores used by the language-choice functions. language_scores = {"Python": {"ease of learning":100, "ease of use":100, "speed of program execution":10, "quality of available tools":70, "popularity":50, "power & expressiveness":100, "cross platform?":100, "cost":100}, "Perl": {"ease of learning":50, "ease of use":60, "speed of program execution":20, "quality of available tools":50, "popularity":85, "power & expressiveness":70, "cross platform?":100, "cost":100}, "Ruby": { "ease of learning":50, "ease of use":100, "speed of program execution":20, "quality of available tools":20, "popularity":10, "power & expressiveness":100, "cross platform?":80, "cost":100}, "Tcl": {"ease of learning":100, "ease of use":100, "speed of program execution":10, "quality of available tools":50, "popularity":40, "power & expressiveness":10, "cross platform?":100, "cost":100}, "JavaScript": {"ease of learning":70, "ease of use":75, "speed of program execution":10, "quality of available tools":50, "popularity":100, "power & expressiveness":40, "cross platform?":50, "cost":100}, "Visual Basic": {"ease of learning":50, "ease of use":100, "speed of program execution":20, "quality of available tools":100, "popularity":100, "power & expressiveness":50, "cross platform?":1, "cost":1}, "Java": {"ease of learning":15, "ease of use":50, "speed of program execution":50, "quality of available tools":100, "popularity":90, "power & expressiveness":100, "cross platform?":100, "cost":100}, "C++": {"ease of learning":10, "ease of use":25, "speed of program execution":90, "quality of available tools":90, "popularity":80, "power & expressiveness":100, "cross platform?":90, "cost":100}, "C": {"ease of learning":15, "ease of use":20, "speed of program execution":100, "quality of available tools":80, "popularity":80, "power & expressiveness":80, "cross platform?":110, "cost":100}, "Lisp": {"ease of learning":40, "ease of use":50, "speed of program execution":80, "quality of available tools":60, "popularity":25, "power & expressiveness":110, "cross platform?":80, "cost":90}, "Delphi": {"ease of learning":50, "ease of use":110, "speed of program execution":85, "quality of available tools":100, "popularity":30, "power & expressiveness":100, "cross platform?":80, "cost":10} } def ProgramLanguageFinal(): print "This is a program to help give you an idea which programming languages you should consider learning." print "While there are any number of languages you might consider, this program considers only 11 of the most popluar ones." print print "The program will ask you to input a ranking or weighting for a number of criteria that may be of importance" print "in choosing your next programming language." # First look up the criteria listed in the scores. # To do that, we need a language name, which can also # be looked up from the scores. languages = language_scores.keys() some_language = languages[0] criteria = language_scores[some_language].keys() rankings = get_user_rankings(criteria) results = ranked_list(calculate_results(languages, language_scores, rankings)) # Take the pairs out of results in order, and print them out for option, result in results: print "%5s\t%s" % (result, option) def ProgramLanguageScript(): print print "This is a program to help you choose a scripting language." print print "You will be asked to rank some important criteria as to their relative importance to you." print "These criteria are 'ease of learning', 'ease of use', 'speed of program execution'" "'quality of available tools', 'popularity', and 'power & expressiveness'" print print "Please rank each of the criteria with a number from 1 to 100 when prompted." print print "100 means of highest relative importance, 1 means of least importance." # This time we want a subset of languages, so I'm going to specify them. options = ["Python", "Perl", "Ruby", "Tcl", "JavaScript", "Visual Basic"] criteria = language_scores[options[0]].keys() rankings = get_user_rankings(criteria) results = ranked_list(calculate_results(options, language_scores, rankings)) # Take the pairs out of results in order, and print them out for option, result in results: print "%5s %s" % (result, option) def Basketball(): print "This is a program to help you decide which team will win a basketball game" print print "When prompted, enter a number ranking each team on the prompted team skill" print "on a scale from 1 to 100, with 1 being terrible and 100 being the best imaginable" print team_one = raw_input ("What is the name of team one: ") team_two = raw_input ("What is the name of team two: ") teams = (team_one, team_two) rankings = {"speed":100, "size":66, "jumping_ability":50, "defense":60, "shooting":75, "ballhandling":50, "rebounding":50} criteria = rankings.keys() scores = {team_one: {}, team_two: {}} for c in criteria: for team in (team_one, team_two): scores[team][c] = get_number("rank the team %s of %s on a scale of 1 to 100: " % (c, team), 1, 100) results = calculate_results(teams, scores, rankings) for team in teams: print "%s has a power ranking of %d" % (team, results[team]) # Now, who won? ranked_results = ranked_list(results) # Compare the scores. if ranked_results[0][1] == ranked_results[1][1]: print "the two teams are a toss-up!!!" else: print "%s wins!!" % ranked_results[0][0] def YesNo(): print "Program to help you make a Yes or No decision." options = ["Yes", "No"] criteria = get_list("Enter your criteria ...", "Criterion %d: ") rankings = get_user_rankings(criteria) scores = get_user_scores(options, criteria ) print `scores` results = ranked_list(calculate_results(options, scores, rankings)) print print "The results are" print print "%5s %s" % ("Score", "Option") for option, result in results: print "%5s %s" % (result, option) if results[0] > results[1]: print "You should decide Yes!!!" else: print print "You should decide No!!!" print ###### MAIN LOOP ############ while 1: # loop forever print "Please enter the number for the type of decision you wish to analayze:" print "1. General Decision Analysis, you choose the options, criteria, etc." print "2. Help in Choosing Programming Language amongst 11 popular languages" print "3. Help in choosing scripting programming language amongst 6 scripting languages" print "4. Which Basketball Team will win the Game???" print "5. Questions with Yes or No type answers" choice = get_number("Please type in the number of the type of decision-program you wish to run from above and hit enter:", 1, 5) if choice ==1: decisionanalysis() elif choice ==2: ProgramLanguageFinal() elif choice ==3: ProgramLanguageScript() elif choice ==4: Basketball() elif choice ==5: YesNo() elif choice =="quit": break # exit from infinite loop else: print "Invalid operation" |
From: Kevin A. <al...@se...> - 2001-09-04 01:03:47
|
The short answer is that you should be able to do this in PythonCard. When you run into specific problems related to PythonCard, just post the questions here. It sounds like a lot of your journey is going to be learning to design a non-modal visual interface for a program that was previously a linear series of steps. Off the top of my head I'm not sure what resources to point you towards, hopefully someone else on the list can provide some pointers. Validators: One thing that PythonCard definitely doesn't provide you with right now are 'validators' which are sort of like your 'get_number' function below. We'll probably have validators later, wxPython even provides a hook for them, but for now you'll probably want to make it more like an HTML form where the user enters input in a bunch of fields, and then presses a "Submit" or "Calculate" button and if one of the fields has invalid input you will present an error message and they can redo the input. You could also check the input with a 'loseFocus' handler and when we have a closeField messages being generated this will be even simpler; closeField means that not only did the field lose focus, but that the text changed too. Turn on the Message Watcher and uncheck 'Hide unused' to see these events occurring as you tab and click between fields. Anyway, in the short term what you can do is have a 'gainFocus' handler which saves the current value of the field in variable, then a 'loseFocus' handler which compares the original value to the current value and if they are different (text changed), then it will do your validation test and if the data isn't valid, you present an error dialog and then set the focus back to the field and select all the text. That is a very common user interface for text validation in GUIs. Other people on the list can probably suggest other methods. This is the kind of thing I'll try and add to one of the samples, unless someone beats me to it. ka > -----Original Message----- > From: pyt...@li... > [mailto:pyt...@li...]On Behalf Of Ronald > D Stephens > Sent: Monday, September 03, 2001 12:34 PM > To: pyt...@li... > Subject: [Pythoncard-users] Decision Analysis , a Python script to be > re-coded in PythonCard > > > Well, my first Python script or applet was a simple weighted > average type of program to help in making decisions that can be > analyzed by comparing various options for various criteria, > weighted by importance for each criteria, and scored by calculating a > simple weighted average for each option and then comparing the > scores for various options, with higher scores representing better > options. > > This program is a commnad line Python program that runs OK in > IDLE or Pythonwin. > > My goal is to make it work with a gui user interface. My thinking > is that this will be a good learning exercise for me in learning > PythonCard. > > I have previosuly tried to code a gui version of this in Tkinter, > but I became frustrated before I had a working version. > > I think PythonCard is already up to the task of coding a version > of my Decision Analysis. Am I right or is it too early for this? > > I realize that I will need to start from scratch and re-code this > completely, since the gui version is so much different; although I > welcome any comments to the contrary. > > I am thinking of using sliders for data entry, although I could > use other forms of data input, obviously. > > If any one has any comments, or general suggetions before I get > too far along on this project, please let me know. > > Since I am a newbie and busy with a full time job, this task may > take me awhile, so don't expect immediate results. But once I do > get it, maybe the results will be of use somehow. I doubt it > would be usefull enough to include in the samples of PythonCard, but > anyway, here I go....it's all about learning at this point. > > I caught on to Python easier than I expected, and I was pleased > to be able to do this simple program. But learning gui event driven > programming has been hard for me (I suppose learning to really > use classes, OOP, gui's and event driven programming all at once is > causing me confusion ;-)))). Anyway, I am determined to stick it > out with PythonCard though. > > > Ron Stephens > > # > # This is a decision analysis program that was my first real > Python program, based on weighted > # averages of scores on several criteria for various questions > that need to be decided. > # There is a general program for any kind of decision, allowing > user input of options > # to be decided amongst and criteria to use for decisions; and > then there are a few > # examples of specific options to be decided amongst with > pre-coded "values' or scores > # for the various options for various criteria. > # It is my goal to code this program using PythonCard. > > > > print "A General Decision Analysis Program." > print > print "Have You Ever Had to Make Up Your Mind?" > print > > import sys > > def get_number(prompt, lower=sys.maxint * -1, upper=sys.maxint): > """ get_number(prompt) -> float > > This function prompts for a number. If the user enters bad input, such as > 'cat' or '3l', it will prompt again. > Now checks for upper and lower bounds. > """ > res = None > while res is None: > try: > res = float(raw_input(prompt)) > try: > assert lower <= res <= upper > except AssertionError: > print "Value must be between", lower, \ > "and", upper > res = None > except ValueError: pass > > > return res > > > def get_list(heading, prompt): > > print heading > print > print "(enter a blank line to end the list)" > ret = [] > i = 1 > while 1: > line = raw_input(prompt % i) > if not line: > break > ret.append(line) > i=i+1 > print > return ret > > def get_user_rankings(criteria): > # Next, get the user to rank his criteria. I use a system > where higher > # is better, so that an undesirable characteristic can be > given a negative > # weight. > # > # {} is a dictionary, it can be indexed by (nearly) any expression, > # and we will index it with the names of the criteria. > > rankings = {} > print > print "Enter relative importance of criteria (higher is more > important)" > print > for c in criteria: > rankings[c] = get_number("Criterion %s: " % c) > return rankings > > def get_user_scores(options, criteria): > # Next, get the user to score each option on all the criteria. > # Scores are stored as a two-dimensional dictionary, like so: > # {'option1': {'criteria1': 100, 'criteria2': 10}, > # 'option2': {'criteria1': 50, 'criteria2': 10} > # } > scores = {} > print > print "Enter score for each option on each criterion" > print > for o in options: > scores[o] = {} > print > print "Scores for option %s" % o > print > for c in criteria: > scores[o][c] = get_number("Criterion %s: " % c) > return scores > > def calculate_results(options, scores, rankings): > # Calculate the resulting score for each option. This equation > # is different from Rod Stephen's original program, because I > # make more important criteria have higher rankings, and even let > # bad criteria have negative rankings. > > # The "result" dictionary is indexed with the names of the options. > result = {} > # Criteria can be found automatically, doesn't need to be > # passed as an argument. > criteria = scores[options[0]].keys() > for o in options: > value = 0 > for c in criteria: > # print o, c, rankings[c], scores[o][c] > value = value + rankings[c] * scores[o][c] > result[o] = value > return result > > def ranked_list(results): > # Now, I want to take the dictionary result, and turn it into > a ranked list > > results = results.items() # A list of tuples (key, value) > results.sort(lambda x, y: -cmp(x[1], y[1])) > # Sort the list using the reverse of the > # "value" of the entry, so that higher > # values come first > return results > > > def generic_decision_analyzer(options, criteria): > pass > > def decisionanalysis(): > # This code is placed in the public domain > print > print "This is a general decision program, and you can define > your choices and criteria." > print > print "When prompted, please enter the options or choices > that you need to decide amongst." > print > print "Then, when prompted, enter the criteria for making > this decision." > > > # First, ask the user to enter the lists > options = get_list("Enter your options:", "Option %d: ") > criteria = get_list("Now, enter your criteria:", "Criterion %d: ") > > print "A program to help you make decisions." > rankings = get_user_rankings(criteria) > scores = get_user_scores(options, criteria) > results = ranked_list(calculate_results(options, scores, rankings)) > print > print "Results, in order from highest to lowest score" > print > print "%5s\t%s" % ("Score", "Option") > > # Take the pairs out of results in order, and print them out > for option, result in results: > print "%5s\t%s" % (result, option) > > > > # Here's the scores used by the language-choice functions. > language_scores = {"Python": {"ease of learning":100, > "ease of use":100, > "speed of program execution":10, > "quality of available tools":70, > "popularity":50, > "power & expressiveness":100, > "cross platform?":100, > "cost":100}, > "Perl": {"ease of learning":50, > "ease of use":60, > "speed of program execution":20, > "quality of available tools":50, > "popularity":85, > "power & expressiveness":70, > "cross platform?":100, > "cost":100}, > "Ruby": { "ease of learning":50, > "ease of use":100, > "speed of program execution":20, > "quality of available tools":20, > "popularity":10, > "power & expressiveness":100, > "cross platform?":80, > "cost":100}, > "Tcl": {"ease of learning":100, > "ease of use":100, > "speed of program execution":10, > "quality of available tools":50, > "popularity":40, > "power & expressiveness":10, > "cross platform?":100, > "cost":100}, > "JavaScript": {"ease of learning":70, > "ease of use":75, > "speed of program execution":10, > "quality of available tools":50, > "popularity":100, > "power & expressiveness":40, > "cross platform?":50, > "cost":100}, > "Visual Basic": {"ease of learning":50, > "ease of use":100, > "speed of program execution":20, > "quality of available tools":100, > "popularity":100, > "power & expressiveness":50, > "cross platform?":1, > "cost":1}, > "Java": {"ease of learning":15, > "ease of use":50, > "speed of program execution":50, > "quality of available tools":100, > "popularity":90, > "power & expressiveness":100, > "cross platform?":100, > "cost":100}, > "C++": {"ease of learning":10, > "ease of use":25, > "speed of program execution":90, > "quality of available tools":90, > "popularity":80, > "power & expressiveness":100, > "cross platform?":90, > "cost":100}, > "C": {"ease of learning":15, > "ease of use":20, > "speed of program execution":100, > "quality of available tools":80, > "popularity":80, > "power & expressiveness":80, > "cross platform?":110, > "cost":100}, > "Lisp": {"ease of learning":40, > "ease of use":50, > "speed of program execution":80, > "quality of available tools":60, > "popularity":25, > "power & expressiveness":110, > "cross platform?":80, > "cost":90}, > "Delphi": {"ease of learning":50, > "ease of use":110, > "speed of program execution":85, > "quality of available tools":100, > "popularity":30, > "power & expressiveness":100, > "cross platform?":80, > "cost":10} > } > > > > def ProgramLanguageFinal(): > print "This is a program to help give you an idea which > programming languages you should consider learning." > print "While there are any number of languages you might > consider, this program considers only 11 of the most popluar ones." > print > print "The program will ask you to input a ranking or > weighting for a number of criteria that may be of importance" > print "in choosing your next programming language." > > # First look up the criteria listed in the scores. > # To do that, we need a language name, which can also > # be looked up from the scores. > languages = language_scores.keys() > some_language = languages[0] > criteria = language_scores[some_language].keys() > rankings = get_user_rankings(criteria) > results = ranked_list(calculate_results(languages, > language_scores, rankings)) > # Take the pairs out of results in order, and print them out > for option, result in results: > print "%5s\t%s" % (result, option) > > > def ProgramLanguageScript(): > print > print "This is a program to help you choose a scripting language." > print > print "You will be asked to rank some important criteria as > to their relative importance to you." > print "These criteria are 'ease of learning', 'ease of use', > 'speed of program execution'" > "'quality of available tools', 'popularity', and 'power & > expressiveness'" > print > print "Please rank each of the criteria with a number from 1 > to 100 when prompted." > print > print "100 means of highest relative importance, 1 means of > least importance." > > # This time we want a subset of languages, so I'm going to > specify them. > options = ["Python", "Perl", "Ruby", "Tcl", "JavaScript", > "Visual Basic"] > criteria = language_scores[options[0]].keys() > rankings = get_user_rankings(criteria) > results = ranked_list(calculate_results(options, > language_scores, rankings)) > # Take the pairs out of results in order, and print them out > for option, result in results: > print "%5s %s" % (result, option) > > > def Basketball(): > print "This is a program to help you decide which team will > win a basketball game" > print > print "When prompted, enter a number ranking each team on the > prompted team skill" > print "on a scale from 1 to 100, with 1 being terrible and > 100 being the best imaginable" > print > team_one = raw_input ("What is the name of team one: ") > team_two = raw_input ("What is the name of team two: ") > teams = (team_one, team_two) > > rankings = {"speed":100, "size":66, "jumping_ability":50, > "defense":60, "shooting":75, "ballhandling":50, "rebounding":50} > criteria = rankings.keys() > scores = {team_one: {}, > team_two: {}} > for c in criteria: > for team in (team_one, team_two): > scores[team][c] = get_number("rank the team %s of %s > on a scale of 1 to 100: " % (c, team), 1, 100) > > results = calculate_results(teams, scores, rankings) > for team in teams: > print "%s has a power ranking of %d" % (team, results[team]) > # Now, who won? > ranked_results = ranked_list(results) > # Compare the scores. > if ranked_results[0][1] == ranked_results[1][1]: > print "the two teams are a toss-up!!!" > else: > print "%s wins!!" % ranked_results[0][0] > > > def YesNo(): > print "Program to help you make a Yes or No decision." > options = ["Yes", "No"] > criteria = get_list("Enter your criteria ...", "Criterion %d: ") > > rankings = get_user_rankings(criteria) > scores = get_user_scores(options, criteria ) > print `scores` > results = ranked_list(calculate_results(options, scores, rankings)) > print > print "The results are" > print > print "%5s %s" % ("Score", "Option") > > for option, result in results: > print "%5s %s" % (result, option) > > if results[0] > results[1]: > print "You should decide Yes!!!" > > else: > print > print "You should decide No!!!" > print > > > ###### MAIN LOOP ############ > > while 1: # loop forever > > print "Please enter the number for the type of decision you > wish to analayze:" > print "1. General Decision Analysis, you choose the options, > criteria, etc." > print "2. Help in Choosing Programming Language amongst 11 > popular languages" > print "3. Help in choosing scripting programming language > amongst 6 scripting languages" > print "4. Which Basketball Team will win the Game???" > print "5. Questions with Yes or No type answers" > choice = get_number("Please type in the number of the type of > decision-program you wish to run from above and hit enter:", 1, 5) > > if choice ==1: > decisionanalysis() > elif choice ==2: > ProgramLanguageFinal() > elif choice ==3: > ProgramLanguageScript() > elif choice ==4: > Basketball() > elif choice ==5: > YesNo() > elif choice =="quit": > break # exit from infinite loop > else: > print "Invalid operation" > > > > > > > > > > > > > > _______________________________________________ > Pythoncard-users mailing list > Pyt...@li... > https://lists.sourceforge.net/lists/listinfo/pythoncard-users > |
From: Ronald D S. <rd...@ea...> - 2001-09-04 10:33:27
|
Thanks, Kevin. I will be quietly working on this in the background. Your pointers will be of help to me. Once I get a reasonable facsimile of this running, I'll share it with the group. And I'll probably have specific questions along the way. Ron Stephens ----- Original Message ----- From: "Kevin Altis" <al...@se...> To: <pyt...@li...> Sent: Monday, September 03, 2001 9:04 PM Subject: RE: [Pythoncard-users] Decision Analysis , a Python script to be re-coded in PythonCard > The short answer is that you should be able to do this in PythonCard. When > you run into specific problems related to PythonCard, just post the > questions here. It sounds like a lot of your journey is going to be learning > to design a non-modal visual interface for a program that was previously a > linear series of steps. Off the top of my head I'm not sure what resources > to point you towards, hopefully someone else on the list can provide some > pointers. > > Validators: > One thing that PythonCard definitely doesn't provide you with right now are > 'validators' which are sort of like your 'get_number' function below. We'll > probably have validators later, wxPython even provides a hook for them, but > for now you'll probably want to make it more like an HTML form where the > user enters input in a bunch of fields, and then presses a "Submit" or > "Calculate" button and if one of the fields has invalid input you will > present an error message and they can redo the input. > > You could also check the input with a 'loseFocus' handler and when we have a > closeField messages being generated this will be even simpler; closeField > means that not only did the field lose focus, but that the text changed too. > Turn on the Message Watcher and uncheck 'Hide unused' to see these events > occurring as you tab and click between fields. > > Anyway, in the short term what you can do is have a 'gainFocus' handler > which saves the current value of the field in variable, then a 'loseFocus' > handler which compares the original value to the current value and if they > are different (text changed), then it will do your validation test and if > the data isn't valid, you present an error dialog and then set the focus > back to the field and select all the text. That is a very common user > interface for text validation in GUIs. Other people on the list can probably > suggest other methods. > > This is the kind of thing I'll try and add to one of the samples, unless > someone beats me to it. > > ka > > > -----Original Message----- > > From: pyt...@li... > > [mailto:pyt...@li...]On Behalf Of Ronald > > D Stephens > > Sent: Monday, September 03, 2001 12:34 PM > > To: pyt...@li... > > Subject: [Pythoncard-users] Decision Analysis , a Python script to be > > re-coded in PythonCard > > > > > > Well, my first Python script or applet was a simple weighted > > average type of program to help in making decisions that can be > > analyzed by comparing various options for various criteria, > > weighted by importance for each criteria, and scored by calculating a > > simple weighted average for each option and then comparing the > > scores for various options, with higher scores representing better > > options. > > > > This program is a commnad line Python program that runs OK in > > IDLE or Pythonwin. > > > > My goal is to make it work with a gui user interface. My thinking > > is that this will be a good learning exercise for me in learning > > PythonCard. > > > > I have previosuly tried to code a gui version of this in Tkinter, > > but I became frustrated before I had a working version. > > > > I think PythonCard is already up to the task of coding a version > > of my Decision Analysis. Am I right or is it too early for this? > > > > I realize that I will need to start from scratch and re-code this > > completely, since the gui version is so much different; although I > > welcome any comments to the contrary. > > > > I am thinking of using sliders for data entry, although I could > > use other forms of data input, obviously. > > > > If any one has any comments, or general suggetions before I get > > too far along on this project, please let me know. > > > > Since I am a newbie and busy with a full time job, this task may > > take me awhile, so don't expect immediate results. But once I do > > get it, maybe the results will be of use somehow. I doubt it > > would be usefull enough to include in the samples of PythonCard, but > > anyway, here I go....it's all about learning at this point. > > > > I caught on to Python easier than I expected, and I was pleased > > to be able to do this simple program. But learning gui event driven > > programming has been hard for me (I suppose learning to really > > use classes, OOP, gui's and event driven programming all at once is > > causing me confusion ;-)))). Anyway, I am determined to stick it > > out with PythonCard though. > > > > > > Ron Stephens > > > > # > > # This is a decision analysis program that was my first real > > Python program, based on weighted > > # averages of scores on several criteria for various questions > > that need to be decided. > > # There is a general program for any kind of decision, allowing > > user input of options > > # to be decided amongst and criteria to use for decisions; and > > then there are a few > > # examples of specific options to be decided amongst with > > pre-coded "values' or scores > > # for the various options for various criteria. > > # It is my goal to code this program using PythonCard. > > > > > > > > print "A General Decision Analysis Program." > > print > > print "Have You Ever Had to Make Up Your Mind?" > > print > > > > import sys > > > > def get_number(prompt, lower=sys.maxint * -1, upper=sys.maxint): > > """ get_number(prompt) -> float > > > > This function prompts for a number. If the user enters bad input, such as > > 'cat' or '3l', it will prompt again. > > Now checks for upper and lower bounds. > > """ > > res = None > > while res is None: > > try: > > res = float(raw_input(prompt)) > > try: > > assert lower <= res <= upper > > except AssertionError: > > print "Value must be between", lower, \ > > "and", upper > > res = None > > except ValueError: pass > > > > > > return res > > > > > > def get_list(heading, prompt): > > > > print heading > > print > > print "(enter a blank line to end the list)" > > ret = [] > > i = 1 > > while 1: > > line = raw_input(prompt % i) > > if not line: > > break > > ret.append(line) > > i=i+1 > > print > > return ret > > > > def get_user_rankings(criteria): > > # Next, get the user to rank his criteria. I use a system > > where higher > > # is better, so that an undesirable characteristic can be > > given a negative > > # weight. > > # > > # {} is a dictionary, it can be indexed by (nearly) any expression, > > # and we will index it with the names of the criteria. > > > > rankings = {} > > print > > print "Enter relative importance of criteria (higher is more > > important)" > > print > > for c in criteria: > > rankings[c] = get_number("Criterion %s: " % c) > > return rankings > > > > def get_user_scores(options, criteria): > > # Next, get the user to score each option on all the criteria. > > # Scores are stored as a two-dimensional dictionary, like so: > > # {'option1': {'criteria1': 100, 'criteria2': 10}, > > # 'option2': {'criteria1': 50, 'criteria2': 10} > > # } > > scores = {} > > print > > print "Enter score for each option on each criterion" > > print > > for o in options: > > scores[o] = {} > > print > > print "Scores for option %s" % o > > print > > for c in criteria: > > scores[o][c] = get_number("Criterion %s: " % c) > > return scores > > > > def calculate_results(options, scores, rankings): > > # Calculate the resulting score for each option. This equation > > # is different from Rod Stephen's original program, because I > > # make more important criteria have higher rankings, and even let > > # bad criteria have negative rankings. > > > > # The "result" dictionary is indexed with the names of the options. > > result = {} > > # Criteria can be found automatically, doesn't need to be > > # passed as an argument. > > criteria = scores[options[0]].keys() > > for o in options: > > value = 0 > > for c in criteria: > > # print o, c, rankings[c], scores[o][c] > > value = value + rankings[c] * scores[o][c] > > result[o] = value > > return result > > > > def ranked_list(results): > > # Now, I want to take the dictionary result, and turn it into > > a ranked list > > > > results = results.items() # A list of tuples (key, value) > > results.sort(lambda x, y: -cmp(x[1], y[1])) > > # Sort the list using the reverse of the > > # "value" of the entry, so that higher > > # values come first > > return results > > > > > > def generic_decision_analyzer(options, criteria): > > pass > > > > def decisionanalysis(): > > # This code is placed in the public domain > > print > > print "This is a general decision program, and you can define > > your choices and criteria." > > print > > print "When prompted, please enter the options or choices > > that you need to decide amongst." > > print > > print "Then, when prompted, enter the criteria for making > > this decision." > > > > > > # First, ask the user to enter the lists > > options = get_list("Enter your options:", "Option %d: ") > > criteria = get_list("Now, enter your criteria:", "Criterion %d: ") > > > > print "A program to help you make decisions." > > rankings = get_user_rankings(criteria) > > scores = get_user_scores(options, criteria) > > results = ranked_list(calculate_results(options, scores, rankings)) > > print > > print "Results, in order from highest to lowest score" > > print > > print "%5s\t%s" % ("Score", "Option") > > > > # Take the pairs out of results in order, and print them out > > for option, result in results: > > print "%5s\t%s" % (result, option) > > > > > > > > # Here's the scores used by the language-choice functions. > > language_scores = {"Python": {"ease of learning":100, > > "ease of use":100, > > "speed of program execution":10, > > "quality of available tools":70, > > "popularity":50, > > "power & expressiveness":100, > > "cross platform?":100, > > "cost":100}, > > "Perl": {"ease of learning":50, > > "ease of use":60, > > "speed of program execution":20, > > "quality of available tools":50, > > "popularity":85, > > "power & expressiveness":70, > > "cross platform?":100, > > "cost":100}, > > "Ruby": { "ease of learning":50, > > "ease of use":100, > > "speed of program execution":20, > > "quality of available tools":20, > > "popularity":10, > > "power & expressiveness":100, > > "cross platform?":80, > > "cost":100}, > > "Tcl": {"ease of learning":100, > > "ease of use":100, > > "speed of program execution":10, > > "quality of available tools":50, > > "popularity":40, > > "power & expressiveness":10, > > "cross platform?":100, > > "cost":100}, > > "JavaScript": {"ease of learning":70, > > "ease of use":75, > > "speed of program execution":10, > > "quality of available tools":50, > > "popularity":100, > > "power & expressiveness":40, > > "cross platform?":50, > > "cost":100}, > > "Visual Basic": {"ease of learning":50, > > "ease of use":100, > > "speed of program execution":20, > > "quality of available tools":100, > > "popularity":100, > > "power & expressiveness":50, > > "cross platform?":1, > > "cost":1}, > > "Java": {"ease of learning":15, > > "ease of use":50, > > "speed of program execution":50, > > "quality of available tools":100, > > "popularity":90, > > "power & expressiveness":100, > > "cross platform?":100, > > "cost":100}, > > "C++": {"ease of learning":10, > > "ease of use":25, > > "speed of program execution":90, > > "quality of available tools":90, > > "popularity":80, > > "power & expressiveness":100, > > "cross platform?":90, > > "cost":100}, > > "C": {"ease of learning":15, > > "ease of use":20, > > "speed of program execution":100, > > "quality of available tools":80, > > "popularity":80, > > "power & expressiveness":80, > > "cross platform?":110, > > "cost":100}, > > "Lisp": {"ease of learning":40, > > "ease of use":50, > > "speed of program execution":80, > > "quality of available tools":60, > > "popularity":25, > > "power & expressiveness":110, > > "cross platform?":80, > > "cost":90}, > > "Delphi": {"ease of learning":50, > > "ease of use":110, > > "speed of program execution":85, > > "quality of available tools":100, > > "popularity":30, > > "power & expressiveness":100, > > "cross platform?":80, > > "cost":10} > > } > > > > > > > > def ProgramLanguageFinal(): > > print "This is a program to help give you an idea which > > programming languages you should consider learning." > > print "While there are any number of languages you might > > consider, this program considers only 11 of the most popluar ones." > > print > > print "The program will ask you to input a ranking or > > weighting for a number of criteria that may be of importance" > > print "in choosing your next programming language." > > > > # First look up the criteria listed in the scores. > > # To do that, we need a language name, which can also > > # be looked up from the scores. > > languages = language_scores.keys() > > some_language = languages[0] > > criteria = language_scores[some_language].keys() > > rankings = get_user_rankings(criteria) > > results = ranked_list(calculate_results(languages, > > language_scores, rankings)) > > # Take the pairs out of results in order, and print them out > > for option, result in results: > > print "%5s\t%s" % (result, option) > > > > > > def ProgramLanguageScript(): > > print > > print "This is a program to help you choose a scripting language." > > print > > print "You will be asked to rank some important criteria as > > to their relative importance to you." > > print "These criteria are 'ease of learning', 'ease of use', > > 'speed of program execution'" > > "'quality of available tools', 'popularity', and 'power & > > expressiveness'" > > print > > print "Please rank each of the criteria with a number from 1 > > to 100 when prompted." > > print > > print "100 means of highest relative importance, 1 means of > > least importance." > > > > # This time we want a subset of languages, so I'm going to > > specify them. > > options = ["Python", "Perl", "Ruby", "Tcl", "JavaScript", > > "Visual Basic"] > > criteria = language_scores[options[0]].keys() > > rankings = get_user_rankings(criteria) > > results = ranked_list(calculate_results(options, > > language_scores, rankings)) > > # Take the pairs out of results in order, and print them out > > for option, result in results: > > print "%5s %s" % (result, option) > > > > > > def Basketball(): > > print "This is a program to help you decide which team will > > win a basketball game" > > print > > print "When prompted, enter a number ranking each team on the > > prompted team skill" > > print "on a scale from 1 to 100, with 1 being terrible and > > 100 being the best imaginable" > > print > > team_one = raw_input ("What is the name of team one: ") > > team_two = raw_input ("What is the name of team two: ") > > teams = (team_one, team_two) > > > > rankings = {"speed":100, "size":66, "jumping_ability":50, > > "defense":60, "shooting":75, "ballhandling":50, "rebounding":50} > > criteria = rankings.keys() > > scores = {team_one: {}, > > team_two: {}} > > for c in criteria: > > for team in (team_one, team_two): > > scores[team][c] = get_number("rank the team %s of %s > > on a scale of 1 to 100: " % (c, team), 1, 100) > > > > results = calculate_results(teams, scores, rankings) > > for team in teams: > > print "%s has a power ranking of %d" % (team, results[team]) > > # Now, who won? > > ranked_results = ranked_list(results) > > # Compare the scores. > > if ranked_results[0][1] == ranked_results[1][1]: > > print "the two teams are a toss-up!!!" > > else: > > print "%s wins!!" % ranked_results[0][0] > > > > > > def YesNo(): > > print "Program to help you make a Yes or No decision." > > options = ["Yes", "No"] > > criteria = get_list("Enter your criteria ...", "Criterion %d: ") > > > > rankings = get_user_rankings(criteria) > > scores = get_user_scores(options, criteria ) > > print `scores` > > results = ranked_list(calculate_results(options, scores, rankings)) > > print > > print "The results are" > > print > > print "%5s %s" % ("Score", "Option") > > > > for option, result in results: > > print "%5s %s" % (result, option) > > > > if results[0] > results[1]: > > print "You should decide Yes!!!" > > > > else: > > print > > print "You should decide No!!!" > > print > > > > > > ###### MAIN LOOP ############ > > > > while 1: # loop forever > > > > print "Please enter the number for the type of decision you > > wish to analayze:" > > print "1. General Decision Analysis, you choose the options, > > criteria, etc." > > print "2. Help in Choosing Programming Language amongst 11 > > popular languages" > > print "3. Help in choosing scripting programming language > > amongst 6 scripting languages" > > print "4. Which Basketball Team will win the Game???" > > print "5. Questions with Yes or No type answers" > > choice = get_number("Please type in the number of the type of > > decision-program you wish to run from above and hit enter:", 1, 5) > > > > if choice ==1: > > decisionanalysis() > > elif choice ==2: > > ProgramLanguageFinal() > > elif choice ==3: > > ProgramLanguageScript() > > elif choice ==4: > > Basketball() > > elif choice ==5: > > YesNo() > > elif choice =="quit": > > break # exit from infinite loop > > else: > > print "Invalid operation" > > > > > > > > > > > > > > > > > > > > > > > > > > > > _______________________________________________ > > Pythoncard-users mailing list > > Pyt...@li... > > https://lists.sourceforge.net/lists/listinfo/pythoncard-users > > > > > _______________________________________________ > Pythoncard-users mailing list > Pyt...@li... > https://lists.sourceforge.net/lists/listinfo/pythoncard-users |
From: Andy T. <an...@cr...> - 2001-09-04 11:40:57
|
Ron, I would add some URLs to useful guides to GUI programming but I can't seem to find any. In their absence I'll tip in my thoughts on the basics of the process and wish you well on your journey; Kevin Altis wrote: [snip Kevin's very useful reply] > > >>-----Original Message----- >>From: pyt...@li... >>[mailto:pyt...@li...]On Behalf Of Ronald >>D Stephens >>Sent: Monday, September 03, 2001 12:34 PM >>To: pyt...@li... >>Subject: [Pythoncard-users] Decision Analysis , a Python script to be >>re-coded in PythonCard >> >> >>Well, my first Python script or applet was a simple weighted >>average type of program to help in making decisions that can be >>analyzed by comparing various options for various criteria, >>weighted by importance for each criteria, and scored by calculating a >>simple weighted average for each option and then comparing the >>scores for various options, with higher scores representing better >>options. Tip number one : Always know what you want to achieve. Sounds like we are OK here then. >> >>This program is a commnad line Python program that runs OK in >>IDLE or Pythonwin. >> >>My goal is to make it work with a gui user interface. My thinking >>is that this will be a good learning exercise for me in learning >>PythonCard. Possibly, but looking at your code you have an awful lot of functionality in there, and a lot of it is related to presenting menus in a character mode environment. I would apply some RAD techniques though, and develop 'little and often'. Start with a simple concept and implement that. Once you've got that working to your satisfaction add a little more functionality, then a little more, and a little more, until - voila - you have your completed application. If you try and convert your existing working code in one go the paradigm shift will confuse you even more. >> >>I have previosuly tried to code a gui version of this in Tkinter, >>but I became frustrated before I had a working version. Didn't we all, thats why we are working on PythonCard ;-) Don't forget that one of the purposes of this project is to make it easy to develop graphical applications. You can help us by sharing your frustrations (not that there will be many) and joys as you go along the development path. >> >>I think PythonCard is already up to the task of coding a version >>of my Decision Analysis. Am I right or is it too early for this? Look at what we've got already. You can code *anything* you like in the PythonCard prototype, its just a question of how many compromises you currently have to make for missing functionality. That is a reason to develop applications in the current framework, to find out what we have missed and to add it to the feature list. >> >>I realize that I will need to start from scratch and re-code this >>completely, since the gui version is so much different; although I >>welcome any comments to the contrary. Sorry, you are right on that front; Tip two: seperate display from function in all GUI applications. Make it look right and then make it work right (or vice versa, whatever lights your candle). By logically keeping the display of data apart from its manipulation you make your code simple and easy to maintain. Kevin has given you some top tips about using events. Bear this in mind when you develop your application. You can get the contents and display right before adding the event handlers you need to tie everything together, you don't need to do it all at once. >> >>I am thinking of using sliders for data entry, although I could >>use other forms of data input, obviously. Sliders would be good, none of the existing samples use them so you would be breaking new ground here. Try out the use of them before you start coding your logic, if they feel and look good then use them but don't be afraid to try a few different things before settling on what suits the application best. Bear in mind here the difference between the presentation of data and the value of it. Sliders can have a numeric value, but so can other widgets. All you need to keep in the back of your mind is that you need the user to enter a number, the mechanism they use to provide it is a presentation issue only. This way your application logic should not need to change if you decide to alter your presentation. >> >>If any one has any comments, or general suggetions before I get >>too far along on this project, please let me know. Hope I've been of some help. >> >>Since I am a newbie and busy with a full time job, this task may >>take me awhile, so don't expect immediate results. But once I do >>get it, maybe the results will be of use somehow. I doubt it >>would be usefull enough to include in the samples of PythonCard, but >>anyway, here I go....it's all about learning at this point. >> >>I caught on to Python easier than I expected, and I was pleased >>to be able to do this simple program. But learning gui event driven >>programming has been hard for me (I suppose learning to really >>use classes, OOP, gui's and event driven programming all at once is >>causing me confusion ;-)))). Anyway, I am determined to stick it >>out with PythonCard though. >> Tip three: You will benefit for applying OOP techniques to your application but they aren't *absolutely* necessary. Concentrate on the events model first. I'm an OO innocent but I'm managing to battle through. I just have to remember to keep everything nice and modular and then when I actually understand what mixins and model/view controllers are I can refactor my code - if I want to. >> >>Ron Stephens >> [snip sample code] >> >> >> Regards, Andy -- ----------------------------------------------------------------------- From the desk of Andrew J Todd esq. "Shave my poodle!" |