python - 如何使用 Python 2.7 在 Tkinter 中设计 GUI 序列

标签 python user-interface python-2.7 tkinter gui-designer

我想编写一个程序,在不同的对话框中向用户询问一系列问题。每个框一次显示一个,如果单击“下一步”按钮,则转到下一个框。我的问题是我是否为每个对话框创建一个类,然后在单击“下一步”按钮后调用下一个类?或者有更优雅的解决方案吗?

最佳答案

我的建议是构建一个包含当前问题的基类,然后当用户回答问题并前进到下一个问题时,基类会更新新的当前问题的显示。您不需要在任何时候销毁小部件(退出应用程序时除外),并且您还可以在创建新小部件之前重用小部件。

让我将您的问题格式简化为以下形式:每个问题都包含一个问题描述和一组答案,用户可以在其中选择一个答案。这些简化可以删除,但我设置它们是为了提供处理该问题的初始代码。 这是这样做的起点(我对命名的想象力很弱):

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:

enter image description here enter image description here

关于python - 如何使用 Python 2.7 在 Tkinter 中设计 GUI 序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13873190/

相关文章:

python-2.7 - Kinesis Agent 报告 python 流数据错误

JavaFX .getChildren().add(root) 抛出 java.lang.IllegalStateException

Java - 在 GUI 中使用线程

python - opencv2 Aruco 库模块不适用于 python

python - Mypy 似乎忽略了 TypeVar 类型的界限

visual-studio-2008 - 带有 Visual C++ Express 版本的 GUI 应用程序

javascript - HTML 到 Python - 数据被视为字符串而不是列表 - 如何强制 Python 处理为多维列表

python - 在Django中提供静态文件的最佳做法

python - 传递了稀疏矩阵,但需要密集数据。使用 X.toarray() 转换为密集的 numpy 数组

python - 如何指定变量作为 re.sub 中的第一个参数