Zingzy/hPyT

Bug in window_frame.center_relative()

Closed this issue · 7 comments

Hello @Zingzy,
First of all, watch this video:

Video not found...

I read the documentation about this method that you explained. But the example of this method ends with an error:

window = CTk()
window.title("Primary Window")

child_window = CTkToplevel()

window_frame.center_relative(window, child_window)

window.bind("<Configure>", lambda event: window.center_relative(window, child_window))

------------------------------------------------------------------------

  File "g:\program\full\test.py", line 189, in <lambda>
    window.bind("<Configure>", lambda event: window.center_relative(window, child_window))
                                             ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\tkinter\__init__.py", line 2410, in __getattr__
    return getattr(self.tk, attr)
           ^^^^^^^^^^^^^^^^^^^^^^
AttributeError: '_tkinter.tkapp' object has no attribute 'center_relative'

What is the solution to the problem?

Hello @Nigacatch , thank you for pointing out the bug, there indeed was some mistake in the documentation.

This is the correct updated code to implement that:

window = CTk()
window.title("Primary Window")

child_window = CTkToplevel()

window_frame.center_relative(window, child_window)

window.bind("<Configure>", lambda event: window_frame.center_relative(window, child_window))

previously it was lambda event: window.center_relative whereas it should have been lambda event: window_frame.center_relative

I will update this in the documentation too..

Thanks @Zingzy , but the main problem is in the video... that other widgets are broken when this method is used. I also looked at the program log file and found 2 errors which I posted below.

['  File "C:\\Program Files\\Python311\\Lib\\tkinter\\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "g:\\program\\full\\main.py", line 1981, in <lambda>
    self.bind("<Configure>", lambda event: window_frame.center_relative(self, top))
                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\\Users\\anar BRO\\AppData\\Roaming\\Python\\Python311\\site-packages\\hPyT\\hPyT.py", line 402, in center_relative
    ctypes.windll.user32.GetWindowRect(hwnd_child, ctypes.byref(rect_child))
']
<class 'ctypes.ArgumentError'>: argument 1: TypeError: Don't know how to convert parameter 1

-----------------------------------------------------------

['  File "C:\\Program Files\\Python311\\Lib\\tkinter\\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:\\Program Files\\Python311\\Lib\\tkinter\\__init__.py", line 861, in callit
    func(*args)
  File "g:\\program\\full\\main.py", line 1922, in check_webservice_status_every_sec
    border_color.reset(self)
  File "C:\\Users\\anar BRO\\AppData\\Roaming\\Python\\Python311\\site-packages\\hPyT\\hPyT.py", line 267, in reset
    old_ex_style = get_window_long(hwnd, GWL_EXSTYLE)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
']
<class 'ctypes.ArgumentError'>: argument 1: TypeError: Don't know how to convert parameter 1

Is there a way to fix this bug?

@Nigacatch can you please show me the code where the error is happening? Also are you using customtkinter or some other framework?

Absolutely @Zingzy,
My program code:

global click_counter_about
click_counter_about = 1 

....

class About(customtkinter.CTkToplevel):
    def __init__(self):
        super().__init__()
        self.geometry('600x300')
        self.grab_set()
        self.title('About')
        self.configure(fg_color="#16191e")
        maximize_minimize_button.hide(self)
        mode = MicaTheme.DARK  
        style = MicaStyle.ALT    
        hwnd = self.frame() 
        ApplyMica(HWND=hwnd, Theme=mode, Style=style)
        frame = customtkinter.CTkFrame(
            self, height=285, width=585, corner_radius=10)
        frame.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)

        me_image = customtkinter.CTkImage(
            Image.open(resourcePath('icons/user.png')), size=(75, 75))

        main_pic = customtkinter.CTkLabel(
            frame, text='', image=me_image)
        main_pic.place(relx=0.5, rely=0.15, anchor=tkinter.CENTER)

        customtkinter.CTkFrame(frame, width=570, height=3, fg_color='#4C4E52').place(relx=0.5, rely=0.31, anchor=tkinter.CENTER)
       
        customtkinter.CTkFrame(frame, width=570, height=3, fg_color='#4C4E52').place(relx=0.5, rely=0.74, anchor=tkinter.CENTER)
     
        window_frame.center(self)

class App(customtkinter.CTk):
    def __init__(self):
        super().__init__()
        self.title("Talayar")
        self.configure(fg_color="#16191e")
        self.geometry(center(self, 720, 1280))
        self.resizable(False, False)
        customtkinter.set_appearance_mode('dark')
        mode = MicaTheme.DARK 
        style = MicaStyle.ALT  
        hwnd = self.frame()  
        ApplyMica(HWND=hwnd, Theme=mode, Style=style)

        ....

        frame = customtkinter.CTkFrame(
            self, height=701, width=212, corner_radius=10)
        frame.place(relx=0.91, rely=0.5, anchor=tkinter.CENTER)

        logo_image = customtkinter.CTkImage(
            Image.open(resourcePath('icons/logo.png')), size=(118, 118))

        main_logo = customtkinter.CTkLabel(
            frame, text='', image=logo_image)
        main_logo.place(relx=0.5, rely=0.091, anchor=tkinter.CENTER)

        def open_about(event):
            global click_counter_about
            if click_counter_about == 5:
                top = About()
                window_frame.center_relative(self, top)
                self.bind("<Configure>", lambda event: window_frame.center_relative(self, top))
                click_counter_about = 1
            else:
                click_counter_about += 1
        
        main_logo.bind("<Button-1>", open_about)

        ....

This is a simple code example that gives this error (also, when the child window is closed and when we move the main window with the mouse, this error is strongly displayed in the terminal):

from customtkinter import *
import tkinter
from hPyT import *

window = CTk()
window.title("Primary Window")
window.geometry('600x300')
window_frame.center(window)

def top():
    ctktop = CTkToplevel()
    ctktop.title('Child Window')
    ctktop.geometry('300x150')
    window_frame.center_relative(window, ctktop)
    window.bind("<Configure>", lambda event: window_frame.center_relative(window, ctktop))
    
btn1 = CTkButton(master=window, width=300,text='click', command=top)
btn1.place(relx=0.5, rely=0.1, anchor=tkinter.CENTER)

btn2 = CTkButton(master=window, width=300, text='tested text 1')
btn2.place(relx=0.5, rely=0.3, anchor=tkinter.CENTER)

btn3 = CTkButton(master=window, width=300, text='tested text 2')
btn3.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)

