Tkinter Class Import Module Issue - python

I'm trying to keep my code clean by separating the GUI from the logic.
Inside of the 'main.py' file, I'd like to call functions from other files that are imported to build the GUI.
The problem is that I cannot figure out how to build a GUI from the 'main.py' file when I try to call another file as an imported module.
Here's what I have in the 'main.py' file:
from tkinter import *
import create_btn
class Main(Tk):
def __init__(self):
super().__init__()
self.title('Main Window')
self.geometry('600x400')
self.eval('tk::PlaceWindow . center')
if __name__ == '__main__':
app = Main()
app.mainloop()
And here is what I have in the 'create_btn.py' file:
from tkinter import *
def createBTN(self):
self.b1 = Button(root, text='B1')
self.b1.pack()
So, how exactly can I build a simple button from another file that I want to import into the 'main.py', or in other words, how do I get the 'create_btn.py' file to build the button inside of the 'main.py' file? A simple example would be greatly appreciated.

I have completely rewritten your code:
# main.py
from tkinter import *
import create_btn
class Main_app:
def __init__(self):
self.root = Tk()
self.root.title("Main Window")
self.geometry("600x400")
self.eval('tk::PlaceWindow . center')
self.button = create_btn.create(self.root)
self.root.mainloop()
a = Main_app()
# create_btn.py
from tkinter import *
class create:
def __init__(self, root):
btn = Button(root, text="Button")
btn.pack()
return btn
This way you can edit the button later in main.py

Related

Python Tkimport how to make one from several windows when importing from a module?

I am writing an application in tkinter consisting of several modules in which there are classes. Each module to a separate page of the app. As I move the buttons between the pages "next", "previous" it opens a new window for me every time. How do I make it so that each time calling pages opens in the same window?
I give draft code.
thank you for your help :D
task1.py
import tkinter as tk
from Test.modul.task1 import FirstPage1
class FirstPage0:
def __init__(self, root):
self.root = root
def get_settings(self):
# Window settings
self.root.geometry("100x200")
def get_second_page(self):
FirstPage1(tk.Toplevel()).get_run_first_page()
def get_button(self):
# Add buttons
tk.Button(self.root, text="Start page", command=self.get_second_page).pack()
tk.Button(self.root, text="Exit", command=self.root.destroy).pack()
def get_run_first_page(self):
# Launching the application
self.get_settings()
self.get_button()
self.root.mainloop()
if __name__ == '__main__':
first = FirstPage0(tk.Tk())
first.get_run_first_page()
task2.py
import tkinter as tk
class FirstPage1:
def __init__(self, root):
self.root = root
def get_settings(self):
# Window settings
self.root.geometry("100x200")
def get_second_page1(self):
from Test.task import FirstPage0
FirstPage0(tk.Toplevel()).get_run_first_page()
def get_button(self):
# Add buttons
tk.Button(self.root, text="Back", command=self.get_second_page1).pack()
tk.Button(self.root, text="Exit", command=self.root.destroy).pack()
def get_run_first_page(self):
# Launching the application
self.get_settings()
self.get_button()
self.root.mainloop()
if __name__ == '__main__':
first = FirstPage1(tk.Tk())
first.get_run_first_page()
Solution
#AdrianSz, you wanted to make the buttons not stack under each other. There are three ways to do so. One, is to keep only one button and change its command and text parameters each time when the frames change. Another would be to unpack the button not needed and pack the button needed. The third would be to pack the buttons in the root window instead of frame and change the text and command parameters. I would recommend the second method as it is easier and less prone to errors.
Code
task1.py
import tkinter as tk
from Test.modul.task1 import FirstPage1
class FirstPage0:
def __init__(self, root):
self.root = root
def get_settings(self):
# Window settings
self.root.geometry("100x200")
def get_second_page(self):
self.root.pg_0_btn_start.pack_forget()
self.root_pg_0_btn_exit.pack_forget()
FirstPage1(tk.Toplevel()).get_run_first_page()
def get_button(self):
# Add buttons
self.root.pg_0_btn_start = tk.Button(self.root, text="Start page",
command=self.get_second_page).pack()
self.root_pg_0_btn_exit = tk.Button(self.root, text="Exit",
command=self.root.destroy).pack()
def get_run_first_page(self):
# Launching the application
self.get_settings()
self.get_button()
self.root.mainloop()
if __name__ == '__main__':
first = FirstPage0(tk.Tk())
first.get_run_first_page()
task2.py
import tkinter as tk
class FirstPage1:
def __init__(self, root):
self.root = root
def get_settings(self):
# Window settings
self.root.geometry("100x200")
def get_second_page1(self):
from Test.task import FirstPage0
self.root.pg_1_btn_back.pack_forget()
self.root_pg_1_btn_exit.pack_forget()
FirstPage0(tk.Toplevel()).get_run_first_page()
def get_button(self):
# Add buttons
self.root.pg_1_btn_back = tk.Button(self.root, text="Back", command=self.get_second_page1).pack()
self.root.pg_1_btn_exit = tk.Button(self.root, text="Exit", command=self.root.destroy).pack()
def get_run_first_page(self):
# Launching the application
self.get_settings()
self.get_button()
self.root.mainloop()
if __name__ == '__main__':
first = FirstPage1(tk.Tk())
first.get_run_first_page()
Note: I couldn't test this code from my side so if there are any errors, please comment on this answer
Suggestions
Since you are using modules for these, just make them inherit a class specified in a different file and operate them both from that file. There you can use self to access the methods of a subclass because the subclasses instantiate the base class and thus the self is a object of the subclass and is passed to the base class. The type of code you used is quite confusing too. I have added code to give you your wanted output using the principles I mentioned here. Hope this helped!

