Customtkinter "master" Parameter beim erstellen von einem Textfeld?
Hey,
ich habe eine Klasse erstellt die ein Hauptfenster erstellt und möchte aus einer anderen klasse einen Textfeld erstellen der sich auf das Hauptfenster bezieht.
So wie ich es verstanden habe braucht man dafür den Parameter "master" um vorzugeben in welchem Fenster nun der Textfeld angezeigt werden soll.
Leider funktioniert das bei mir nicht so richtig. Hat jemand davon Ahnung und kann mir meinen Fehler zeigen?
lieben Dank! :)
main.py
import view
import controller
import customtkinter as ctk
class Main(view.MainWindow):
def __init__(self):
super().__init__()
self.main_window = view.MainWindow()
self.main_window.set_size("1680", "900")
self.main_window.set_title("YourTerminal")
controller.InputBoxMain()# Nach meinem Verständnis muss hier der Master-Parameter angegeben werden. Wie übergebe ich diesen?
def run(self):
self.main_window.get_window().mainloop()
if __name__ == "__main__":
app = Main()
app.run()
view.py
import customtkinter as ctk
class MainWindow:
def __init__(self):
self.window = ctk.CTk()
def set_size(self, width, height):
self.window.geometry(f"{width}x{height}")
def set_title(self, title):
self.window.title(title)
def get_window(self):
return self.window
class WindowTemplate:
def __init__(self):
self.window = ctk.CTkToplevel()
def set_size(self, width, height):
self.window.geometry(f"{width}x{height}")
def set_title(self, title):
self.window.title(title)
def get_window(self):
return self.window
# der master Parameter gibt an wo diese Box angezeigt werden soll
class InputBoxTemplate:
def __init__(self, master): # Wie übergebe ich den master Parameter?
self.master = master
self.box = ctk.CTkEntry(self.master)
def set_size(self, width, height, y, x):
self.box.place(width=width, height=height, pady=y, padyx=x)
def set_placeholder(self, placeholder):
self.box._placeholder_text(f"{placeholder}")
controller.py
import view
import customtkinter as ctk
import main
class InputBoxMain(view.InputBoxTemplate, main.Main):
def __init__(self):
super().__init__()
self.master = ctk.CTk()
self.window = view.InputBoxTemplate(self.master)# Oder der Master-Parameter wird hier übergeben? Hier versuche ich master auf ctk.CTk zu beziehen. Das ist das Haupfenster.
self.window.set_size(200, 200, 10, 10)
self.window.set_placeholder("Hier steht der Placeholder")
Hier die Fehlermeldung falls relevant:
Traceback (most recent call last):
File , line 1, in <module>
import view
File , line 2, in <module>
import main
File , line 2, in <module>
import controller
File " line 4, in <module>
class InputBoxMain(view.InputBoxTemplate, main.Main):
^^^^^^^^^^^^^^^^^^^^^
AttributeError: partially initialized module 'view' has no attribute 'InputBoxTemplate' (most likely due to a circular import)
1 Antwort
Deine Vererbungsstrukturen erscheinen etwas chaotisch. Um das also einmal vorauszunehmen: Solltest du dich hinsichtlich der objektorientierten Programmierung noch nicht auskennen, wäre es vorteilhaft, sich erst einmal diesem Thema zu widmen, bevor du mit CustomTkinter weitermachst.
1) Ich sehe keinen Sinn, wieso die Main-Klasse von view.MainWindow erben sollte. Sie repräsentiert kein Fensterobjekt. Sie besitzt lediglich ein Attribut (main_window), welches ein view.MainWindow-Objekt hält.
Auch für InputBoxMain solltest du die Hierarchie überdenken.
2) Im gesamten Programm sollte es nur einen einzigen Root (zeitgleich die oberste Komponente) geben. Du erstellst in InputBoxMain bereits einen zweiten. Das window-Attribut von MainWindow verweist auf den ersten Root.
3) Die set_size-Methode von InputBoxTemplate tut nicht das, was ihr Name verspricht. In ihr versuchst du, die Komponente an eine bestimmte Position zu verschieben. Außerdem vergibst du der place-Methode dabei falsche Argumente.
Richte die Komponente am besten gleich nach dem Erstellen mit pack aus.
self.box.pack(padx=x, pady=y)
Die Größe des Feldes kannst du entweder über Argumente des Konstruktors bestimmen oder nachträglich via configure:
self.box.configure(width=width)
self.box.configure(height=height)
Wirf diesbezüglich auch einen Blick in die Dokumentation.
4) Bei _placeholder_text handelt es sich um ein Attribut, keine Methode. Auch hier gilt: Wenn du dessen Wert nachträglich ändern möchtest, nutze configure.
self.box.configure(placeholder_text=f"{placeholder}")
5) Mit dem master gibst du das Parent Widget (die Elternkomponente) für ein Widget an.
In deinem Fall soll das Eingabefeld in dein Hauptfenster gehängt werden. Demzufolge müsstest du dir in Main das Rootobjekt der MainWindow-Instanz holen und sie an InputBoxMain weitergeben.
controller.InputBoxMain(self.main_window.get_window())
Der Konstruktor von InputBoxMain muss demzufolge um einen Parameter ergänzt werden. Dessen Wert wird an den Konstruktor von InputBoxTemplate überreicht.
def __init__(self, master):
self.window = view.InputBoxTemplate(master)
# etc. ...
Dort kannst du das empfangene Objekt nutzen, um das Eingabefeld zu kreieren.
def __init__(self, master):
self.box = ctk.CTkEntry(master=master)