0

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'. But I am able to raise my second frame from the root class but that's not what i want. 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. 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.

  • According to the [ttkthemes docs](https://ttkthemes.readthedocs.io/en/latest/example.html), you have to use `from ttkthemes import ThemedTk` and then `class root(ThemedTk): ; def __init__(self): ; super().__init__(theme='arc')` – stovfl Oct 06 '19 at 15:07
  • Your `def show_frame(self, cont):` looks wrong. See [Switch between two frames in tkinter](https://stackoverflow.com/a/7557028/7414759) – stovfl Oct 06 '19 at 15:22
  • I fail to implement the method provided in [link](https://stackoverflow.com/a/7557028/7414759) given by @stovfl in my program by myself mostly because I'm new to oop (this is my 2nd program in oop), it would be helpful if someone else can implement it and post the code. –  Oct 06 '19 at 16:10
  • _"it would be helpful if someone else can implement it and post the code."_ - that's not what stackoverflow is for. – Bryan Oakley Oct 06 '19 at 16:14
  • Nevermind the problems solved ^_^ –  Oct 07 '19 at 06:43

1 Answers1

0

Part of the problem is that you're not using PEP8 naming conventions, which makes your code hard to read and understand. 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). When we read your code and see something like root.some_method() we're assuming you're calling some_method() on an instance. In your case, however, you're calling it on the class itself.

The problem is this line:

root.show_Class_frame(root)

root is a class, not an instance of a class. This parameter ultimately becomes the master of another widget, but you can't use a class as a master. You must use an instance of a widget class as master.

You are already creating an instance of root, named app. Instead of calling root.show_Class_frame() you need to be calling 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).

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • All right, all solved with the help of above answer. Changes made- used ```Home_first.pack_forget(self) ; app.show_frame(Class_second)``` and removed ```show_Class_frame()``` method (there was no need for it) that's it. –  Oct 07 '19 at 06:39