Вам необходимо:
1) использовать Canvas.create_window(x, y, window=widget)
метод
2) установить для атрибута canvas scrollregion
значение Canvas.bbox("all")
(но перед обновлением окна, в противном случае вы получите неправильный результат "
3) правильно прикрепите полосу прокрутки к холсту (см. Код ниже)
Я также могу дать вам несколько советов:
1) Лучше использовать OOP для GUI. Для небольших приложений это может не быть проблемой, но если ваше приложение более сложное и большое, вам будет гораздо проще работать с кодом OOP, чем с процедурным.
2 ) Вы заметили, что в вашем коде много похожих частей? Помните: почти во всех случаях нет необходимости создавать множество похожих переменных вручную (это также называется принципом DRY (не повторяйте себя) ) . Вы можете генерировать все автоматически, используя циклы. Иногда вам нужно использовать функцию enumerate
из встроенных Python. Если вы не будете использовать принцип DRY, вы потратит гораздо больше времени на разработку.
3) Это б etter, чтобы избежать переопределения уже импортированных вещей, импортируя другой модуль. В вашем коде вы делаете:
from tkinter import *
from tkinter.ttk import *
Оба из этих модулей содержат Button
, Entry
, Scrollbar
, Radiobutton
et c. Таким образом, вы можете все перепутать. Лучше сделать так:
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