龟窗出现空白

时间:2016-12-25 22:23:30

标签: python tkinter turtle-graphics

这是我的代码。它在Python 3.5.2中,使用tkinter和turtle。

按下按钮显示项目的位置时,乌龟窗口为空白。如果我将关于乌龟的所有代码移动到tkinter窗口后调用mainloop,则在关闭tkinter窗口并且工作正常后会打开乌龟窗口。

如何修复我的代码,以便在按下按钮时显示。

import csv
import collections
from tkinter import *

def direction(n):
    import turtle
    wn = turtle.Screen() #sets up window
    turtle.bgpic("WilleysMap.gif") #loads picture of map
    m = turtle.Turtle() #creates arrow
    m.speed(100) #sets the speed
    m.penup() #lifts pen so no marks are made
    m.forward(160)
    m.right(90)
    m.forward(80)
    m.speed(1) #reduces speed so path can be seen
    if n == 1:#------------------------------------------------------------------NU 1
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.right(90)
        m.forward(180)
        m.right(90)
        m.forward(300)
        m.left(90)
        m.forward(80)
        wn.mainloop()       
    elif n == 2: #---------------------------------------------------------------NU 2
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.right(90)
        m.forward(180)
        m.right(90)
        m.forward(235)
        m.left(90)
        m.forward(80)
        wn.mainloop()       
    elif n == 3: #---------------------------------------------------------------NU 3
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.right(90)
        m.forward(180)
        m.right(90)
        m.forward(180)
        m.left(90)
        m.forward(80)
        wn.mainloop()
    elif n == 4: #---------------------------------------------------------------NU 4
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.right(90)
        m.forward(180)
        m.right(90)
        m.forward(300)
        m.right(90)
        m.forward(80)
        wn.mainloop()
    elif n == 5: #---------------------------------------------------------------NU 5
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.right(90)
        m.forward(180)
        m.right(90)
        m.forward(200)
        m.right(90)
        m.forward(80)
        wn.mainloop()       
    elif n == 6: #---------------------------------------------------------------NU DECK
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.right(90)
        m.forward(180)
        m.right(90)
        m.forward(60)
        m.left(90)
        m.forward(80)
        wn.mainloop()
    elif n == 7: #---------------------------------------------------------------PARKING LOT
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.left(90)
        m.forward(50)
        m.left(45)
        m.forward(140)
        m.left(45)
        m.forward(100)
        m.left(45)
        m.forward(180)
        wn.mainloop()
    elif n == 8: #---------------------------------------------------------------HUT AREA
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.right(90)
        m.forward(80)
        m.right(90)
        m.forward(40)
        wn.mainloop()
    elif n == 9: #---------------------------------------------------------------SIDE STRUCTURE 1
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(20)
        m.right(90)
        m.forward(180)
        m.left(90)
        m.forward(30)
        m.right(90)
        m.forward(80)
        wn.mainloop()
    else: #----------------------------------------------------------------------SIDE STRUCTURE 2
        m.pencolor("red")
        m.pensize(15)
        m.pendown()
        m.forward(80)
        m.right(90)
        m.forward(60)
        wn.mainloop()


with open('code.csv') as f: #loads itemDict from the code.csv file
    reader1 = csv.reader(f)
    itemDict = dict(reader1)

with open('loc.csv') as f: #loads itemLoc from the loc.csv file
    reader2 = csv.reader(f)
    itemLoc = dict(reader2)
itemLoc['Emerald Green Arborvitae'] = itemLoc.pop('Emerald Green Arborvitae') #corrects error in translation

global find
def evaluate(event):
    if entry.get() in itemDict:
        res.configure(text = "UPC: " + str(entry.get()) + "\n The " + itemDict[entry.get()] + " can be found at: " + itemLoc[itemDict[entry.get()]], font = "Verdana 15 bold")
    else:
        res.configure(text = "UPC: " + str(entry.get()) + "\n The UPC you entered is not listed", font = "Verdana 15 bold")

