我想编写一个程序,在不同的对话框中向用户询问一系列问题。每个框一次显示一个,如果单击下一步按钮,则转到下一个框。我的问题是我是否为每个对话框创建一个类,并在单击下一步按钮后调用下一个类?或者有更优雅的解决方案吗?
问问题
1721 次
2 回答
3
我的建议是构建一个包含当前问题的基类,然后当用户回答一个问题并进入下一个问题时,基类会更新新的当前问题的显示。您不需要在任何时候销毁小部件(退出应用程序时除外),您还可以在创建新小部件之前重用小部件。
让我将你的问题的格式简化为这个:每个问题都包含一个问题描述和一组答案,用户可以在其中选择一个答案。这些简化可以删除,但我设置它们是为了提供一个初始代码来处理问题。这是这样做的起点(我对命名的想象力很弱):
import random
import Tkinter
import ttk
# Make 5 "questions" with varied number of answers to pick from.
QUESTION = [u"Question %d" % (i + 1) for i in range(5)]
QOPTS = []
k = 1
for _ in QUESTION:
num_opts = random.randint(3, 6)
QOPTS.append([u"text %d" % (k + i) for i in range(num_opts)])
k += num_opts
class Question:
def __init__(self, master):
self._common_var = Tkinter.StringVar()
self._title = None
self._lframe = None
self._rb = []
self._make_gui(master)
def get_answer(self):
return self._common_var.get()
def reset_answer(self):
self._common_var.set("")
def _make_gui(self, master):
self._title = ttk.Label(master, padding=(0, 6, 0, 0))
self._title.grid(in_=master, padx=6, row=0, column=0, sticky='ew')
self._lframe = ttk.Labelframe(master)
self._lframe.grid(in_=master, padx=6, row=1, column=0, sticky='nsew')
def update_gui(self, question, options):
self._title['text'] = question
for i, opt in enumerate(options):
if i < len(self._rb):
if not self._rb[i].grid_info():
self._rb[i].grid()
self._rb[i]['text'] = opt
else:
rb = ttk.Radiobutton(self._lframe, text=opt, value=i,
variable=self._common_var)
rb.grid(in_=self._lframe, row=i, column=0, sticky='w')
self._rb.append(rb)
# Deal with i < total.
for k in xrange(i + 1, len(self._rb)):
self._rb[k].grid_remove()
class Base:
def __init__(self, frame, q, o):
self.master = frame
self.question = None
self.curr_question = 0
self.q = q
self.o = o
self._make_gui(frame)
self._update_gui()
def next_question(self):
answer = self.question.get_answer()
try:
answer = int(answer)
except ValueError:
print "Question not answered, stay here."
return
print "Answer for question %d: %d" % (self.curr_question, answer)
self.question.reset_answer()
self.curr_question += 1
self._update_gui()
def _make_gui(self, frame):
self.question = Question(frame)
frame.columnconfigure(0, weight=1)
frame.rowconfigure(1, weight=1)
btn = [(u"Next", self.next_question)]
self._btn = []
for i, (text, cmd) in enumerate(btn):
# Assumption: the Question instance always uses the rows 0 and 1.
b = ttk.Button(frame, text=text, command=cmd)
b.grid(in_=frame, padx=6, pady=6, row=2, column=i, sticky='e')
self._btn.append(b)
def _update_gui(self):
if self.curr_question == len(self.q):
print "Done"
self.master.quit()
return
elif self.curr_question == len(self.q) - 1:
for btn in self._btn:
# No next question
btn['text'] = u"Finish"
self.question.update_gui(self.q[self.curr_question],
self.o[self.curr_question])
root = Tkinter.Tk()
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
root.geometry('300x250')
frame = ttk.Frame(root)
frame.grid(sticky='nsew')
Base(frame, QUESTION, QOPTS)
root.mainloop()
这是您将获得的 GUI:
于 2012-12-21T02:40:08.880 回答
0
你确定你必须为对话框创建一个类吗?Tkinter 内置对话框类不好吗?您可以为函数提供 Dialogs 的迭代器next()
,每个 Next 按钮在单击时都会调用该迭代器。你的意思是这样的吗?
于 2012-12-14T09:33:26.147 回答