进度条写在父类的方法里,子类运行程序时想调用却报故障object has no attribute 'process'

先说明下我的程序架构,我将面板的一些操作控件包括进度条放在Class1中,执行程序放在Class2中,Class1作为Class2的父类
当点击了Class1中的按钮时调用Class2的函数,在这个函数里,调用了Class1中的进度条更新函数,这个进度条更新函数里又会调用进度条控件的那个函数(这一步出错了),报的错误原因是object has no attribute ‘process’。想问问有什么办法可以解决这个问题。
现状1:父类中的按钮控件和进度条控件也要放在一个方法里,否则也会报相同的错误。
现状2:父类中的其它方法调用进度条函数可以正常使用。
现状3:子类中可以继承父类的方法,但是方法定义的self.process类型是<class ‘tkinter.ttk.Progressbar’>这不是一个属性并没被使用到。
附上相关的代码:

Class1():
    def frame_progress():
        self.frame_pro = Frame(frameT, bd=2, relief=GROOVE, bg='#B5B5B5')
        self.frame_pro.pack(padx=1, side=TOP, anchor=W,fill=BOTH, expand=YES)
        s = ttk.Style()
        s.configure("red.Horizontal.TProgressbar", foreground='Green1', background='Green1', height=100)
        self.process = ttk.Progressbar(self.frame_pro, style="red.Horizontal.TProgressbar", length=620,mode="determinate", maximum=100, orient=HORIZONTAL)
        self.process.pack(padx=1, side=LEFT)
        self.pro_lab = StringVar()
        self.progress_label = Label(self.frame_pro, textvariable=self.pro_lab, fg="#0000CD", bg='#B5B5B5').pack(padx=1,side=LEFT)
#调用进度条的函数
```python
Class1():
    def updata_process(self, count, sum):
        p = round(count / sum * 100)
        if p % 5 == 0:  # 降低更新频率
            # self.value(p)
            self.process["value"] = p
            # time.sleep(0.01)  # 有程序后不需要sleep
            self.frame_pro.update()  # 程序和界面得放一块,界面把路径传参给程序,程序又要调用界面更新,会形成闭环出错
            self.pro_lab.set(str(p) + '%')
        if p == 100.00:
            self.pro_lab.set("完成")
```python
#子类中函数
Class2(Class1):
    def fun1(self):
        for i in range(100):
            time.sleep(500)
            super().updata_process(i,100)
