2

ユーザーにさまざまなダイアログ ボックスで一連の質問をするプログラムを作成したいと考えています。各ボックスは 1 つずつ表示され、[次へ] ボタンをクリックすると次のボックスに移動します。私の質問は、ダイアログごとにクラスを作成し、次のボタンがクリックされたら次のクラスを呼び出すだけですか? または、これに対するよりエレガントなソリューションはありますか?

4

2 に答える 2

3

私の推奨事項は、現在の質問を保持する基本クラスを構築することです。ユーザーが質問に答えて次の質問に進むと、基本クラスは新しい現在の質問の表示を更新します。どの時点でも (アプリケーションを終了する場合を除いて) ウィジェットを破棄する必要はなく、新しいウィジェットを作成する前にウィジェットを再利用することもできます。

質問の形式を次のように単純化してみましょう。各質問には、質問の説明と、ユーザーが 1 つを選択できる一連の回答が含まれています。これらの単純化は削除できますが、問題に対処するための初期コードを提示するために設定しました。これがまさにこれを行うための出発点です(命名に対する私の想像力は弱かったです):

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 の組み込みダイアログ クラスは問題ありませんか? ダイアログの反復子をnext()関数に提供できます。これは、クリックされたときにすべての [次へ] ボタンが呼び出されます。そのようなことを意味しましたか?

于 2012-12-14T09:33:26.147 に答える