You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派屏幕Python 3.8环境下Tkinter滚动功能添加后窗口空白问题

树莓派屏幕Python 3.8环境下Tkinter滚动功能添加后窗口空白问题

嗨,我来帮你搞定这个问题!你的窗口变空白主要有两个核心问题,咱们逐个解决:

问题根源分析

  1. 主循环位置错误:你把tkFenster.mainloop()放在了滚动条代码之后,而Tkinter的主循环一旦启动就会阻塞后续代码执行,后面所有创建按钮、标签的代码根本没机会运行,窗口自然是空的。
  2. 滚动条绑定错误:Tkinter的顶层窗口(Toplevel)本身不支持滚动视图(yview),你直接把滚动条的command绑定到自身的yview是无效的,得用一个可滚动的容器来承载所有控件。

解决方案步骤

第一步:调整主循环位置

把tkFenster.mainloop()移到所有代码的最后一行,确保所有控件都创建完成后再启动主循环。

第二步:重构滚动功能

我们用Canvas作为滚动容器,在Canvas内部放一个Frame,所有原来的控件都放到这个Frame里,再把滚动条和Canvas绑定起来,这样就能实现滚动效果了。

修改后的完整代码

import tkinter as tk
from tkinter import *
from tkinter import ttk

# 假设这些变量是你之前定义好的(用户代码里用到但没给出的变量)
maxschritte = 10
max_ausgaenge = 8
rez_arr = [[0 for _ in range(max_ausgaenge+3)] for _ in range(maxschritte)]
Wartaufext = 0
Wartwert = 1000
Drehwinkel = 90

# 定义用户代码里用到的函数(示例空实现,你替换成自己的逻辑)
def Einstellungen_zurueck():
    pass
def einst_speichern_double():
    pass
def plusschritte():
    pass
def minusschritte():
    pass
def Kalibrierung():
    pass
def Motorplus():
    pass
def Motorminus():
    pass
def Startposition():
    pass

# 创建顶层窗口
tkFenster = tk.Toplevel()
tkFenster.title("Einstellungen")
tkFenster.geometry('800x480')
tkFenster.attributes('-zoomed', True)

# ------------------- 滚动功能实现 -------------------
# 创建滚动条
Yscroll = tk.Scrollbar(tkFenster)
Yscroll.pack(side=tk.RIGHT, fill=Y)

# 创建Canvas作为滚动容器
scroll_canvas = tk.Canvas(tkFenster, yscrollcommand=Yscroll.set)
scroll_canvas.pack(side=LEFT, fill=BOTH, expand=True)

# 绑定滚动条到Canvas的yview
Yscroll.configure(command=scroll_canvas.yview)

# 创建内部Frame,所有控件都放在这个Frame里
content_frame = tk.Frame(scroll_canvas)
# 将Frame放到Canvas中
canvas_window = scroll_canvas.create_window((0, 0), window=content_frame, anchor=NW)

# 定义函数更新Canvas的滚动区域
def update_scroll_region(event):
    scroll_canvas.configure(scrollregion=scroll_canvas.bbox("all"))
# 绑定Frame大小变化事件,更新滚动区域
content_frame.bind("<Configure>", update_scroll_region)

# 树莓派触摸屏支持鼠标滚轮(可选,根据你的设备调整)
def on_mouse_wheel(event):
    scroll_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
scroll_canvas.bind_all("<MouseWheel>", on_mouse_wheel)
# ---------------------------------------------------

# 原来的控件创建代码,注意把所有tkFenster替换成content_frame
rowsizelist = []
einst_reihenanzahl = 1
if maxschritte <= 6:
    einst_reihenanzahl = 7
else:
    einst_reihenanzahl=maxschritte+1

for i in range(einst_reihenanzahl):
    rowsizelist.append(i)

columnamount = 4
columnamount = max_ausgaenge + 3
columnsizelist = []
for i in range(columnamount):
    columnsizelist.append(i)

content_frame.rowconfigure(rowsizelist, minsize = 10, weight = 1)
content_frame.columnconfigure(columnsizelist, minsize = 10, weight = 1)

btn_zurueckscreen = tk.Button(content_frame, text = "Zurück", command = Einstellungen_zurueck)
btn_zurueckscreen.grid(row = 0, column = 0, rowspan = 1, columnspan = 1, sticky = "nsew")

