【问题标题】:set new list variable equal to list generated in a function that has listbox values passed to it将新的列表变量设置为等于在将列表框值传递给它的函数中生成的列表
【发布时间】:2013-08-20 20:06:46
【问题描述】:

我创建了一个函数,该函数应在列表框中获取用户选择,并将它们填充到列表中。然后我希望能够在函数之外访问这个列表,但我不知道该怎么做。我知道我应该调用该函数,但我对如何将任何东西传递给它感到困惑。这是我的代码

def usr_fc(*events):
   UsrFCList = []
   selctd_indices = lbox.curselection()
   lst_select = list(selctd_indices)
   for i in lst_select:
     UsrFCList.append(lbox.get(i))
   lbox.quit()

我已对其进行了编辑,以包含我目前拥有的所有代码:

#import modules and functions
import arcpy
import tkFont
from Tkinter import *

#create entry widget and get/set variable/workspace with function 'set_wkspc'
def set_wkspc():
  wk = e_ws.get()
  arcpy.env.workspace = wk
  e_ws.quit()

wk_input = Tk()

e_ws = Entry(wk_input, width=75)
e_ws.pack()

e_ws.focus_set()

b = Button(wk_input, text="choose workspace", width=15, command=set_wkspc)
b.pack()

mainloop()

#function to list all feature classes within specified workspace
def getFC(ws):
  ws = arcpy.env.workspace
  FCList1 = []
  FCList2 = []
  fcs1 = arcpy.ListFeatureClasses()
  FCList1.append(fcs1)
  fds = arcpy.ListDatasets()
  for fd in fds:
    arcpy.env.workspace = ws + '/'  + fd
    fcs2 = arcpy.ListFeatureClasses()
    FCList2.append(fcs2)
  FCList1.extend(FCList2)
  return FCList1

x = arcpy.env.workspace

lb_list = getFC(x)

#new Listbox class and function that sets up a listbox size according to its contents
class AutoSzLB(Listbox):
def autowidth(self,maxwidth):
    f = tkFont.Font(font=self.cget("font"))
    pixels = 0
    for item in self.get(0, "end"):
        pixels = max(pixels, f.measure(item))
    # bump listbox size until all entries fit
    pixels = pixels + 10
    width = int(self.cget("width"))
    for w in range(0, maxwidth+1, 5):
        if self.winfo_reqwidth() >= pixels:
            break
        self.config(width=width+w)

#list variable for user's choice of feature classes and a function that creates
#list of chosen feature classes

def usr_fc(*events):
  UsrFCList = []
  selctd_indices = lbox.curselection()
  lst_select = list(selctd_indices)
  for i in lst_select:
    UsrFCList.append(lbox.get(i))
  lbox.quit()

#generate scrollbar, execute button and listbox of feature classes to select
#for analysis
fc_lb = Tk()
scrollbar = Scrollbar(fc_lb)
scrollbar.pack(side=RIGHT, fill=Y)
lbox = AutoSzLB(fc_lb,selectmode=EXTENDED)
for item in lb_list:
  lbox.insert(END, *item)

button = Button(fc_lb, text="Analyze selected feature classes", command=usr_fc)

lbox.autowidth(250)
lbox.pack()
button.pack()

#attach listbox to scrollbar
lbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=lbox.yview)

mainloop()

#create entry widget and set workspace for analysis output
def set_out_wkspc():
  wk = out_ws.get()
  ident_ouput_path = wk
  out_ws.quit()

out_wk = Tk()

out_ws = Entry(out_wk, width=75)
out_ws.pack()

out_ws.focus_set()

b2 = Button(out_wk, text="set output workspace", width=20, command=set_wkspc)
b2.pack()

mainloop()

【问题讨论】:

  • 尝试从函数返回列表,或者(不推荐)将其分配给全局变量。
  • 我认为您需要向我们展示此代码的更多上下文。看起来usr_fc 是一个事件的回调函数,在这种情况下,您需要包装回调函数以允许它访问您的 GUI 对象的命名空间,但是如果没有更多上下文很难建议您,因为它很大程度上取决于GUI 的其余部分是如何编码的。
  • 您有意创建然后销毁第一个根窗口是否有原因?这是非常不寻常的。 GUI 通常会创建一个窗口,该窗口会一直存在到程序退出。
  • 我很新,我想要的只是在给定或选择一个值时关闭窗口。我认为我需要退出或销毁来关闭它

标签: python function listbox tkinter


【解决方案1】:

这里是快速修复:

UsrFCList = []  # You've added this name to the module-level namespace.

def usr_fc(*events):
   selctd_indices = lbox.curselection()
   lst_select = list(selctd_indices)
   for i in lst_select:
     UsrFCList.append(lbox.get(i))  # The interpreter looks for UsrFCList in the local function namespace, and since you're not assigning to that name, it look at the next biggest namespace, which is the module namespace.
   lbox.quit()

# You should now have access to any data you put in UsrFCList, outside the usr_fc function.

但是,处理此问题的最佳方法是重写代码,以便 GUI 的内部数据、小部件和回调函数位于它们自己的类中。这样它们就可以共享一个类命名空间,因此它们可以像UsrFCList 的内容一样相互传递数据。从长远来看,如果您想制作任何复杂的 GUI,您将需要执行我在下面概述的操作。

如果不重写整个代码,它大致如下所示:

class App:
    def __init__(root, self):
        # initialize your class with all your widgets
        self.fc_lb = root
        self.button = Button(fc_lb, text="Analyze selected feature classes", command=lambda *events:self.usr_fc(*events))
# Note  ^^^^ all your widgets and data will be accessible through the `self` reference to your GUI instance.
        self.UsrFCList = []
        self.lbox = AutoSzLB(self.fc_lb,selectmode=EXTENDED)
        # . . . you'd have to add all the other setup required to make your GUI

    def usr_fc(self, *events):
    #          ^^^^ you now have access to everything in the instance namespace available inside usr_fc 
        self.UsrFCList = []
        selctd_indices = lbox.curselection()
        lst_select = list(selctd_indices)
        for i in lst_select:
            self.UsrFCList.append(lbox.get(i))
        self.lbox.quit()

    # . . . and you'd add all the other functions that need to work with internal GUI widgets/data 

rootWindow = Tk()
newGUI = App(rootWindow)  # Create a new GUI instance
rootWindow.mainloop()

# Hopefully that gives you the idea.

【讨论】:

    猜你喜欢
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    • 2018-12-17
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    相关资源
    最近更新 更多