Getting button input from module on tkinter python

I am working on a project that uses buttons, but I would like to make it modular. The only problem I can't seem to get pass by is getting if someone is pressing the button from a different file
-file 1
from tkinter import*
class app2:
def __init__(self):
s = Tk()
but = Button(text="Test",command=subcommand)
but.pack()
s.mainloop()
def subcommand():
x = command()
x.command
class command:
def __init__(self,int):
self.command = ()
y = app2()
file 2-
from tkinter import*
from idea2 import *
def clicked():
print("HI")
x = command()
x.command(clicked())
My code basically just takes a function from another file and loads it into the command class. So basically the button can get different commands from different files. I don't know what to put for "x = command(???)" because I am trying to get that from a different file.
Basic question:
How to make my Tkinter button modular.
just pass the callback into the app2 constructor
file1
from tkinter import*
class app2:
def __init__(self,btn_callback=subcommand):
s = Tk()
but = Button(text="Test",command=btn_callback)
but.pack()
s.mainloop()
file2
from idea import app2
def my_callback(*args,**kwargs):
print("Buttton pressed...")
app = app2(my_callback)
or better yet make use of the event system in tkinter ... something like this
import tkinter as Tkinter
import tkinter.messagebox as tkMessageBox
def helloCallBack(*a,**kw):
tkMessageBox.showinfo( "Hello Python", "Hello World")
class MyApp(Tkinter.Tk):
def __init__(self):
super().__init__()
self.b = Tkinter.Button(self, text ="Hello", command = lambda:self.event_generate("<<button_click>>"))
self.b.pack()
app = MyApp()
app.bind("<<button_click>>",helloCallBack)
app.mainloop()

Python - How to call a function created into a different file