```python
if __name__ == '__main__':
    frameT = Tk()
    frameT.configure(bg='#CFCFCF')
    screen_width = frameT.winfo_screenwidth()
    screen_height = frameT.winfo_screenheight()
    width_default = 1920  #生成程序电脑的默认分辨率
    height_default = 1080 #生成程序电脑的默认分辨率
    width_scale = 670/width_default
    height_scale = 780/height_default
         frameT.geometry(f'{int(width_scale*screen_width)}x{int(height_scale*screen_height)}+500+150')
    frameT.title('CanoeAutoTestToolV1.5')
    frameT.iconbitmap('ico/doge.ico')  # 更改窗口图标
    start1=casetool().frame_path()
    # start2 = casetool().frame_function()
    # start3=casetool().frame_progress()
    frameT.mainloop()
Jason990420
最佳答案

It looks like wrong code to show your question.

Demo Code

import time
from tkinter import *
from tkinter import ttk

class Class1():

    def __init__(self):
        self.frame_progress()

    def frame_progress(self):
        self.frame = Frame(root, bd=2, relief=GROOVE, bg='#B5B5B5')
        self.frame.pack(padx=1, side=TOP, anchor=W, fill=BOTH, expand=YES)
        s = ttk.Style()
        s.configure("red.Horizontal.TProgressbar", foreground='Green1', background='Green1', height=100)
        self.process = ttk.Progressbar(self.frame, style="red.Horizontal.TProgressbar", length=620, mode="determinate", maximum=100, orient=HORIZONTAL)
        self.process.pack(padx=1, side=LEFT)
        self.pro_lab = StringVar()
        self.pro_lab.set("0%")
        self.progress_label = Label(self.frame, width=4, justify=CENTER, textvariable=self.pro_lab, fg="#0000CD", bg='#B5B5B5')
        self.progress_label.pack(padx=1,side=LEFT)
        self.button = Button(root, text='CALL')
        self.button.pack(side=BOTTOM)

    def updata_process(self, count, sum):
        p = round(count / sum * 100)
        if p % 5 == 0:
            self.process["value"] = p
            self.frame.update()
            self.pro_lab.set(str(p) + '%')
        if p == 100.00:
            self.pro_lab.set("完成")

class Class2(Class1):

    def __init__(self):
        super().__init__()
        self.button['command'] = self.fun1


    def fun1(self):
        for i in range(101):
            time.sleep(0.1)
            super().updata_process(i, 100)

root = Tk()
c = Class2()
root.mainloop()

file

1年前 评论
Benc (楼主) 1年前
讨论数量: 3
Jason990420

It looks like wrong code to show your question.

Demo Code

import time
from tkinter import *
from tkinter import ttk

class Class1():

    def __init__(self):
        self.frame_progress()

    def frame_progress(self):
        self.frame = Frame(root, bd=2, relief=GROOVE, bg='#B5B5B5')
        self.frame.pack(padx=1, side=TOP, anchor=W, fill=BOTH, expand=YES)
        s = ttk.Style()
        s.configure("red.Horizontal.TProgressbar", foreground='Green1', background='Green1', height=100)
        self.process = ttk.Progressbar(self.frame, style="red.Horizontal.TProgressbar", length=620, mode="determinate", maximum=100, orient=HORIZONTAL)
        self.process.pack(padx=1, side=LEFT)
        self.pro_lab = StringVar()
        self.pro_lab.set("0%")
        self.progress_label = Label(self.frame, width=4, justify=CENTER, textvariable=self.pro_lab, fg="#0000CD", bg='#B5B5B5')
        self.progress_label.pack(padx=1,side=LEFT)
        self.button = Button(root, text='CALL')
        self.button.pack(side=BOTTOM)

    def updata_process(self, count, sum):
        p = round(count / sum * 100)
        if p % 5 == 0:
            self.process["value"] = p
            self.frame.update()
            self.pro_lab.set(str(p) + '%')
        if p == 100.00:
            self.pro_lab.set("完成")

class Class2(Class1):

    def __init__(self):
        super().__init__()
        self.button['command'] = self.fun1


    def fun1(self):
        for i in range(101):
            time.sleep(0.1)
            super().updata_process(i, 100)

root = Tk()
c = Class2()
root.mainloop()

file

1年前 评论
Benc (楼主) 1年前

谢谢你的帮助,按照你的方式已解决该问题。我出现这个问题总结如下:

1、在执行Class1(放控件)后再执行Class2(功能函数),这样就会出现object has no attribute错误。 解决方式就是把tkinte控件放在class1的_init_中,Class2继承Class1的_init_。最后应用时实例化Class2(之前一直是Class1我以为已经运行控件了理所当然就继承给子类了)

2、继问题1,我之前犯的错误是控件放在放在_init_中当Button按下时,界面会复制一遍导致界面乱掉。原因是执行Button绑定的函数时会执行一遍_init_。 解决方式就是把Button绑定的函数放到Class2中,Class2继承了Class1中的_init_但是按下按钮时不会重复执行一遍Class1中的_init_,界面就不会出错了。

3、尤其是要注意函数执行的先后顺序,如果子类中用到了例如路径这种由父类提供的变量,原先的做法是传参给子类,使用这种方式后,直接在父类中将子类需要用到的变量打包成方法,最后子类使用父类中的Button,command绑定这个方法在_init_中就能直接使用了。

4、使用command时应该把Button实例化。我之前在父类中把button和pack直接写一块了即button1 = Button().pack,然后在子类中使用button1['command']=self,fun1时出错,仔细看了你的回复才发现错误。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!