def show():
    if itemLoc[itemDict[entry.get()]] == 'NU 1':
        direction(1)
    elif itemLoc[itemDict[entry.get()]] == 'NU 2':
        direction(2)
    elif itemLoc[itemDict[entry.get()]] == 'NU 3':
        direction(3)    
    elif itemLoc[itemDict[entry.get()]] == 'NU 4':
        direction(4)
    elif itemLoc[itemDict[entry.get()]] == 'NU 5':
        direction(5)
    elif itemLoc[itemDict[entry.get()]] == 'NU DECK':
        direction(6)    
    elif itemLoc[itemDict[entry.get()]] == 'PARKING LOT':
        direction(7)    
    elif itemLoc[itemDict[entry.get()]] == 'HUT AREA':
        direction(8)
    elif itemLoc[itemDict[entry.get()]] == 'SIDE STRUCTURE 1':
        direction(9)    
    else:
        direction(10)

w = Tk()

w.geometry("650x700")


Label(w, text="Type UPC into entry bar. To see a visual representation of the items location, press the 'Show' button.", font = "Verdana 10").pack(anchor=W)
Label(w, text="").pack()

Label(w, text="Please enter UPC of item", font = "Verdana 10").pack()
Label(w, text="you would like to locate", font = "Verdana 10").pack()
Label(w, text="and press 'Enter'", font = "Verdana 10").pack()
entry = Entry(w)
entry.focus_set()

entry.bind("<Return>", evaluate)
entry.pack()

Label(w, text="").pack()

Button(w, text ="Show", command=show).pack()

Label(w, text="").pack()

res = Label(w)
res.pack()

Label(w, text="Scroll down to see all listed UPCs", font = "Verdana 10").pack()

scrollbar = Scrollbar(w)
scrollbar.pack(side=RIGHT, fill=Y)
T = Text(w, height=15, width=75, bg = 'blue', fg = 'white')
T.pack()
quote = ''
with open('code.csv', newline='') as f:
    reader = csv.reader(f)
    for row in reader:
        quote += ("" + row[0] + ' '*(13-len(row[0])) + row[1] + '\n')
T.insert(END, quote)
scrollbar.config(command=T.yview)

w.mainloop()

修改 问题在于

turtle.bgpic("WilleysMap.gif")

如果我在它前面放一个#,代码工作正常,乌龟图形只是在白色屏幕而不是地图上绘制。有谁知道如何解决这个错误?

顺便说一下,数据加载只是一个两个合并的CSV文件。好像: Arborvitate,ARB1 金柳,GW34 等等 等

修改 这是我得到的错误

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\lucas\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1550, in __call__
    return self.func(*args)
  File "x-wingide-python-shell://86210440/2", line 173, in show
  File "x-wingide-python-shell://86210440/2", line 29, in direction
  File "<string>", line 8, in bgpic
  File "C:\Users\lucas\AppData\Local\Programs\Python\Python35-32\lib\turtle.py", line 1482, in bgpic
    self._setbgpic(self._bgpic, self._bgpics[picname])
  File "C:\Users\lucas\AppData\Local\Programs\Python\Python35-32\lib\turtle.py", line 738, in _setbgpic
    self.cv.itemconfig(item, image=image)
  File "<string>", line 1, in itemconfig
  File "C:\Users\lucas\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 2418, in itemconfigure
    return self._configure(('itemconfigure', tagOrId), cnf, kw)
  File "C:\Users\lucas\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1321, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: image "pyimage2" doesn't exist

1 个答案:

答案 0 :(得分:1)

最后我运行你的代码。

您有错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1540, in __call__
    return self.func(*args)
  File "<pyshell#6>", line 141, in show
    direction(1)
  File "<pyshell#6>", line 27, in direction
    wn.mainloop()
AttributeError: '_Screen' object has no attribute 'mainloop'

您尝试执行wn.mainloop(),但wn没有方法mainloop(),但turtle有 - 所以您需要turtle.mainloop()

BTW:您可以缩短代码并将turtle.mainloop()置于所有if/elif/else

之下

