Connecting two files or classes in Python - python-3.x

I have two pages(each having a class) that that needs to be connected, page1(file1.py) and page2(file2.py).
I want to open page2 with a button that will be on page1. As mentioned the codes for each page are in separate files, file1 and file2.
I used import file2 but as soon as I run the program it opens and runs file2.py which I dont want. I want to open page2 via button when the user needs to open it.
Any suggestions???
Regards
Khisrow

Just put the second page inside a class, import that inside a function and call that. Then give the function as the command to a Button.
Like this:
Module_one:
import tkinter as tk
def test_func():
import Module_two
Module_two.TestClass()
root = tk.Tk()
b = tk.Button(root, text="Click", command=lambda: test_func())
b.pack()
root.mainloop()
Module_two:
class TestClass:
def __init__(self):
import tkinter as tk
root = tk.Toplevel()
lbl = tk.Label(root, text="Test Label")
lbl.pack()

Related

why does importing a tk variable from main break this code?

I'm trying to organize my code into two separate modules - main, and new_window
main passes a tk object to new_window to populate it with a label and a button.
Pressing the button is supposed to close the window.
This is main:
import tkinter as tk
from new_window import *
#I create a tk object called "main_menu"
main_menu = tk.Tk()
#The tk object is passed to a class in another module to have its properties applied
main_menu_obj = MainMenu(main_menu)
#the main loop function is called as required by tk
main_menu.mainloop()
This is new_window:
import tkinter as tk
#to close the window, the tk variable created in main must is imported
from main import main_menu
class MainMenu:
#when this module receives the tk object from main, it adds a label and a button
def __init__(self, root):
print('main menu')
root.title('Main Menu')
Label_1 = tk.Label(root, text='Main Menu')
Button_1 = tk.Button(root, text='close',command=self.close)
Label_1.pack()
Button_1.pack()
#when the button is pressed, the tk object "main_menu" is destroyed
def close(self):
print('closing window')
main.main_menu.destroy()
When I run this, I receive: NameError: name 'MainMenu' is not defined. But I just defined this class in new_window. What mistake am I making? If I comment out "from main import main_menu" and comment out "main.main_menu.destroy()" it works great and prints "closing window" when I press the close button. (but obviously it doesn't close the window then).
It is circular import issue, i.e. A imports B and B imports A.
Actually you don't need to import main inside new_window because you have already passed the reference of the root window to MainMenu class. Therefore you can use this reference to close the root window.
Updated new_window.py:
import tkinter as tk
# don't need to import main here
class MainMenu:
#when this module receives the tk object from main, it adds a label and a button
def __init__(self, root):
# save argument root
self.root = root
print('main menu')
root.title('Main Menu')
Label_1 = tk.Label(root, text='Main Menu')
Button_1 = tk.Button(root, text='close',command=self.close)
Label_1.pack()
Button_1.pack()
#when the button is pressed, the tk object "main_menu" is destroyed
def close(self):
print('closing window')
self.root.destroy()

Calling functions without closing the master window - Python Tkinter

I've tried to create a software. In this software there is a menu widget with function button that open functions e widgets. But, I've noticed, to keep going on script, it's necessary to close the master window (menu).
I've created an example to you understand my problem.
from tkinter import *
#Create Fuction that open new fuctions and widget
def test():
#Open a new widget
def fun_test_1():
top_level = Tk()
def test1():
top_level1 = Toplevel()
top_level1.title('new1')
top_level1.mainloop()
Button(top_level, text='test1',command=test1).pack()
top_level.mainloop()
fun_test_1()
#Before, open the second widget
def fun_test_2():
print('def fun_test_2(): works!')
top_level = Tk()
def test1():
top_level1 = Toplevel()
top_level1.title('new1')
top_level1.mainloop()
Button(top_level, text='Button', command=test1).pack()
top_level.mainloop()
fun_test_2()
root = Tk()
root.title('MASTER')
Button(root, text='Button',command=test).pack()
root.mainloop()
So, I need that fun_test_2() be called without close the root widget
And all functions i've tried to change Tk() to Toplevel() and Toplevel() to Tk().
The problem is you calling mainloop more than once, and for creating more than one instance of Tk. When you call mainloop, it won't return until that window has been destroyed. That's a fundamental aspect of how tkinter works.
The solution is to not create more than one instance of Tk and to not call mainloop more than once. If you need multiple windows, create instances of Toplevel. And again, only call mainloop once in total, not once per window.

How to open two modules in one window, Python Tkinter

I have a question: i am tossing the code from 2ch files, i have already lost ideas. Calling fileA.py opens a window for me with two buttons exit and start. Exit works but when I click start I need to open the second window fileB.pt. (I want both windows to open in one window) Seemingly works only problem I have is it doesn't open "window on window" but "docks underneath" and I have the effect of two windows open :/. Please help, thank you in advance:) Python 3.10
fileA.py
import tkinter as tk
from GUI.module.scale_of_img import get_scale
class FirstPage:
def __init__(self, root):
self.root = root
def get_settings(self):
# Window settings
self.root.title('....')
self.root.resizable(False, False)
self.root.geometry("1038x900")
if __name__ == '__main__':
first = FirstPage(tk.Tk())
first.get_run_first_page()
fileB.py
import tkinter as tk
"importy..."
''' The second side of the application '''
class SecondPage:
def __init__(self, root=None):
self.root = root
self.my_canvas = tk.Canvas(self.root, width=1038, height=678)
self.my_canvas.pack(fill="both", expand=True)
if __name__ == '__main__':
second = SecondPage(tk.Tk())
second.get_run()
in order to put two "windows" in the same "window" you need to put all items inside a Frame, which is basically a container than you can simply pack when you want everything to show and unpack when you want everything in it to disapear.
all items in the first window will be children of a frame and all items in the second window will be children of another frame, and to switch you just need to call pack_forget() on one and pack() on another.
for the first file
class FirstPage:
def __init__(self, root):
self.root = root
self.frame = tk.Frame(root)
self.frame.pack(expand=True)
def get_picture(self):
# all items inside this window must be children of self.frame
self.my_canvas = tk.Canvas(self.frame, width=1038, height=500)
...
def get_second_page(self):
from GUI.module.second_page import SecondPage
self.frame.pack_forget() # to hide first page
# self.frame.destroy() # if you are never brining it back
SecondPage(self.root).get_run()
and for the second file
class SecondPage:
def __init__(self, root=None):
self.root = root
self.frame = tk.Frame(root) # new frame
self.frame.pack(expand=True)
self.my_canvas = tk.Canvas(self.frame, width=1038, height=678)
self.my_canvas.pack(fill="both", expand=True)
def get_button(self):
# Add buttons
# all here should be children of self.frame now
button1 = tk.Button(self.frame, text="...", )
...
you could destroy the first frame when you switch over to save some resources if you don't intend to return to it ever again, but the difference in memory is negligible.
assuming what you want is another Tk window to open, you shouldn't give it the same root, instead use an instance of Toplevel
from tkinter import Toplevel
# class definition here
def get_second_page(self):
from GUI.module.second_page import SecondPage
SecondPage(Toplevel(self.root)).get_run()
passing the Toplevel as a child of self.root is necessary, but note that the two windows have different roots.
Edit: turns out this wasn't what the OP ment by "window on window" -_-, but it am keeping it here for other readers.

multiple commands for a tkinter button

I have been trying to execute 2 commands in 1 button. I have read that using lambda can solve the problem. But my situation is a little different. On button press, one command is to destroy the existing GUI, and the second command, I want is to open another SERVER GUI. Below is my existing button functionality.
exit_button = Button(topFrame, text='Quit', command=window.destroy)
How can I open another GUI using same button?
Thank you for any help.
Edit:-
I have now created the below function:
def close_func():
os.kill(os.getpid(), signal.SIGINT)
GUI_Interface()
window.destroy()
server_socket.close()
GUI_Interface is a function that I need to call after closing the existing .py file. If I put GUI_Interface as the first command for close_func(), then it really does not go back to the 2nd step and never closes the existing.py file.
And if I place GUI_Interface in the end, it just closes the existing one and nevr opens the function of the new .py file
Three options at least:
using or (with lambda if arguments):
from tkinter import Tk, Button
root = Tk()
Button(root, text='Press', command=lambda: print('hello') or root.destroy() or print('hi')).pack()
root.mainloop()
important to use or because and didn't work (don't know why or how this works at all)
or use function definitions:
from tkinter import Tk, Button
def func():
print('hello')
root.destroy()
print('hi')
root = Tk()
Button(root, text='Press', command=func).pack()
root.mainloop()
or lists with lambda:
from tkinter import Tk, Button
def func():
print('hello')
root.destroy()
print('hi')
root = Tk()
Button(root, text='Press', command=lambda: [print('hello'), root.destroy()]).pack()
root.mainloop()

How do I display a message before closing the tkinter window?

A message is required to be shown just before closing the tkinter window on the click of a close button added to the window.
lab = Label(window,text = 'thank you')
lab.grid()
window.destroy()
I used the above code to do so, but the window gets closed before the message is being displayed
Can I have the solution for this?
You can either use this:
from tkinter import Tk
import tkinter.messagebox as msgbox
def display_msg():
msgbox.showinfo(title='', message='Thank You')
root.destroy()
root = Tk()
root.protocol('WM_DELETE_WINDOW', display_msg)
root.mainloop()
which will show You a messagebox before closing,
or if You want to display a widget use this:
from tkinter import Tk, Label
def display_msg():
msg = Label(root, text='Thank You!')
msg.pack()
root.after(3000, root.quit)
root = Tk()
root.protocol('WM_DELETE_WINDOW', display_msg)
root.mainloop()
When You protocol root with 'WM_DELETE_WINDOM' You can make it execute a function when You try to close the window.
In the first example it will just show an infobox.
In the second example it will wait for 3 seconds (3000 miliseconds) and then destroy the root

Resources