I'm pretty new in Python. I'm trying to develop a GUI using a drag and drop designer called PAGE (http://page.sourceforge.net/html/index.html) based on Tkinter.
After having created a new project, I added a button to a window. The following code is autogenerated by PAGE and saved into a file called 'myGui.py':
import sys
import tkinter as tk
import tkinter.ttk as ttk
from tkinter.constants import *
import myGui_support
class Toplevel1:
def __init__(self, top=None):
...
self.StartButton = tk.Button(self.top)
self.StartButton.configure(command=myGui_support.StartButton_Callback)
...
def start_up():
myGui_support.main()
if __name__ == '__main__':
myGui_support.main()
PAGE creates also a second file called 'myGui_support.py', in which after some import statements, the following code is included:
import myGui
def main(*args):
'''Main entry point for the application.'''
global root
root = tk.Tk()
root.protocol( 'WM_DELETE_WINDOW' , root.destroy)
# Creates a toplevel widget.
global _top1, _w1
_top1 = root
_w1 = myGui.Toplevel1(_top1)
root.mainloop()
if __name__ == '__main__':
myGui.start_up()
def StartButton_CallBack():
_w1.DebugLabel["text"] = 'START BUTTON PRESSED'
def StopButton_CallBack():
_w1.DebugLabel["text"] = 'STOP BUTTON PRESSED'
Once I run the myGui in Spyder, an Attribute error occurres:
AttributeError: module 'myGui_support' has no attribute 'StartButton_Callback'
How can it be possible? I already defined the callback function into the 'myGui_support.py'. Any suggestions?

python program using tkinter wont run due to a tclError

I'm trying to learn how to make a GUI with tkinter the conde is rather basic but I get the following error:
Exception has occurred: TclError
no display name and no $DISPLAY environment variable
File "/home/josh/Documents/VSC/python/SECOM/mainWindow.py", line 7, in __init__
self.wind = Tk()
File "/home/josh/Documents/VSC/python/SECOM/mainWindow.py", line 12, in <module>
MW = mainWindow()
When I google such error there is only answer for raspberry pi or remote servers and stuff. Im just using ubuntu(20.04) and have a conda (4.8.3) venv with python (3.8). I'm also using VSC and have the venv as interpreter in VSC. HELP :c
MainWindow.py
from tkinter import ttk
from tkinter import *
class mainWindow:
def __init__(self):
self.title = "SECOM"
self.wind = Tk()
self.wind.title(self.title)
if __name__ == '__main__':
MW = mainWindow()
window.mainloop()
You are talking a lot about windows in your code, but not much of anything is actually a window. Some of it is nothing, at all. Try This.
import tkinter as tk
class Root(tk.Tk):
def __init__(self, **kwargs):
tk.Tk.__init__(self, **kwargs)
#PUT YOUR APP HERE
if __name__ == '__main__':
root = Root()
root.title("SECOM")
root.mainloop()
Here are the problems with your script
from tkinter import ttk
#importing like this pollutes your namespace
from tkinter import *
class mainWindow:
def __init__(self):
#there is no reason to store a reference to the title
self.title = "SECOM"
#why are you burying your root in a class property
self.wind = Tk()
#this is why you don't need a reference to title
self.wind.title(self.title)
if __name__ == '__main__':
#sure
MW = mainWindow()
#window? window where? You buried this in MW.wind
window.mainloop()

Building a tkinter GUI module, so the main program doesn't need to import tkinter

I want to create a GUI module that I can import in my main program without having to import tkinter there, letting just the module handle everything. Here's how I imagine that it might work:
main.py
import gui as g
def update():
#Update the GUI with new Data from this main program
GUI = g.gui()
gui.after(1000, update)
gui.mainloop()
gui.py
import tkinter as tk
class viewer(tk.Frame):
#Some variables
def __init__(self, parent):
tk.Frame.__init(self, parent)
self.parent = parent
self.initialize(400, 100)
def initialize(self, width, height):
#Initialize some widgets, place them on grid, etc
def start(self):
#Do some other stuff, make a main window, configurations, etc
print('Started!')
Edit: "Don't ask for opinion"
How do I make this work?
import tkinter as tk
import gui as g
root = tk.Tk()
GUI = g.gui(root)
GUI.after(1000, update)
GUI.mainloop()
The above is what I don't want.
I used a workaround that seemed plausible to me:
main.py
import gui
GUI = gui.start()
GUI.after(1000, update)
GUI.mainloop()
gui.py
import tkinter as tk
def start():
root = tk.Tk()
run = viewer(root) # <- The class provided above
return run

Categories

Resources