但后台的turtle使用tkinter来显示窗口而tkinter只能运行一个mainloop(),而您已经w.mainloop(),因此您不需要turtle.mainloop()需要global find

BTW: find = some_variable 没有创建全局变量。在函数外部创建的所有变量都是全局的 - 因此您只需要

global
函数内部使用

RawTurtle来通知函数使用外部变量而不是创建本地变量。

编辑:修改示例。

因为我没有您的数据,所以我只创建了一个名称为#34;示例&#34;。

我必须使用tk.Canvastk.Toplevelcanvas来更好地控制与龟的窗口。但是你可以直接在主窗口中使用pack(pady=20)(没有`tk.Toplevel&#39;)并且只有一个窗口。

我使用 'NU 1': 'f20 r90 f180 r90 f300 l90 f80', 在标签之间留出空间。

我用文字来描述曲目。

import tkinter as tk
from  tkinter import messagebox
import turtle

def draw_track(track):
    win = tk.Toplevel()
    canvas = tk.Canvas(win, width=500, height=500)
    canvas.pack()
    m = turtle.RawTurtle(canvas)

    # move to start
    m.speed(100)
    m.penup()
    m.forward(160)
    m.right(90)
    m.forward(80)
    m.speed(1)

    # draw
    m.pencolor("red")
    m.pensize(15)
    m.pendown()

    # split text into command
    track = track.split()

    # execute commands
    for element in track:
        cmd = element[0]
        number = int(element[1:])
        if cmd == 'f':
            m.forward(number)
        elif cmd == 'r':
            m.right(number)
        elif cmd == 'l':
            m.left(number)

def evaluate(event):
    if entry.get() in itemDict:        
        text="UPC: {}\nThe {} can be found at: {}".format(entry.get(), itemDict[entry.get()], itemLoc[itemDict[entry.get()]])
    else:
        text="UPC: {}\nThe UPC you entered is not listed".format(entry.get())
    res.configure(text=text, font="Verdana 15 bold")

def show():
    text = entry.get().strip()
    if text in item_dict:
        track = data[item_loc[item_dict[text]]]
        draw_track(track)
    else:
        messagebox.showwarning("Warning", "No '{}' in dictionary".format(text))

# --- main ---

# - data -

item_dict = {'example': 1}
item_loc  = {1: 'NU 1'}

data = {
    'NU 1': 'f20 r90 f180 r90 f300 l90 f80',
    'NU 2': 'f20 r90 f180 r90 f235 l90 f80',
    'NU 3': 'f20 r90 f180 r90 f180 l90 f80',
    'NU 4': 'f20 r90 f180 r90 f300 r90 f80',
    'NU 5': 'f20 r90 f180 r90 f200 r90 f80',
    'NU DECK': 'f20 r90 f180 r90 f60 l90 f80',
    'PARKING LOT': 'f20 l90 f50 l45 f140 l45 f100 l45 f180',
    'HUT AREA': 'f20 r90 f80 r90 f40',
    'SIDE STRUCTURE 1': 'f20 r90 f180 l90 f30 r90 f80',
    'SIDE STRUCTURE 2': 'f80 r90 f60',
}

# - gui -

root = tk.Tk()

font = "Verdana 10"

l = tk.Label(root, text="Type UPC into entry bar.\nTo see a visual representation of the items location, press the 'Show' button.", font=font)
l.pack()

l = tk.Label(root, text="Please enter UPC of item\nyou would like to locate\nand press 'Enter'", font=font)
l.pack(pady=20)

entry = tk.Entry(root)
entry.pack()

entry.bind("<Return>", evaluate)
entry.focus_set()

b = tk.Button(root, text="Show", command=show)
b.pack(pady=20)

root.mainloop()

代码:

class InteropExamples {
    /* note: these delegates fields must be kept alive in a real class too,
       or else GC can collect them.
    */

    // One method has out, the other [Out] attribute (in order, A out, B [Out])
    readonly TryGetLocationA _tryGetLocationA;
    readonly TryGetLocationB _tryGetLocationB;

    // One method has ref IntPtr, the other IntPtr[] (in order, A ref IntPtr, B IntPtr[])
    readonly IsEntityValidA _isEntityValidA;
    readonly IsEntityValidB _isEntityValidB;

    readonly int _mainThreadID;

    public bool InvokeRequired => GetCurrentThreadId() != _mainThreadID;

    public InteropExamples() {
        var addressOne = IntPtr.Zero; // real address of the func here of course.
        var addressTwo = IntPtr.Zero; // real address of the func here of course.

        _tryGetLocationA =
            Marshal.GetDelegateForFunctionPointer(addressOne, typeof(TryGetLocationA)) as TryGetLocationA;
        _tryGetLocationB =
            Marshal.GetDelegateForFunctionPointer(addressOne, typeof(TryGetLocationB)) as TryGetLocationB;

        _isEntityValidA =
            Marshal.GetDelegateForFunctionPointer(addressTwo, typeof(IsEntityValidA)) as IsEntityValidA;
        _isEntityValidB =
            Marshal.GetDelegateForFunctionPointer(addressTwo, typeof(IsEntityValidB)) as IsEntityValidB;

        _mainThreadID = System.Diagnostics.Process.GetCurrentProcess().Threads[0].Id;
    }


    // This way works as expected with no limits.
    // delegate void TryGetLocationA(IntPtr address, out Vector3 result);   
    public Vector3 GetLocationA(IntPtr address) {
        Vector3 location;
        // note: Invoke(_tryGetLocationA, address, out location) is not possible here.
        _tryGetLocationA(address, out location);
        return location;
    }

    // In this example, we use a trick to be able to 
    // use the out despite using params object[] args
    // not allowing you to pass out or ref.
    // delegate void TryGetLocationB(IntPtr address, [Out] Vector3[] result);   
    public Vector3 GetLocationB(IntPtr address) {
        // note: if your delegate signature - 
        // has out and not the attribute [Out]
        // it will fail.
        var location = new Vector3[1];
        // The result gets passed to the first index of the array, 0.
        // Use our special invoke method with params object[] thus not allowing - 
        // us to use out directly like in example A.
        Invoke(_tryGetLocationB, address, location);
        return location[0];
    }

    // This way works fine and as expected.
    public bool IsEntityValid_A(IntPtr entityAddress) {
        // note:  (bool) Invoke(_isEntityValidA, ref entityAddress) is not valid here.
        return _isEntityValidA(ref entityAddress);
    }

    public bool IsEntityValid_B(IntPtr entityAddress) {
        // note: no ref tag needed here, unlike the [Out] example.
        // The array trick allows us to once again by pass the limit -
        // of not being able to use ref in params object[] (or params of any kind).
        var isEntityValid = (bool) Invoke(_isEntityValidB, new[] {entityAddress});
        return isEntityValid;
    }


    // An example of why we might want to invoke unmanaged funcs with -
    // a generic method using params[] object[] args, which sadly -
    // with out using tricks will not allow use of out/ref signatures.
    // Work arounds exist and shown in this class.
    object Invoke<T>(T target, params object[] args) where T : class {
        var targetDelegate = target as Delegate;
        if (targetDelegate == null) {
            throw new ArgumentException("Target method is not a delegate type.");
        }

        if (!InvokeRequired) {
            return targetDelegate.DynamicInvoke(args);
        }

        var callback = new InvokeDelegateTarget {
            Target = targetDelegate,
            Args = args
        };

        /* notify some class to invoke your delegate */
        Helper.ProcessDelegate(callback);
        /* while callback.Result == null {} or what ever check you do */

        return callback.Result;
    }

    [DllImport("kernel32.dll")]
    static extern int GetCurrentThreadId();

    [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
    delegate void TryGetLocationB(IntPtr address, [Out] Vector3[] result);

    [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
    delegate void TryGetLocationA(IntPtr address, out Vector3 result);

    [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
    delegate bool IsEntityValidA(ref IntPtr entityAddress);


    [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
    delegate bool IsEntityValidB(IntPtr[] entityAddress);
}