window.mainloop()

....

Traceback (most recent call last):
  File "C:\Program Files\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "g:\program\full\test.py", line 193, in <lambda>
    window.bind("<Configure>", lambda event: window_frame.center_relative(window, ctktop))
                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\anar BRO\AppData\Roaming\Python\Python311\site-packages\hPyT\hPyT.py", line 402, in center_relative
    ctypes.windll.user32.GetWindowRect(hwnd_child, ctypes.byref(rect_child))
ctypes.ArgumentError: argument 1: TypeError: Don't know how to convert parameter 1

In the code above, the widgets do not look bad like in the video, because very few widgets are defined... but the error is displayed.

@Nigacatch I think I found the error, you see the when the window is closed, the main window is still binded to the center_relative function which tries to center the destroyed window every time. Here is the fixed code:

from customtkinter import *
import tkinter
from hPyT import *

window = CTk()
window.title("Primary Window")
window.geometry('600x300')
window_frame.center(window)

def top():
	ctktop = CTkToplevel()
	ctktop.title('Child Window')
	ctktop.geometry('300x150')
	window_frame.center_relative(window, ctktop)

	window.bind("<Configure>", lambda event: window_frame.center_relative(window, ctktop))

	def on_close():
		window.unbind("<Configure>")
		ctktop.destroy()

	ctktop.protocol("WM_DELETE_WINDOW", on_close)

btn1 = CTkButton(master=window, width=300,text='click', command=top)
btn1.place(relx=0.5, rely=0.1, anchor=tkinter.CENTER)

btn2 = CTkButton(master=window, width=300, text='tested text 1')
btn2.place(relx=0.5, rely=0.3, anchor=tkinter.CENTER)

btn3 = CTkButton(master=window, width=300, text='tested text 2')
btn3.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)

window.mainloop()

I've added an on_close function inside the top function, which is called when the child window is being closed. It unbinds the <Configure> event and then destroys the child window.

Thank you @Zingzy,
The bug was fixed. I added the modified code to the main program and it works correctly and I have no errors. Add this method on_close to the library or put it in the documentation so that this problem does not occur.

For sure, I will update the documentation.