uni 的一个作业要求我使用 tkinter 创建一个 GUI 程序,该程序采用函数、颜色、起点、终点以及之间要采取的步骤(每一步之间画线)。
我已经做得很好了。我已经完成了整个布局和框架(基本上)我发现一些事情有点困难。
我们已获得此支持代码。
from Tkinter import *
import tkMessageBox
from tkColorChooser import askcolor
from math import *
class FunctionError(Exception):
"""A simple function error exception produced by the make_function
function for invalid function definitions.
"""
pass
def make_function(text):
"""Take a string representing a function in x and return the corresponding
function.
The FunctionError exception is thrown if text does not represent a valid
function.
make_function(string) -> (float -> float)
"""
try:
exec 'f = lambda x: ' + text
1+f(2.0) ## test to see if there are any errors in the definition
except ZeroDivisionError: ## ignore zero division errors
pass
except:
raise FunctionError()
return f
class FunctionIterator(object):
"""An iterator object that is intended to be used to produce (x,y)
pairs of a function
Constructor: FunctionIterator(function, startx, endx, steps)
function is the function being iterated over
startx is the x value to start the iteration
endx is the x value at the end of the iteration
steps is the number of iterations.
Assumes if a division by zero occurs at a given x it won't occur
'close to' x
Example:
Assume square is a function defined to square a number - i.e.
square(x) = x*x
Then
>>> list(FunctionIterator(square, 0.0, 5.0, 5))
[(0.0, 0.0), (1.0, 1.0), (2.0, 4.0), (3.0, 9.0), (4.0, 16.0), (5.0, 25.0)]
and
for x,y in FunctionIterator(square, 0.0, 5.0, 5): print x,y
produces output
0.0 0.0
1.0 1.0
2.0 4.0
3.0 9.0
4.0 16.0
5.0 25.0
NOTE: for functions that are undefined at a given x (e.g. log(-1))
the y value returned is set to 10000000
"""
def __init__(self, f, startx, endx, steps):
self._f = f
self._startx = startx
self._endx = endx
self._delta = (endx-startx)/steps
def __iter__(self):
self._x = self._startx
self._zero = False
return self
def next(self):
if self._x > self._endx + self._delta/2:
raise StopIteration
else:
x = self._x
try:
y = self._f(x)
self._x += self._delta
return (x, y)
except ZeroDivisionError:
if x == self._startx:
x += self._delta/2
y = self._f(x)
self._x += self._delta
return (x, y)
elif self._zero:
x += self._delta/2
y = self._f(x)
self._x += self._delta
self._zero = False
return (x, y)
else:
x -= self._delta/2
y = self._f(x)
self._zero = True
return (x, y)
except:
self._x += self._delta
return (x, 10000000)
class WorldScreen(object):
"""The WorldScreen class is used to convert between real coodinates
and screen coordinates.
Constructor: WorldScreen(x1, y1, x2, y2, width, height)
(x1, y1) : The bottom left in real coords
(x2, y2) : The top right in real coords
width : the width of the screen (canvas)
height: the height of the screen (canvas)
NOTE: On a canvas the y increases are you move down the canvas
so a 'flip' occurs between real y values and screen values - see
example below
"""
def __init__(self, x1, y1, x2, y2, width, height):
self.x = x1
self.y = y1
self.xscale = (x2-x1)/width
self.yscale = (y2-y1)/height
self.height = height
def world2screen(self, x, y):
"""Return the screen (canvas) coordinates given real coordinates.
If the calculated screen y coord is outside the screen then the
appropriate 'edge value' is returned.
world2screen(float, float) -> (float, float)
Example:
>>> ws = World_Screen(0,0,10,10, 100.0, 100.0)
>>> ws.world2screen(5, 5)
(50.0, 50.0)
>>> ws.world2screen(10, 10)
(100.0, 0.0)
Note that in this case when y is 10 in real coordinates (i.e.
at the top then the y coord in the canvas is 0 (i.e. at the top)
"""
wy = self.height - (y - self.y)/self.yscale
"""
if wy < 0:
wy = 0
elif wy > self.height:
wy = self.height
"""
return ((x-self.x)/self.xscale, wy)
def screen2world(self, x, y):
"""Return the real coordinates given screen (canvas)coordinates.
screen2world(float, float) -> (float, float)
Example:
>>> ws = World_Screen(0,0,10,10, 100.0, 100.0)
>>> ws.screen2world(50,50)
(5.0, 5.0)
>>> ws.screen2world(100,0)
(10.0, 10.0)
"""
return (x*self.xscale + self.x, (self.height - y)*self.yscale + self.y)
这是我的代码
class PointFrame(Frame):
"""a simple application to allow a user ti enter an
expression and evaluate it
"""
def __init__(self, master):
"""
a a=simple expression evaluator
"""
Frame.__init__(self, master)
Label(self, text='Last Point Clicked: ').pack(side=LEFT)
Label(self, text='').pack(side=LEFT)
Label(self, text='Cursor Point: ').pack(side=LEFT)
Label(self, text='').pack(side=LEFT)
class CanvasApp(object):
def __init__(self, master):
master.title('canvas')
self._canvas = Canvas(master, bg='white', width=500, height=500)
self._canvas.pack(side=TOP, expand=True, fill=BOTH)
class FunctionFrame(Frame):
"""a simple application to allow a user ti enter an
expressio
n and evaluate it
"""
def __init__(self, master):
"""
a a=simple expression evaluator
"""
Frame.__init__(self, master, relief=SUNKEN, bg='#A5A5A5', pady=3)
Label(self, text='Function in x: ', bg='#A5A5A5').pack(side=LEFT)
function = Entry(self, width=35).pack(side=LEFT, padx=2)
Button(self, text='Select', command=self.select).pack(side=RIGHT, padx=4)
colour = Entry(self, width=15).pack(side=RIGHT)
Label(self, text='Function Colour: ', bg='#A5A5A5').pack(side=RIGHT, padx=2)
def select(self):
(rgb, hx)= askcolor()
class PlotFrame(Frame):
"""a simple application to allow a user ti enter an
expression and evaluate it
"""
def __init__(self, master):
"""
a a=simple expression evaluator
"""
entry_width = 10
Frame.__init__(self, master, bg='#A5A5A5', pady=3)
Label(self, text='Plot Settings', bg='#A5A5A5').pack(side=LEFT)
Label(self, text='Start X:', bg='#A5A5A5').pack(side=LEFT)
start_x = Entry(self, width=entry_width).pack(side=LEFT)
Label(self, text='End X:', bg='#A5A5A5').pack(side=LEFT)
end_x = Entry(self, width=entry_width).pack(side=LEFT)
Label(self, text='Start Y:', bg='#A5A5A5').pack(side=LEFT)
start_y = Entry(self, width=entry_width).pack(side=LEFT)
Label(self, text='End Y:', bg='#A5A5A5').pack(side=LEFT)
end_y = Entry(self, width=entry_width).pack(side=LEFT)
Label(self, text='Steps: ', bg='#A5A5A5').pack(side=LEFT)
steps = Entry(self, width=entry_width).pack(side=LEFT)
class ButtonFrame(Frame):
"""a simple application to allow a user ti enter an
expression and evaluate it
"""
def __init__(self, master):
"""
a a=simple expression evaluator
"""
Frame.__init__(self, master, bg='#CECEF6')
Button(self, text='Add Function', command=self.add_function).pack(side=LEFT)
Button(self, text='Redraw All', command=self.redraw_all).pack(side=LEFT)
Button(self, text='Remove Last Function', command=self.remove_last).pack(side=LEFT)
Button(self, text='Remove All Functions', command=self.remove_all).pack(side=LEFT)
Button(self, text='Exit', command=self.exit_app).pack(side=LEFT)
def add_function(self):
make_function(function)
def redraw_all(self):
pass
def remove_last(self):
pass
def remove_all(self):
pass
def exit_app(self):
self.master.destroy
class PlotApp(object):
def __init__(self, master):
master.title('Assignment 2')
PointFrame(master).pack(side=TOP, expand=True, fill=BOTH, pady=2)
self._canvas = Canvas(master, bg='white', width=500, height=500).pack(side=TOP, expand=True, fill=BOTH, padx=8)
FunctionFrame(master).pack(side=TOP, expand=True, fill=BOTH, pady=4)
separator = Frame(height=18, bd=1)
separator.pack(fill=X)
PlotFrame(master).pack(side=TOP, expand=True, fill=BOTH, pady=4)
separator = Frame(height=10, bd=1)
separator.pack(fill=X)
ButtonFrame(master).pack(side=TOP, pady=5)
我遇到的问题;
如何使用支持代码中的 make_function 函数来检查我的条目(函数)中给出的函数是否是函数。抱歉说了这么多功能。
我的第一堂课-pointframe 的意思是在真实世界坐标中显示canval 中的最后一个单击点和当前光标点。我打算在支持中使用 worldscreen 功能来转换成现实世界的绳索。我怎样才能做到这一点?
选择按钮使用 tkcolorchooser 选择颜色。我怎样才能使该颜色出现在它旁边的颜色条目中?
如何使用颜色、函数、起点和终点以及步骤来绘制函数。在支持代码中使用函数迭代器?那么我怎样才能用一个新的来绘制它,改变颜色,删除所有并重绘所有呢?
我意识到这很多。我不是要求有人为我做这件事。我只是在寻求帮助、提示和任何可以帮助我靠近的东西。
谢谢