btn_save = tk.Button(content_frame, text = "Speichern", command = einst_speichern_double)
btn_save.grid(row = 1, column = 0, rowspan = 2, columnspan = 1, sticky = "nsew")

btn_plusSchritt = tk.Button(content_frame, text = "+ Schritte", command = plusschritte)
btn_plusSchritt.grid(row = 3, column = 0, rowspan = 1, columnspan = 1, sticky = "nsew")

btn_minusSchritt = tk.Button(content_frame, text = "- Schritte", command = minusschritte)
btn_minusSchritt.grid(row = 4, column = 0, rowspan = 1, columnspan = 1, sticky = "nsew")

# hier wird das 2D Dictionary vorbereitet
IDs = []
for i in range(maxschritte):
    IDs.append("Schritt " + str(i+1))

holder_defaultslist = []
#print(max_ausgaenge)
for i in range(max_ausgaenge):
    if i < 6:
        holder_defaultslist.append("Aus. " + str(i+1))
    if i == 6:
        holder_defaultslist.append("Mot.+")
    if i == 7:
        holder_defaultslist.append("Mot.-")
    if i == 8:
        holder_defaultslist.append("Wart.")

holder_defaults = {}
holder_defaults = dict.fromkeys(holder_defaultslist, "")
# print(holder_defaults)

IDs.append("Warten \n auf extern")
var_holder= dict.fromkeys(IDs, holder_defaults)
#print(var_holder)

kalla = 3
reihe = 0
vars_rez = []
for i in range(maxschritte*max_ausgaenge+1): # hier werden Checkbuttonsvariablen erstellt
    vars_rez.append(tk.IntVar())

rei = int(((i-i%max_ausgaenge)/max_ausgaenge))
spal = int(i%max_ausgaenge) + 2
#print(str(rei) +" Reihe +" + str(spal) + " Spalte")
# print(str(rei) + " ? " + str(spal))
# print(rez_arr[rei][spal])

if i<maxschritte*max_ausgaenge:
    if rez_arr[rei][spal] == 1:
        vars_rez[i].set(True)
    else:
        vars_rez[i].set(False)
else:
    vars_rez[i].set(False)
#print(vars_rez[i])

laufer = 0
ent_rez=[]
for i in range(maxschritte):     # hier wird Entryvariablen erstellt
    ent_rez.append(tk.StringVar())
ent_rez.append(tk.StringVar()) #für Wartwert
ent_rez.append(tk.StringVar()) #für Drehwinkel

for labelz in var_holder.keys():
    # print (labelz)
    if reihe < maxschritte:
        lbl = tk.Label(content_frame, text = labelz + "\n Zeit(ms)") # hier wird das Label erstellt
        lbl.grid(row = reihe, column = 1, rowspan = 1, columnspan = 1, sticky = "nsew")

        ent = tk.Entry(content_frame,width = 5, textvariable = ent_rez[reihe]) # hier wird das Entry erstellt, die Breite zur Not wieder weglassen wenns auf dem Touch nicht geht
        ent.grid(row = reihe, column = 2, rowspan = 1, columnspan = 1, sticky = "nsew")
        ent.delete(0, 'end')
        ent.insert(0, rez_arr[reihe][1])
    else:
        lbl = tk.Label(content_frame, text = labelz) # hier wird das Label für letzte Zeile erstellt
        lbl.grid(row = reihe, column = 1, rowspan = 1, columnspan = 1, sticky = "nsew")

    if reihe < maxschritte:
        for labely in var_holder[labelz].keys():
            chb = tk.Checkbutton(content_frame, text = labely, variable=vars_rez[laufer]) # hier wird der Checkbutton erstellt
            chb.grid(row = reihe, column = kalla, rowspan = 1, columnspan = 1, sticky = "nsew")
            if rez_arr[reihe][kalla-1] == 1:
                chb.select()
            kalla = kalla + 1
            laufer = laufer + 1
        if kalla == 3 + max_ausgaenge:
            kalla = 3
            reihe = reihe + 1
    else:
        chb = tk.Checkbutton(content_frame, text = "W a ext", variable=vars_rez[laufer]) # hier wird der Checkbutton erstellt
        #print(vars_rez[laufer])
        global Wartwert
        global Drehwinkel
        print(Wartwert)
        print(Drehwinkel)
        chb.grid(row = reihe, column = kalla-1, rowspan = 1, columnspan = 1, sticky = "nsew")
        #print("wart auf ext vor select"+ str(Wartaufext))
        if Wartaufext == 1:
            chb.select()
        #print(rez_arr)

