1

所以这就是问题所在。我已经开始使用 python 一段时间了,我遇到了一个问题。虽然一开始看起来很简单,但它让我连续忙了几个小时。*运行程序时我没有收到任何语法错误,尽管程序无法将新 IP 写入文件。

我正在为一个程序创建一个函数,该函数要求客户端提供一个新的 IP 地址,因为服务器(我的 IP)当前不是静态的。由于我的 IP 更改非常频繁,我想为客户(试图与我建立连接)提供更改他们尝试连接的 IP 的选项。

所以这里是函数:

#CONFIGURE NEW IP
def IpConfigNew():
   #Creates new window 
   IpConfig = Tk()
   IpConfig.configure(background = 'white')
   IpConfig.title('Configure IP')
   IpConfig.geometry('300x60+260+380')
   IpNew = StringVar()
   Label(IpConfig, font  = ('Helvetica',12), text = 'Please enter the IP address of the   server', bg = 'white').place(x=0,y=4)
   #Creates box for user to type IP in.
   Entry(IpConfig,textvariable=IpNew, bg = "light blue").place(x=4,y=35)

 #Store New Ip NOTE that it is nested within IpConfigNew
 def IpStore():
     #Retrieves new IP from text box and stores it in variable 
     GetIpNew = IpNew.get()
     mypath = str('Latest Server')
     #Creates directory to write new IP to.
     if not os.path.isdir(mypath):
         os.makedirs(mypath)
     StoreLatestServer = open('Latest Server\NewIp.txt', 'w')
     #Writes new IP
     StoreLatestServer.write("%s"%(GetIpNew))
     StoreLatestServer.close()
     IpConfig.destroy()#Closes window

   #Calls on function IpStore in order to store the new IP    
   Button(IpConfig,text = 'Done', command = IpStore).place(x=150,y=30)
   IpConfig.mainloop()

def PromptIpReconfig():
  confirm = tkMessageBox.askyesno(title = "Configure Server IP", message = "Are you   sure?")
#Checks to see if the user chose to change IP
if confirm >0: 
  #In the event that the user said yes go to IpConfigNew
  IpConfigNew()
else:
   return

#Configure Menu Bar #Sets up Menu Bar for parent Window(app)
menubar = Menu(app)
filemenu = Menu(menubar,tearoff = 0)
# Goes to     PromptIpReconfig (Prompts user to Reconfigure the IP after clicking button)
filemenu.add_command(label="Configure IP", command = PromptIpReconfig) 
filemenu.add_command(label="Quit", command=app.destroy)
menubar.add_cascade(label='Options',menu = filemenu)
app.config(menu=menubar)#Draws menubar on parent window(app)

我不知道为什么它不工作,因为我之前做过这个,但期望略有不同。当我尝试将新 IP 写入文件时,没有任何内容写入文件。新目录已创建,因此我知道该功能正在运行。我对比了我之前制作的那个程序和这个程序。我发现,如果我这样做,效果很好:

#CONFIGURE NEW IP
#Creates new window
IpConfig = Tk()
IpConfig.configure(background = 'white')
IpConfig.title('Configure IP')
IpConfig.geometry('300x60+260+380')
IpNew = StringVar()
Label(IpConfig, font  = ('Helvetica',12), text = 'Please enter the IP address of the   server', bg = 'white').place(x=0,y=4)
#Creates box for user to type IP in.
Entry(IpConfig,textvariable=IpNew, bg = "light blue").place(x=4,y=35)

 #Store New Ip
 def IpStore():
     #Retrieves new IP from text box and stores it in variable GetIpNew
     GetIpNew = IpNew.get()
     mypath = str('Latest Server')
     #Creates directory to write new IP to.
     if not os.path.isdir(mypath):
         os.makedirs(mypath)
     StoreLatestServer = open('Latest Server\NewIp.txt', 'w')
     #Writes new IP
     StoreLatestServer.write("%s"%(GetIpNew))
     StoreLatestServer.close()
     #Closes window
     IpConfig.destroy()

#Calls on function IpStore in order to store the new IP
Button(IpConfig,text = 'Done', command = IpStore).place(x=150,y=30)
IpConfig.mainloop()

我发现如果我在不使用菜单栏的情况下启动它,而只是在程序启动时启动它,它工作正常。我不确定问题是从菜单栏中调用 IpConfigNew 函数还是与我正在嵌套函数的事实有关。

如果有人可以在这里帮助我,我会很高兴的,因为它已经困扰了我好几天了!

4

2 回答 2

0

我事先没有把我的程序的布局说得很清楚,我现在试着解释一下。

我拥有的是我的主窗口,在我的主窗口(称为“应用程序”)内,我设置了一个菜单栏。这个菜单栏有一个名为“options”的级联和一个名为“PromptIpReconfig”的命令:

app = Tk() 
filemenu.add_command(label="Configure IP", command = PromptIpReconfig)
filemenu.add_command(label="Quit", command=app.destroy)
menubar.add_cascade(label='Options',menu = filemenu)

当我调用函数“PromptIpReconfig”时,会发生以下情况:

def PromptIpReconfig():
   confirm = tkMessageBox.askyesno(title = "Configure Server IP", message = "Are you sure?")
   if confirm >0:
      IpConfigNew()
   else:
      return

如果用户决定说是,则IpConfigNew()调用:

