2

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)

我遇到的问题;

  1. 如何使用支持代码中的 make_function 函数来检查我的条目(函数)中给出的函数是否是函数。抱歉说了这么多功能。

  2. 我的第一堂课-pointframe 的意思是在真实世界坐标中显示canval 中的最后一个单击点和当前光标点。我打算在支持中使用 worldscreen 功能来转换成现实世界的绳索。我怎样才能做到这一点?

  3. 选择按钮使用 tkcolorchooser 选择颜色。我怎样才能使该颜色出现在它旁边的颜色条目中?

  4. 如何使用颜色、函数、起点和终点以及步骤来绘制函数。在支持代码中使用函数迭代器?那么我怎样才能用一个新的来绘制它,改变颜色,删除所有并重绘所有呢?

我意识到这很多。我不是要求有人为我做这件事。我只是在寻求帮助、提示和任何可以帮助我靠近的东西。

谢谢

4

0 回答 0