btn_Kalibrierung = tk.Button(content_frame, width = 4, text = "Kalibrie-\nrung", command = Kalibrierung)
btn_Kalibrierung.grid(row = reihe, column = 3, rowspan = 1, columnspan = 2, sticky = "nsew")

btn_Motorplus = tk.Button(content_frame, width = 4, text = "Motor+", command = Motorplus)
btn_Motorplus.grid(row = 5, column = 0, rowspan = 1, columnspan = 1, sticky = "nsew")

btn_Motorminus = tk.Button(content_frame, width = 4, text = "Motor-", command = Motorminus)
btn_Motorminus.grid(row = 6, column = 0, rowspan = 1, columnspan = 1, sticky = "nsew")

lbl = tk.Label(content_frame, text = "Warten auf\nmaximal:")
lbl.grid(row = reihe, column = 5, rowspan = 1, columnspan = 1, sticky = "nsew")

ent = tk.Entry(content_frame, width = 4, textvariable = ent_rez[reihe])
ent.grid(row = reihe, column = 6, rowspan = 1, columnspan = 1, sticky = "nsew")
ent.delete(0, 'end')
#Wartwert = ent_rez[reihe].get()
ent.insert(0, Wartwert)

lbl = tk.Label(content_frame, text = "Winkel(°)\nvor/zurück")
lbl.grid(row = reihe, column = 7, rowspan = 1, columnspan = 1, sticky = "nsew")

ent = tk.Entry(content_frame, width = 4, textvariable = ent_rez[reihe+1])
ent.grid(row = reihe, column = 8, rowspan = 1, columnspan = 1, sticky = "nsew")
ent.delete(0, 'end')
#Drehwinkel = ent_rez[reihe+1].get()
ent.insert(0, Drehwinkel)

btn_Startposition = tk.Button(content_frame, width = 4, text = "Motor in \n Startposition", command = Startposition)
btn_Startposition.grid(row = reihe, column = 9, rowspan = 1, columnspan = 2, sticky = "nsew")

#lbl = Label(content_frame, text = "Motor im \nUhrzeigersinn")
#lbl.grid(row = reihe, column = 9, rowspan = 1, columnspan = 1, sticky = "nsew")

#lbl = Label(content_frame, text = "Motor gegen \nUhrzeigersinn")
#lbl.grid(row = reihe, column = 10, rowspan = 1, columnspan = 1, sticky = "nsew")

reihe=reihe+1

# print(vars_rez)

# lbl = Label(content_frame, text="Warten \n auf extern")
# lbl.grid(row=maxschritte, column=1, rowspan=1,columnspan=1, sticky="nsew" )

# chb = Checkbutton(content_frame, text = "W a ex", variable=vars_rez[maxschritte*max_ausgaenge]) # hier wird der Checkbutton erstellt
# chb.grid(row = maxschritte, column = 2, rowspan = 1, columnspan = 1, sticky = "nsew")

print("varscheckforext=" + str(vars_rez[maxschritte*max_ausgaenge]))

# 主循环移到最后
tkFenster.mainloop()

关键修改点说明

  1. 主循环位置:把tkFenster.mainloop()移到代码最后,确保所有控件都初始化完成。
  2. 滚动容器结构:用Canvas+Frame的组合承载所有控件,解决顶层窗口无法滚动的问题。
  3. 控件父容器替换:把所有原来绑定到tkFenster的控件,全部改成绑定到content_frame(Canvas内部的Frame)。
  4. 滚动区域更新:绑定content_frame的<Configure>事件,自动更新Canvas的滚动范围,确保所有内容都能被滚动到。
  5. 修复变量赋值:你代码里的vars_rez[i].set = True是错误的,应该改成vars_rez[i].set(True),我已经帮你修正了这个小bug。

这样修改后,你的滚动功能就能正常工作,同时原来的按钮、标签等控件也会正常显示啦~

备注:内容来源于stack exchange,提问作者Mprog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 09:04:30