#CONFIGURE NEW IP
def IpConfigNew():
    IpConfig = Tk()
    IpConfig.configure(background = 'white')
    IpConfig.title('Configure IP')
    IpConfig.geometry('300x60+260+380')
    IpNew = StringVar()
    Label(IpConfig, font  = ('Helvetica',12), text = 'Please enter the IP address of the server', bg = 'white').place(x=0,y=4)
    Entry(IpConfig,textvariable=IpNew, bg = "light blue").place(x=4,y=35)

    #Store New Ip
    def IpStore():
        GetIpNew = IpNew.get()
        mypath = str('Latest Server')
        if not os.path.isdir(mypath):
            os.makedirs(mypath)
        StoreLatestServer = open('Latest Server\NewIp.txt', 'w')
        StoreLatestServer.write("%s"%(GetIpNew))
        StoreLatestServer.close()
        IpConfig.destroy()

    Button(IpConfig,text = 'Done', command = IpStore).place(x=150,y=30)
    IpConfig.mainloop()

IpConfigNewIpConfig = Tk()在主窗口中打开一个子窗口。输入新 IP 后,子窗口提供了一个单击按钮。单击按钮后,它会调用命令“IpStore”:

#Store New Ip
def IpStore():
    GetIpNew = IpNew.get()
    mypath = str('Latest Server')
    if not os.path.isdir(mypath):
        os.makedirs(mypath)
    StoreLatestServer = open('Latest Server\NewIp.txt', 'w')
    StoreLatestServer.write("%s"%(GetIpNew))
    StoreLatestServer.close()
    IpConfig.destroy()

所以基本上我的程序的整体布局是这样的:

from Tkinter import *
import os
import tkMessageBox
#Create parent window
app = Tk()

def IpConfigNew():
   #Creates new window 
   IpConfig = Tk()
   IpNew = StringVar()
   Label(IpConfig, font  = ('Helvetica',12), text = 'Please enter the IP address of the   server', bg = 'white').place(x=0,y=4)
   #Creates box for user to type IP in.
   Entry(IpConfig,textvariable=IpNew, bg = "light blue").place(x=4,y=35)

 #Store New Ip NOTE that it is nested within IpConfigNew
 def IpStore():
     #Retrieves new IP from text box and stores it in variable 
     GetIpNew = IpNew.get()
     mypath = str('Latest Server')
     #Creates directory to write new IP to.
     if not os.path.isdir(mypath):
         os.makedirs(mypath)
     StoreLatestServer = open('Latest Server\NewIp.txt', 'w')
     #Writes new IP
     StoreLatestServer.write("%s"%(GetIpNew))
     StoreLatestServer.close()
     IpConfig.destroy()#Closes window

   #Calls on function IpStore in order to store the new IP    
   Button(IpConfig,text = 'Done', command = IpStore).place(x=150,y=30)
   IpConfig.mainloop()

def PromptIpReconfig():
   confirm = tkMessageBox.askyesno(title = "Configure Server IP", message = "Are you sure?")
   if confirm >0:
      #In the case that the user says yes
      IpConfigNew()
   else:
      return


#Create menu bar
filemenu.add_command(label="Configure IP", command = PromptIpReconfig)
filemenu.add_command(label="Quit", command=app.destroy)
menubar.add_cascade(label='Options',menu = filemenu)

app.mainloop()

我很确定问题是函数 IpConfigNew 因为这似乎有效:

from Tkinter import *
import tkMessageBox
import os


#Creates new window   
IpConfig = Tk()
IpNew = StringVar()
Label(IpConfig, font  = ('Helvetica',12), text = 'Please enter the IP address of the   server', bg = 'white').place(x=0,y=4)
#Creates box for user to type IP in.
Entry(IpConfig,textvariable=IpNew, bg = "light blue").place(x=4,y=35)

#Store New Ip NOTE that it is nested within IpConfigNew
def IpStore():
     #Retrieves new IP from text box and stores it in variable 
     GetIpNew = IpNew.get()
     mypath = str('Latest Server')
     #Creates directory to write new IP to.
     if not os.path.isdir(mypath):
         os.makedirs(mypath)
     StoreLatestServer = open('Latest Server\NewIp.txt', 'w')
     #Writes new IP
     StoreLatestServer.write("%s"%(GetIpNew))
     StoreLatestServer.close()
     IpConfig.destroy()#Closes window

#Calls on function IpStore in order to store the new IP    
Button(IpConfig,text = 'Done', command = IpStore).place(x=150,y=30)
IpConfig.mainloop()

这应该让你们更清楚地了解我正在处理的内容。谢谢

于 2013-10-02T09:54:55.253 回答
0

最后,我会将这两行移到里面IpConfigNew

#Calls on function IpStore in order to store the new IP    
Button(IpConfig,text = 'Done', command = IpStore).place(x=150,y=30)
IpConfig.mainloop()

编辑:似乎有一种带有多个事件循环和 StringVar 的错误,请参阅Tkinter Folklore。无论如何,在您想要显示对话框的情况下,您不需要另一个 Tk 循环。所以改变你的代码是这样的:

def IpConfigNew():
    #Creates a Toplevel window instead of a new "main" window in a new loop
    IpConfig = Toplevel(app) 

    ...

    #IpConfig.mainloop()
    app.wait_window(IpConfig)

这解决了我测试中的问题。

于 2013-10-02T08:00:29.920 回答