如何解决我如何使用 tkinter/ttk 制作多个单独的进度条,其中包含百分比?
我一直在尝试为 DnD 会话的游戏大师设计一个小帮助工具,用于记录玩家在统计数据和技能方面的升级进度。我希望这些统计数据与进度条一起显示,其中包含一个百分比,在它们下方,我完全能够使用没有任何百分比的常规进度条来做到这一点:
但是一旦我尝试按照我在此处找到的示例来获取内部带有百分比的进度条,它们就会以某种方式相互连接,将百分比加在一起并在每个进度条中显示总数
控制台输出如下:
"Smith's tools | Progress: 1253/2000
62.64999999999999
Dragonchess set | Progress: 24/2000
1.2"
当加在一起时,它加起来为 63.84999,这导致上图中四舍五入的总百分比为 63.85。
这些是在我为保存的每个字符调用的函数中创建的,最初我复制了来自 this post 的代码,这导致所有进度条汇总在一起,而使用当前代码显示每个字符单独的总百分比,然后将其与下一个字符的百分比相加,所有进度条都会填充到最高百分比。
这是我第一次在这里发帖,所以如果您需要更多代码或详细信息,请告诉我。产生这些奇怪的填充结果的函数如下:
def buildbasicobjectinfo(elems,charfield,charname):
pbnum = 0
for elem in elems:
try:
style.layout('TProgressbar.'+str(charname)+'.'+str(pbnum),[('Progressbar.trough',{'children': [('Horizontal.Progressbar.pbar',{'side': 'left','sticky': 'ns'})],'sticky': 'nswe'}),('Progressbar.label',{'sticky': ''})])
t = elem.childNodes[0].firstChild.data+" | Progress: "+elem.childNodes[2].firstChild.data+"/"+elem.childNodes[1].firstChild.data
print(t)
progress = tk.Label(charfield,text=t)
progress.pack(anchor="w")
pbar = ttk.Progressbar(charfield,style='TProgressbar.'+str(charname)+'.'+str(pbnum),variable=variable)
print("variable="+str(variable))
percentage = float(float(elem.childNodes[2].firstChild.data)/float(elem.childNodes[1].firstChild.data)*100)
print(percentage)
pbar.step(percentage)
pbar.pack(anchor="w")
style.configure('TProgressbar.'+str(charname)+'.'+str(pbnum),text='{:g} %'.format(variable.get()))
pbnum = pbnum+1
except AttributeError:
print(elem,elem.childNodes[0])
def buildbasicobjectinfo(elems,charname):
for elem in elems:
try:
percentage = round(float(float(elem.childNodes[2].firstChild.data)/float(elem.childNodes[1].firstChild.data)*100),2) #calculate the percentage
print(percentage) #print percentage in console
t = elem.childNodes[0].firstChild.data+" | Progress: "+elem.childNodes[2].firstChild.data+"/"+elem.childNodes[1].firstChild.data+" | Percentage: "+str(percentage)+"%" #format necessary data
print(t) #print data in console
#create label for data in text format
progress = tk.Label(charfield,text=t)
progress.pack(anchor="w")
#create progress bar
pbar = ttk.Progressbar(charfield,orient="horizontal",mode="determinate",length=300)
pbar.step(percentage) #fill progress bar with compelted percentage
pbar.pack(anchor="w")
except AttributeError:
print(elem,elem.childNodes[0])
对于那些对演示问题的小程序感兴趣的人应该这样做,在左侧它将显示 2 个进度条,以正常方式并正确显示,在右侧它将显示 2 个以相同方式创建的进度条方式,但通过添加样式将百分比可视化添加到进度条本身以及它们如何由于某种原因相互添加,在每个条形上方它将显示它们应该处于的百分比:
import tkinter as tk
import tkinter.ttk as ttk
#function to divide the centered frame evenly,replicates distribution of character placement
def sidebysidedisplay(data,frame):
npbframe = tk.LabelFrame(frame,text="normal bars",bd=0,font=(0,12,'bold'))
npbframe.grid(row=1,column=0,sticky="nesw",padx=(0,20))
spbframe = tk.LabelFrame(frame,text="styled bars",'bold'))
spbframe.grid(row=1,column=1,padx=(20,0))
normalprogressbar(data,npbframe)
styledprogressbar(data,spbframe)
def normalprogressbar(items,frame):
print("normal progress bars")
for item in items:
percentage = round(float(float(item[0])/float(item[1])*100),2)
print("Item: "+str(item)+" | Percentage: "+str(percentage))
progress = tk.Label(frame,text=percentage)
progress.pack(anchor="w")
pbar = ttk.Progressbar(frame,length=400)
pbar.step(percentage)
pbar.pack(anchor="w")
def styledprogressbar(items,frame):
print("Styled progress bars")
for item in items:
percentage = round(float(float(item[0])/float(item[1])*100),2)
print("Item: "+str(item)+" | Percentage: "+str(percentage))
style.layout('text.Horizontal.TProgressbar.'+str(item),[('Horizontal.Progressbar.trough',('Horizontal.Progressbar.label',{'sticky': ''})])
progress = tk.Label(frame,style='text.Horizontal.TProgressbar.'+str(item),variable=variable,length=400)
pbar.step(percentage)
pbar.pack(anchor="w")
style.configure('text.Horizontal.TProgressbar.'+str(item),text='{:g} %'.format(variable.get())) # update label
#====================================================================================================#
root = tk.Tk()
root.state("zoomed")
data = ((1253,2000),(24,2000)) #mock data to recreate data read from xml file
style = ttk.Style(root)
variable = tk.DoubleVar(root)
#create centered frame to display data in the center of the screen
centerframe = tk.LabelFrame(root,bd=0)
centerframe.place(relx=.5,rely=.5,anchor="c")
sidebysidedisplay(data,centerframe)
root.mainloop()
解决方法
运行代码后,我发现问题使 variable = tk.DoubleVar(root)
您将一个 variable
用于两个 Progressbars
并且 pbar.step(percentage)
将值添加到 variable
,因此最终您得到总和 63.83%
。
这也造成了其他问题。如果您更改 variable
中的值,则它会更改 Progressbar
中的长度,并且您会在两个小部件中看到相同的长度。
您应该删除 variable
pbar = ttk.Progressbar(frame,length=400,style='text.Horizontal.TProgressbar.'+str(item))
使用 percentage
显示文本
style.configure('text.Horizontal.TProgressbar.'+str(item),text='{:g} %'.format(percentage) ) # update label
或者您必须为两个 variables
创建两个 Progressbars
编辑:
您也可以创建自己的小部件 - 您可以使用 Frame
通过 Label
、Progressbar
和 variable
创建小部件。
使用 variable
的工作代码
import tkinter as tk
import tkinter.ttk as ttk
#function to divide the centered frame evenly,replicates distribution of character placement
def sidebysidedisplay(data,frame):
npbframe = tk.LabelFrame(frame,text="normal bars",bd=0,font=(0,12,'bold'))
npbframe.grid(row=1,column=0,sticky="nesw",padx=(0,20))
spbframe = tk.LabelFrame(frame,text="styled bars",'bold'))
spbframe.grid(row=1,column=1,padx=(20,0))
normalprogressbar(data,npbframe)
styledprogressbar(data,spbframe)
def normalprogressbar(items,frame):
print("Normal progress bars")
for item in items:
percentage = round(float(float(item[0])/float(item[1])*100),2)
print("Item: "+str(item)+" | Percentage: "+str(percentage))
progress = tk.Label(frame,text=percentage)
progress.pack(anchor="w")
pbar = ttk.Progressbar(frame,orient="horizontal",mode="determinate",length=400)
pbar.step(percentage)
pbar.pack(anchor="w")
def styledprogressbar(items,frame):
print("Styled progress bars")
for item in items:
percentage = round(float(float(item[0])/float(item[1])*100),2)
print("Item: "+str(item)+" | Percentage: "+str(percentage))
style.layout('text.Horizontal.TProgressbar.'+str(item),[('Horizontal.Progressbar.trough',{'children': [('Horizontal.Progressbar.pbar',{'side': 'left','sticky': 'ns'})],'sticky': 'nswe'}),('Horizontal.Progressbar.label',{'sticky': ''})])
progress = tk.Label(frame,text=percentage)
progress.pack(anchor="w")
#pbar = ttk.Progressbar(frame,style='text.Horizontal.TProgressbar.'+str(item),variable=variable,length=400)
pbar = ttk.Progressbar(frame,length=400)
pbar.step(percentage)
pbar.pack(anchor="w")
#style.configure('text.Horizontal.TProgressbar.'+str(item),text='{:g} %'.format(variable.get())) # update label
style.configure('text.Horizontal.TProgressbar.'+str(item),text='{:g} %'.format(percentage)) # update label
#====================================================================================================#
root = tk.Tk()
#root.state("zoomed")
data = ((1253,2000),(24,2000)) #mock data to recreate data read from xml file
style = ttk.Style(root)
variable = tk.DoubleVar(root)
#create centered frame to display data in the center of the screen
centerframe = tk.LabelFrame(root,bd=0)
centerframe.place(relx=.5,rely=.5,anchor="c")
sidebysidedisplay(data,centerframe)
root.mainloop()
编辑:
带有自己的小部件的版本
import tkinter as tk
import tkinter.ttk as ttk
class MyWidget(tk.Frame):
def __init__(self,parent,item,*args,**kwargs):
super().__init__(parent,**kwargs)
self.item = item
self.percentage = round(100*item[0]/item[1],2)
print("[MyWidget] Item: {} | Percentage: {}".format(self.item,self.percentage))
style_name = 'text.Horizontal.TProgressbar.'+str(item)
style.layout(style_name,{'sticky': ''})])
self.label = tk.Label(self,text=self.percentage)
self.label.pack(anchor="w")
self.pbar = ttk.Progressbar(self,style=style_name,length=400)
self.pbar.step(self.percentage)
self.pbar.pack(anchor="w")
style.configure(style_name,text='{:g} %'.format(self.percentage))
#function to divide the centered frame evenly,spbframe)
widgetsframe = tk.LabelFrame(frame,text="widgets",'bold'))
widgetsframe.grid(row=1,column=2,0))
for item in data:
w = MyWidget(widgetsframe,item)
w.pack()
def normalprogressbar(items,frame):
print("Styled progress bars")
for item in items:
percentage = round(item[0]/item[1]*100,2)
print("Item: {} | Percentage: {}".format(item,percentage))
style_name = 'text.Horizontal.TProgressbar.'+str(item)
style.layout(style_name,length=400)
pbar.step(percentage)
pbar.pack(anchor="w")
style.configure(style_name,text='{:g} %'.format(percentage))
#====================================================================================================#
root = tk.Tk()
#root.state("zoomed")
data = ((1253,anchor="c")
sidebysidedisplay(data,centerframe)
root.mainloop()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。