简体   繁体   English

如何在 Tkinter 的框架 class 内提升框架 class

[英]How to raise a frame class from within a frame class in Tkinter

I've been trying to raise my second frame from first frame class after the first one is been raised from the root class, but everytime gets an error type object 'root' has no attribute 'tk' .在从根 class 提升第一帧之后,我一直试图从第一帧 class 提升我的第二帧,但每次都会得到一个错误类型 object 'root' 没有属性 ' But I am able to raise my second frame from the root class but that's not what i want.但我能够从根 class 提升我的第二帧,但这不是我想要的。 I would want to raise each consecutive frame from previous frame as i want 4 frames to be raised throughout the program many times with conditions.我想从前一帧提升每个连续的帧,因为我希望在整个程序中根据条件多次提升 4 帧。 If I'm thinking all this the wrong way then please provide a workaround, below is my code.如果我认为这一切都是错误的,那么请提供一个解决方法,下面是我的代码。

import mysql.connector as sql
from os import getenv
from datetime import date
from ttkthemes import themed_tk as ttkt
from tkinter import ttk
import tkinter as tk
from tkinter import messagebox as mg

class root(ttkt.ThemedTk):
    def __init__(self, *args):
        ttkt.ThemedTk.__init__(self, *args)
        self.geometry('800x450')
        self.resizable(0, 0)
        self.set_theme('arc') #equilux
        self.config(background = '#EFEFEF')
        self.navbar()
        self.show_frame(home_first) 
#### I'm able to call Class_second frame from changing the value here

    def show_frame(self, cont):
        frame = cont(self)
        frame.pack(side = 'right', expand = True, fill= 'both', ipadx = 210)
        frame.tkraise()

    def show_Class_frame(self):
        self.show_frame(self, Class_second)

    def about(self):
    ....

    def session(self): 
    ....

    #NAVBAR______________________________
    def navbar(self):
        fl = tk.Frame(self, background = '#0077CC')
        fl.pack(side = 'left', expand = 1, fill= 'both')
        #NAVBAR's internal items______________________________
        ....

class home_first(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        ....
        btnt = ttk.Button(btnfrm, text = 'Teachers', style = 'fntb.TButton', command = self.tch_sel)
        # I want to use these to get to second frame
        btnt.pack(pady = (0,8))
        btns = ttk.Button(btnfrm, text = 'Students', style = 'fntb.TButton', command = self.std_sel)
        btns.pack()

    def tch_sel(self):
        sel = 0 #for teachers direct to page 3 not Class_second Frame
        root.show_Class_frame(root)

    def std_sel(self):
        sel = 1 #for students move to Class_second frame
        root.show_Class_frame(root)

class Class_second(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

class vote_third(tk.Frame):
    pass #from here i need to bring 4th frame

class done_fourth(tk.Frame):
    pass #here there will be like 3 button each going either to Home, Class or Vote frames
if __name__ == '__main__':
    app = root()
    app.mainloop()

Traceback追溯

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Sagar\Anaconda3\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "d:\Code\Python\py_project_votm\vm_vot_main_oop.py", line 76, in tch_sel
    root.show_Class_frame(root)
  File "d:\Code\Python\py_project_votm\vm_vot_main_oop.py", line 31, in show_Class_frame
    self.show_frame(self, Class_second)
  File "d:\Code\Python\py_project_votm\vm_vot_main_oop.py", line 26, in show_frame
    frame = cont(self)
  File "d:\Code\Python\py_project_votm\vm_vot_main_oop.py", line 84, in __init__
    tk.Frame.__init__(self, parent)
  File "C:\Users\Sagar\Anaconda3\lib\tkinter\__init__.py", line 2744, in __init__
    Widget.__init__(self, master, 'frame', cnf, {}, extra)
  File "C:\Users\Sagar\Anaconda3\lib\tkinter\__init__.py", line 2292, in __init__
    BaseWidget._setup(self, master, cnf)
  File "C:\Users\Sagar\Anaconda3\lib\tkinter\__init__.py", line 2262, in _setup
    self.tk = master.tk
AttributeError: type object 'root' has no attribute 'tk'

Also, can someone tell me what other ways would be better to do this program.另外,有人可以告诉我还有什么其他方法可以更好地完成这个程序。 Sorry for bad english.抱歉英语不好。

Part of the problem is that you're not using PEP8 naming conventions, which makes your code hard to read and understand.部分问题是您没有使用PEP8命名约定,这使您的代码难以阅读和理解。 When we read the code we make assumptions based on the naming conventions, and by not using the naming conventions we end up making bad assumptions.当我们阅读代码时,我们会根据命名约定做出假设,如果不使用命名约定,我们最终会做出错误的假设。

Specifically, all of your classes need to begin with a capital letter ( Root , Vote_third , Done_fourth ).具体来说,您的所有课程都需要以大写字母开头( RootVote_thirdDone_fourth )。 When we read your code and see something like root.some_method() we're assuming you're calling some_method() on an instance.当我们阅读您的代码并看到类似root.some_method()的内容时,我们假设您正在实例上调用some_method() In your case, however, you're calling it on the class itself.但是,在您的情况下,您是在 class 本身上调用它。

The problem is this line:问题是这一行:

root.show_Class_frame(root)

root is a class , not an instance of a class. rootclass ,而不是 class 的实例 This parameter ultimately becomes the master of another widget, but you can't use a class as a master.此参数最终成为另一个小部件的主控,但您不能将 class 用作主控。 You must use an instance of a widget class as master.您必须使用小部件 class 的实例作为主控。

You are already creating an instance of root , named app .您已经在创建一个名为approot实例。 Instead of calling root.show_Class_frame() you need to be calling app.show_Class_frame .而不是调用root.show_Class_frame()您需要调用app.show_Class_frame

def tch_sel(self):
    sel = 0 #for teachers direct to page 3 not Class_second Frame
    app.show_Class_frame()

def std_sel(self):
    sel = 1 #for students move to Class_second frame
    app.show_Class_frame()

Also, as mentioned in the comments, self.show_frame(self, Class_second) needs to be changed to self.show_frame(Class_second) .此外,如评论中所述, self.show_frame(self, Class_second)需要更改为self.show_frame(Class_second)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM