Home > Net >  Tkinter causing attribute error when accessing attribute from MyApp class
Tkinter causing attribute error when accessing attribute from MyApp class

Time:12-13

import tkinter as tk
from tkinter import ttk
import customtkinter
import title
import user
from tkinter import *
from PIL import ImageTk, Image
import requests


class MyApp(tk.Tk):

    def __init__(self):
        super().__init__()

        # Declare use as none until logged in
        self.currentUser = None
        # Declaring Title that will be displayed on a Title page as none until it is determined
        self.currentTitle = None

        # Set the title of the window
        self.title('Streaming Recommendations')

        # Set the screen resolution to 1080p (1920x1080)
        self.geometry('1920x1080')

        style = ttk.Style()
        style.theme_use('clam')

        # Create the screens for the application
        self.pages = {
            'login': LoginScreen(self),
            'home': HomeScreen(self),
            'title': TitleScreen(self)
        }

        # Start with the login screen
        self.show_screen('login')

    def show_screen(self, screen_name):
        # Hide all screens
        for screen in self.pages.values():
            screen.hide()


        # Show the selected screen
        self.pages[screen_name].show()

    def set_user(self, loginUser):
        self.currentUser = loginUser

    def get_user(self):
        return self.currentUser

    def set_title(self, newTitle):
        self.currentTitle = newTitle

    def get_title(self):
        return self.currentTitle


class LoginScreen:
    def __init__(self, app):
        self.app = app
        self.login_frame = ttk.Frame(app, width=960, height=540)

        # Create the username and password labels and entry fields
        self.username_label = ttk.Label(self.login_frame, text='Username:')
        self.username_label.grid(row=0, column=0)
        self.username_entry = ttk.Entry(self.login_frame)
        self.username_entry.grid(row=0, column=1)

        self.password_label = ttk.Label(self.login_frame, text='Password:')
        self.password_label.grid(row=1, column=0)
        self.password_entry = ttk.Entry(self.login_frame, show='*')
        self.password_entry.grid(row=1, column=1)

        # Create the login and cancel buttons
        self.login_button = ttk.Button(self.login_frame, text='Login',
                                       command=self.login)
        self.login_button.grid(row=2, column=0)
        self.cancel_button = ttk.Button(self.login_frame, text='Cancel',
                                        command=self.cancel)
        self.cancel_button.grid(row=2, column=1)

    def show(self):
        self.login_frame.place(relx=0.5, rely=0.5, anchor=CENTER)

    def hide(self):
        self.login_frame.place_forget()

    def login(self):
        # Get the username and password from the entry fields
        username = self.username_entry.get()
        password = self.password_entry.get()

        # Verify the username and password
        main_user = user.User(username, password)
        if not main_user.login_status:
            self.username_entry.delete(0, END)
            self.password_entry.delete(0, END)
        else:
            self.app.set_user(main_user)
            self.app.show_screen('home')

    def cancel(self):
        # Clear the entry fields and close the login window
        self.username_entry.delete(0, END)
        self.password_entry.delete(0, END)
        self.app.destroy()


class TitleScreen:
    def __init__(self, app):
        self.displayTitle = app.get_title()
        self.app = app
        self.title_frame = ttk.Frame(app, width=960, height=540)

    def show(self):
        self.title_frame.pack(side=LEFT)
        self.title_frame.place(relx=0.5, rely=0.5, anchor=CENTER)

    def hide(self):
        self.title_frame.pack_forget()


class HomeScreen:
    def __init__(self, app):
        self.app = app
        self.start_y = None
        self.start_x = None

        self.home_frame = ttk.Frame(app, width=1920, height=1080)
        self.photo = Image.open('testposter2.jpg')
        self.photo = ImageTk.PhotoImage(self.photo.resize((100, 150)))
        # Create a canvas for the rows of movie posters
        self.poster_canvas = Canvas(self.home_frame, width=1920, height=540, )
        self.poster_canvas.pack()



        # Create a frame for the movie posters
        self.poster_frame = ttk.Frame(self.poster_canvas)
        self.poster_frame.pack()



        # Create some example movie posters


        for i in range(20):

            poster = ttk.Button(self.poster_frame, image=self.photo, command=self.show_title())
            poster.grid(row=0, column=i)
            # Bind the left mouse button and drag events to a custom function
            poster.bind('<Button-1>', self.on_drag_start)
            poster.bind('<B1-Motion>', self.on_drag)


    def show(self):
        self.home_frame.pack(side=LEFT)

    def hide(self):
        self.home_frame.pack_forget()

    # Define the custom function for handling mouse events
    def on_drag_start(self, event):
        print('on drag start')
        # Save the starting position of the drag event
        self.start_x = event.x

    def on_drag(self, event):
        print('on drag')
        # Calculate the distance moved in x and y directions
        delta_x = event.x - self.start_x

        # Update the position of the poster frame
        self.poster_frame.place(x=self.poster_frame.winfo_x()   delta_x)
        print(self.poster_frame.winfo_x())
        # Save the current position as the starting position for the next drag event
        self.start_x = event.x
        self.start_y = event.y

    def show_title(self):
        # Get the title associated with the selected poster
        selected_title = None
        self.app.show_screen('login')





theapp = MyApp()
theapp.mainloop()

Im getting an error running self.app.show_screen('login') in my homescreen class but it works fine in the loginscreen class and my app.

any idea why I'm getting this error

Traceback (most recent call last):
  File "C:\Users\Exser\PycharmProjects\Testing\app.py", line 216, in <module>
    theapp = MyApp()
  File "C:\Users\Exser\PycharmProjects\Testing\app.py", line 33, in __init__
    'home': HomeScreen(self),
  File "C:\Users\Exser\PycharmProjects\Testing\app.py", line 153, in __init__
    poster = ttk.Button(self.poster_frame, image=self.photo, command=self.show_title())
  File "C:\Users\Exser\PycharmProjects\Testing\app.py", line 187, in show_title
    self.app.show_screen('login')
  File "C:\Users\Exser\PycharmProjects\Testing\app.py", line 42, in show_screen
    for screen in self.pages.values():
  File "C:\Users\Exser\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 2354, in __getattr__
    return getattr(self.tk, attr)
AttributeError: '_tkinter.tkapp' object has no attribute 'pages'

I'm not sure what is causing AttributeError: '_tkinter.tkapp' object has no attribute 'pages' when calling it from homescreen class but not from anywhere else

CodePudding user response:

The error is on this line:

poster = ttk.Button(self.poster_frame, image=self.photo, command=self.show_title())

You should leave the parenthesis:

poster = ttk.Button(self.poster_frame, image=self.photo, command=self.show_title)

Otherwise show_title will be called on initialization of Homescreen which occurs before MyApp.pages has been declared. Hence the error.

  • Related