如何在Python tkinter中使问卷可以滚动?

问题描述 投票:2回答:1

我是Python新手,一直在做一个学校的项目。这个想法是参加酒精使用障碍识别测试(AUDIT),让用户知道他是否应该寻求专业帮助(如果他的分数是14+)。我今天被卡住了。我正在使用tkinter,以及一套10个带有radiooboxes的问题。然而,我无法继续进行,因为问题不适合在屏幕上,而且看在上帝的份上,我不能让它滚动。我已经尝试了所有我能找到的方法,设置一个类,尝试使用一个框架或画布,等等。

"""imports"""
import tkinter as tk
app = tk.Tk()
app.title("AUDIT")
from tkinter import *
from tkinter import ttk

canvas = tk.Canvas(app)
scroll_y = tk.Scrollbar(app, orient="vertical", command=canvas.yview)

frame = tk.Frame(canvas)
# group of widgets
"""question 1"""
o1 = Text(app, height = 1, width =100)
o1.insert(INSERT, "Jak často pijete alkoholické nápoje (včetně piva)")
o1.insert(END, "?")
o1.pack()
OTAZKA1 = [
        ("Nikdy", "0"),
        ("Jednou za měsíc či méně často", "1"),
        ("2-4x za měsíc", "2"),
        ("2-3x týdně", "3"),
        ("4x nebo vícekrát týdně", "4"),
        ]
o1 = StringVar()
o1.set("0") #initialize

for text, mode in OTAZKA1:
    a = Radiobutton(app, text = text, variable = o1, value = mode)
    a.pack(anchor=W)

"""question 2"""
o2 = Text(app, height = 2, width =100)
o2.insert(INSERT, "Kolik standardních sklenic alkoholického nápoje vypijete během typického dne, kdy pijete")
o2.insert(END, "?")
o2.pack()
OTAZKA2 = [
        ("Nejvýše 1", "0"),
        ("1,5 až 2", "1"),
        ("2,5 až 3", "2"),
        ("3,5 až 5", "3"),
        ("5 a více", "4"),
        ]
o2 = StringVar()
o2.set("0") #initialize

for text, mode in OTAZKA2:
    b = Radiobutton(app, text = text, variable = o2, value = mode)
    b.pack(anchor=W)

一直到第10题 我知道这可能不是最有效的方法,但这是我写的第一段代码。我怎样才能添加滚动条使所有的问题都可见?

python tkinter scrollbar
1个回答
0
投票

你需要 1)使用 Canvas.create_window(x, y, window=widget) 方法2)设置画布 scrollregion 归于 Canvas.bbox("all") 但在此之前必须更新窗口,否则会得到错误的结果 "3)用正确的方法将滚动条连接到画布上(见下面的代码)。

我也可以给你一些建议:1)GUI最好用OOP。对于小的应用来说,可能不是问题,但是如果你的应用比较复杂,比较大,你用OOP的代码,会比用程序化的代码要容易很多。2)你是否注意到你的代码有很多相似的部分?记住:在几乎所有的情况下,都不需要手动创建很多类似的变量(也就是所谓的? DRY原则(不重复). 你可以使用循环自动生成一切。有时你需要使用 enumerate 从Python内置的函数。如果你不会使用DRY原则,你会为开发花费更多的时间。 3)最好避免通过导入其他模块来覆盖已经导入的东西。在你的代码中,你是这样做的。

from tkinter import *
from tkinter.ttk import *

既要 这些模块中包含 Button, Entry, Scrollbar, Radiobutton 等。所以你可能会把所有的东西都弄混。最好是这样做。

from tkinter import *
from tkinter.ttk import only, what, you, need

或者甚至更好。

import tkinter as tk
import tkinter.ttk as ttk  # or: from tkinter import ttk

4) 你可以手动调整Canvas中所有东西的大小,并拒绝调整窗口的大小(无论是宽度还是高度)。

下面是重写的代码。

from tkinter import *
from tkinter import messagebox
from tkinter.ttk import Button, Scrollbar, Radiobutton


# Create questions as a list of dictionaries
# The GUI will be generated automatically
questions = [
    {"question": "Jak často pijete alkoholické nápoje (včetně piva)?",
     "answers": ("Nikdy", "Jednou za měsíc či méně často",
                 "2-4x za měsíc", "2-3x týdně",
                 "4x nebo vícekrát týdně")},
    {"question": "Kolik standardních sklenic alkoholického nápoje vypijete během typického dne, kdy pijete?",
    "answers": ("Nejvýše 1", "1,5 až 2", "2,5 až 3", "3,5 až 5", "5 a více")},
    ]

class App(Tk):
    def __init__(self):
        super().__init__()

        self.title("AUDIT")  # set the window title
        self.resizable(False, True)  # make window unresizable by width

        canv_frame = Frame(self)  # create the canvas frame
        # create the Canvas widget
        # highlightthickness=0 removes the black border when the canvas gets focus
        self.canv = Canvas(canv_frame, highlightthickness=0, width=420)
        # add scrolling when mouse wheel is rotated
        self.canv.bind_all("<MouseWheel>",
                           lambda event: self.canv.yview_scroll(-1 * (event.delta // 120), "units"))
        self.canv.pack(fill=BOTH, expand=YES, side=LEFT)  # pack the Canvas

        # Create a scrollbar
        # command=self.canv.yview tells the scrollbar to change the canvas yview
        # and canvas's yscrollcommand=self.yscrollbar.set tells the canvas to update
        # the scrollbar if canvas's yview is changed without it.
        self.yscrollbar = Scrollbar(canv_frame, command=self.canv.yview)
        self.canv["yscrollcommand"] = self.yscrollbar.set
        self.yscrollbar.pack(fill=Y, side=LEFT)  # pack the Scrollbar

        for question_id, question in enumerate(questions, 1):
            qaframe = Frame(self.canv)  # create the question-answers (QA) frame
            text = Text(qaframe, width=50, height=3)  # create the Text widget for question
            text.insert(END, question["question"])  # insert the question text there
            text.pack(fill=X)  # pack the text widget
            aframe = Frame(qaframe)  # create the answers frame
            # Create the question variable and add it to the variables list
            question_var = IntVar(self)
            question["variable"] = question_var
            # create the radiobuttons 
            for answer_id, answer in enumerate(question["answers"]):
                Radiobutton(aframe, variable=question_var, text=answer, value=answer_id).pack()
            aframe.pack(fill=Y)  # pack the answers frame
            self.canv.create_window(210, question_id * 175, window=qaframe)  # insert the QA frame into the Canvas
        canv_frame.pack(fill=BOTH, expand=YES)  # pack the canvas frame
        Button(self, text="Submit", command=self.submit).pack(fill=X)  # create the "Submit" button
        self.update()  # update everything to get the right scrollregion.
        self.canv.configure(scrollregion=self.canv.bbox("all"))  # set the canvas scrollregion

    def submit(self):
        sum_ = 0  # initially, the sum_ equals 0
        for question in questions:
            sum_ += question["variable"].get()  # and then, we add all the questions answers
        messagebox.showinfo("Result", "Your result is %s!" % sum_)  # show the result in an info messagebox

if __name__ == "__main__":  # if the App is not imported from another module,
    App().mainloop()  # create it and start the mainloop
© www.soinside.com 2019 - 2024. All rights reserved.