I have just started learning tkinter and came across a problem.I have two tkinter classes. I am entering a value in an entry field of one tkinter class and trying to show it in the label in the other class. I have tried it many ways but not able to do this. Please if anyone can help me in doing so. Here is my code.
import tkinter
from tkinter import Tk, Toplevel
from tkinter import *
def main():
main_window = Tk()
app = first(main_window)
main_window.mainloop()
class first:
def __init__(self, root):
self.root = root
self.root.title('First window')
self.root.geometry('1350x700+0+0')
single_id = Label(self.root, text="Enter id", font=("Times New Roman", 14), bg='white',
fg='black')
single_id.place(x=200, y=200)
self.mystring = tkinter.StringVar(self.root)
self.txt_id = Entry(self.root, textvariable=self.mystring, font=("Times New Roman", 14), bg='white')
self.txt_id.place(x=300, y=200, width=280)
btn_search = Button(self.root, command=self.second_window, font=("Times New Roman", 15, 'bold'), text='Get Id')
btn_search.place(x=300, y=400, width=220, height=35)
def second_window(self):
self.root.destroy()
main_window = Tk()
app = second(main_window)
main_window.mainloop()
def return_id(self):
return self.mystring.get()
class second:
def __init__(self, root):
self.root = root
self.root.title('Second window')
self.root.geometry('1350x700+0+0')
id = first.return_id
get_id = Label(self.root, text=id, font=("Times New Roman", 14), bg='white',
fg='black')
get_id.place(x=200, y=350)
if __name__ == '__main__':
main()
The way I am doing it is not showing the actual value. Instead it gives
2064283946496return_id
Any help would be greatly appreciated.
What you can do is pass the first class object as an argument to the second class intializer and then call the method on it. Something like this seems to work -:
import tkinter
from tkinter import Tk, Toplevel
from tkinter import *
def main():
main_window = Tk()
app = first(main_window)
main_window.mainloop()
class first:
def __init__(self, root):
self.root = root
self.root.title('First window')
self.root.geometry('1350x700+0+0')
single_id = Label(self.root, text="Enter id", font=("Times New Roman", 14), bg='white',
fg='black')
single_id.place(x=200, y=200)
self.mystring = tkinter.StringVar(self.root)
self.txt_id = Entry(self.root, textvariable=self.mystring, font=("Times New Roman", 14), bg='white')
self.txt_id.place(x=300, y=200, width=280)
btn_search = Button(self.root, command=self.second_window, font=("Times New Roman", 15, 'bold'), text='Get Id')
btn_search.place(x=300, y=400, width=220, height=35)
def second_window(self):
self.root.destroy()
main_window = Tk()
app = second(main_window, self)
main_window.mainloop()
def return_id(self):
return self.mystring.get()
class second:
def __init__(self, root, first):
self.root = root
self.root.title('Second window')
self.root.geometry('1350x700+0+0')
id = first.return_id()
get_id = Label(self.root, text=id, font=("Times New Roman", 14), bg='white',
fg='black')
get_id.place(x=200, y=350)
if __name__ == '__main__':
main()
Related
I have created a program in Python using tkinter. I have created two seperate classes for two windows. I am opening the other window by clicking on the button of one window. I want it such that when new window opens the other should close. My code is
from tkinter import Tk, Toplevel
from tkinter import *
def main():
main_window = Tk()
app = first(main_window)
main_window.mainloop()
class first:
def __init__(self, root):
self.root = root
self.root.title('First window')
self.root.geometry('1350x700+0+0')
frame1 = Frame(self.root, bg='black')
frame1.place(x=400, y=50, width=400, height=600)
btn_1 = Button(frame1, command=self.second_window, text='open second window', font=("Times New Roman", 15, 'bold'), bd=3,
relief=RIDGE,
cursor='hand2', bg='red', fg='white', activeforeground='white', activebackground='red')
btn_1.place(x=100, y=350, width=220, height=35)
def second_window(self):
self.new_window = Toplevel(self.root)
self.app = second(self.new_window)
class second:
def __init__(self, root):
self.root = root
self.root.title('Second Window')
self.root.geometry("1350x700+0+0")
self.root.config(bg='white')
frame1 = Frame(self.root, bg='black')
frame1.place(x=400, y=50, width=400, height=600)
btn_1 = Button(frame1, command=self.first_window, text='open first window',
font=("Times New Roman", 15, 'bold'), bd=3,
relief=RIDGE,
cursor='hand2', bg='red', fg='white', activeforeground='white', activebackground='red')
btn_1.place(x=100, y=350, width=220, height=35)
def first_window(self):
self.new_window = Toplevel(self.root)
self.app = first(self.new_window)
if __name__ == '__main__':
main()
I understand this question is quite common but I cant find a soloution on here which would be applicable for my code.
You can destroy the previous window and start a new window using Tk class
Here is an example
from tkinter import *
from tkinter.ttk import Button
root = Tk()
root.title("title")
root.geometry("800x500")
def window2():
root.destroy()
window2_main = Tk()
Label(window2_main, text="Bye Bye").pack()
window2_main.mainloop()
a = Button(text="Click This", command=window2)
a.pack()
root.mainloop()
I am stuck at referencing methods and variables between classes in Tkinter.
Here is an simple example, I have three different types of windows, which I would like to put into different classes.
In the root window, I can click the button to open the second window, where I can input something in to the Text widget.
Also in the 2nd window I want the OK button to read the content in the Text widget and insert the content into another Text widget into the 3rd window. And the Cancel button can close the 2nd window and show the root window again.
There is many bugs in the code, because I couldn't figure out how to make cross references between classes to access the methods and variables.
Could anyone help me to accomplish that? Thanks.
from tkinter import *
from tkinter import scrolledtext
def main():
"""The main app function"""
root = Tk()
root_window = Root(root)
return None
class Root:
def __init__(self, root):
# Main root window configration
self.root = root
self.root.geometry("200x100")
self.btn_ok = Button(self.root, text="Open new window",
command=NewWindow)
self.btn_ok.pack(padx=10, pady=10)
def hide(self):
"""Hide the root window."""
self.root.withdraw()
def show(self):
"""Show the root window from the hide status"""
self.root.update()
self.root.deiconify()
def onClosing(self, window):
window.destroy()
self.show()
class NewWindow:
def __init__(self):
Root.hide()
self.new_window = Toplevel()
lbl = Label(self.new_window, text="Input here:")
lbl.pack(padx=10, pady=(10, 0), anchor=W)
# Create a scrolledtext widget.
self.new_content = scrolledtext.ScrolledText(
self.new_window, wrap=WORD,
)
self.new_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
# Respond to the 'Cancel' button.
btn_cancel = Button(self.new_window, text="Cancel", width=10,
command=lambda: Root.onClosing(self.new_window))
btn_cancel.pack(padx=10, pady=10, side=RIGHT)
# Add 'OK' button to read sequence
self.btn_ok = Button(self.new_window, text="OK", width=10,
command=WorkingWindow)
self.btn_ok.pack(padx=10, pady=10, side=RIGHT)
def readContent(self):
self.content = self.new_content.get(1.0, END)
self.new_window.destroy()
workwindow = WorkingWindow()
class WorkingWindow:
def __init__(self):
self.work_window = Toplevel()
self.work_content = scrolledtext.ScrolledText(self.work_window, wrap=WORD, font=("Courier New", 11))
self.work_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
self.work_content.insert(1.0, Root.content)
if __name__ == '__main__':
main()
You were almost there all you have to do is pass the instance of Root class to other class you are calling
Here is the corrected code:
from tkinter import *
from tkinter import scrolledtext
def main():
"""The main app function"""
root = Tk()
root_window = Root(root)
root.mainloop()
class Root:
def __init__(self, root):
# Main root window configration
self.root = root
self.root.geometry("200x100")
self.btn_ok = Button(self.root, text="Open new window",
command=lambda :NewWindow(self))
self.btn_ok.pack(padx=10, pady=10)
def hide(self):
"""Hide the root window."""
self.root.withdraw()
def show(self):
"""Show the root window from the hide status"""
self.root.update()
self.root.deiconify()
def onClosing(self, window):
window.destroy()
self.show()
class NewWindow:
def __init__(self, parent):
parent.hide()
self.new_window = Toplevel()
lbl = Label(self.new_window, text="Input here:")
lbl.pack(padx=10, pady=(10, 0), anchor=W)
# Create a scrolledtext widget.
self.new_content = scrolledtext.ScrolledText(
self.new_window, wrap=WORD,
)
self.new_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
# Respond to the 'Cancel' button.
btn_cancel = Button(self.new_window, text="Cancel", width=10,
command=lambda: parent.onClosing(self.new_window))
btn_cancel.pack(padx=10, pady=10, side=RIGHT)
# Add 'OK' button to read sequence
self.btn_ok = Button(self.new_window, text="OK", width=10,
command=self.readContent)
self.btn_ok.pack(padx=10, pady=10, side=RIGHT)
def readContent(self):
self.content = self.new_content.get(1.0, END)
self.new_window.destroy()
workwindow = WorkingWindow(self)
class WorkingWindow:
def __init__(self, parent):
self.work_window = Toplevel()
self.work_content = scrolledtext.ScrolledText(self.work_window, wrap=WORD, font=("Courier New", 11))
self.work_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
self.work_content.insert(1.0, parent.content)
if __name__ == '__main__':
main()
I was writing code with tkinter, and the whole code was in single file, but I successed to split in multiple files. There are two files main.py and MyFirstpanel.py. when I click on button it runs MyFirstPanel.py file. when I click on button then it goes back to main.py. but again I want to go to MyFirstPanel.py file it gives me an error.
Error
myFirstPanel = MyFirstPanel(self.root)
NameError: name 'MyFirstPanel' is not defined
Exception in Tkinter callback
My code looks like this
main.py
from tkinter import *
from MyFirstPanel import *
class MyTkWindow:
def __init__(self, root):
self.root = root # Makes the window
self.mainFrame = Frame(self.root, width=500, height=500)
self.mainFrame.grid(row=0, column=0, padx=10, pady=2)
self.user_login_btn = Button(self.mainFrame, text='Go To First Frame', relief='solid', font=('times new roman', 11),
height=1, width=6, command=self.gotofirstpanel)
self.user_login_btn.grid(row=2, column=0, columnspan=30, sticky=(N, S, E, W))
def gotofirstpanel(self):
self.mainFrame.destroy()
myFirstPanel = MyFirstPanel(self.root)
myFirstPanel.start()
def start(self):
self.root.mainloop()
if __name__ == '__main__':
root = Tk()
myWindow = MyTkWindow(root)
myWindow.start()
MyFirstPanel.py
from tkinter import *
from main import *
class MyFirstPanel:
def __init__(self, root):
self.root = root
self.mainFrame = Frame(self.root, width=500, height=500)
self.mainFrame.grid(row=0, column=0, padx=10, pady=2)
self.user_login_btn = Button(self.mainFrame, text='First Panels', relief='solid', font=('times new roman', 15),
height=1, width=6, command=self.gotomainpanel)
self.user_login_btn.grid(row=2, column=0, columnspan=10, sticky=(N, S, E, W))
def gotomainpanel(self):
self.mainFrame.destroy()
myTkWindow = MyTkWindow(self.root)
myTkWindow.start()
self.root.destroy()
def start(self):
self.root.mainloop()
Here I changed from MyFirstPanel import * to import MyFirstPanel and MyFirstPanel(self.root) to MyFirstPanel.MyFirstPanel(self.root)
main.py
from tkinter import *
import MyFirstPanel
class MyTkWindow:
def __init__(self, root):
self.root = root # Makes the window
self.mainFrame = Frame(self.root, width=500, height=500)
self.mainFrame.grid(row=0, column=0, padx=10, pady=2)
self.user_login_btn = Button(self.mainFrame, text='Go To First Frame', relief='solid', font=('times new roman', 11),
height=1, width=6, command=self.gotofirstpanel)
self.user_login_btn.grid(row=2, column=0, columnspan=30, sticky=(N, S, E, W))
def gotofirstpanel(self):
self.mainFrame.destroy()
myFirstPanel = MyFirstPanel.MyFirstPanel(self.root)
myFirstPanel.start()
def start(self):
self.root.mainloop()
if __name__ == '__main__':
root = Tk()
myWindow = MyTkWindow(root)
myWindow.start()
I have been looking at my code for a while and new to tkinter. The purpose of my code is to display text within the Canvas widget not overlay a label. But unsure how to do this:
My code is as follows:
from tkinter import *
class Example(Frame):
def printLabel(self):
self.hello = []
self.hello.append('Hello')
self.hello.append('World!')
return(self.hello)
def updatePanel(self):
self.panelA.config(text="{}".format(self.printLabel()))
def __init__(self, root):
Frame.__init__(self, root)
self.buttonA()
self.viewingPanel()
def buttonA(self):
self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height = 11, width = 13, command=lambda: self.updatePanel())
self.firstPage.place(x=0, y=0)
def viewingPanel(self):
self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3, anchor=NW, text="")
self.panelA.place(x=100, y=0)
self.cl= Canvas(self.panelA,bg='WHITE',width=165,height=113,relief=SUNKEN)
canvas_id = self.cl.create_text(15, 15, anchor="nw")
self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
self.xb.pack(side=BOTTOM,fill=X)
self.xb.config(command=self.cl.xview)
self.yb= Scrollbar(self.panelA,orient="vertical", command=self.cl.yview)
self.yb.pack(side=RIGHT,fill=Y)
self.yb.config(command=self.cl.yview)
self.cl.itemconfig(canvas_id,font=('Consolas',9), text="{}".format(self.printLabel()))
self.cl.configure(scrollregion = self.cl.bbox("all"))
self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
self.cl.config(width=250,height=150)
self.cl.pack(side=LEFT,expand=True,fill=BOTH)
def main():
root = Tk()
root.title("Tk")
root.geometry('378x176')
app = Example(root)
app.pack(expand=True, fill=BOTH)
root.mainloop()
if __name__ == '__main__':
main()
The Hello World! should display without the brackets in the Canvas but the main issue is that when I click on the Button it just overlaps the canvas and prints out the append on to the Label.
The Label should be inside the Canvas.
Here's how to fix the "main issue" along with the "brackets issue". The latter is taken care of by using the string join() method as suggested in the comments.
The updatePanel() method has been modified so it first create a Label widget with the text you want displayed in it, followed by a Canvas "window" object specifying that widget as its contents. Code for the way you were attempting to do it was also removed from the other class methods.
from tkinter import *
class Example(Frame):
def __init__(self, root):
Frame.__init__(self, root)
self.buttonA()
self.viewingPanel()
def printLabel(self):
text = []
text.append('Hello')
text.append('World!')
return ' '.join(text)
def updatePanel(self):
label = Label(self, bg='white', padx=3, pady=3, anchor=NW,
text=self.printLabel())
label.place(relx=0.5, rely=0.5, anchor=CENTER)
self.cl.create_window(100, 100, window=label) # Put Label in a Canvas "window".
def buttonA(self):
self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height=11,
width=13, command=lambda: self.updatePanel())
self.firstPage.place(x=0, y=0)
def viewingPanel(self):
self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3,
anchor=NW, text="")
self.panelA.place(x=100, y=0)
self.cl= Canvas(self.panelA, bg='WHITE', width=165, height=113, relief=SUNKEN)
canvas_id = self.cl.create_text(15, 15, anchor="nw")
self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
self.xb.pack(side=BOTTOM, fill=X)
self.xb.config(command=self.cl.xview)
self.yb= Scrollbar(self.panelA, orient="vertical", command=self.cl.yview)
self.yb.pack(side=RIGHT, fill=Y)
self.yb.config(command=self.cl.yview)
self.cl.itemconfig(canvas_id, font=('Consolas',9), text=self.printLabel())
self.cl.configure(scrollregion=self.cl.bbox("all"))
self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
self.cl.config(width=250, height=150)
self.cl.pack(side=LEFT, expand=True, fill=BOTH)
def main():
root = Tk()
root.title("Tk")
root.geometry('378x176')
app = Example(root)
app.pack(expand=True, fill=BOTH)
root.mainloop()
if __name__ == '__main__':
main()
I am learning a bit of tkinter at the moment and have come across a problem I can't seem to solve.
I have 1 class (named 'GUI') in which I first declare an object of another class (named 'client') then create a simple tkinter GUI with an entry field in which the user enters an address.
I then have a button that when pressed, gets the address and passes it to a function of the client class. This function calls another function from a library, which goes out to an external source (the 'client') and gets the value of a boolean register at that address.
Up to here I have working.
I now would like to update another entry field in the tkinter GUI with the value of that Boolean register.
Here is a code sample:
class GUI:
def __init__(self, master):
device = client()
self.master = master
#Define size (x,y) and position (top left is 0,0) of window
master.geometry("800x400+300+300")
#Disable window resize
master.resizable(width=False, height=False)
#GUI Controls
lbl_read_discrete_output = Label(self.master, text="Read boolean register")
lbl_read_discrete_output_address = Label(self.master, text="Address:")
ent_read_discrete_output_address = Entry(self.master)
btn_read_discrete_output_address = Button(self.master, text='READ', command=lambda: device.read_discrete_output(int(ent_read_discrete_output_address.get())))
ent_read_discrete_output_value = Entry(self.master, state='disabled')
#GUI Layout
lbl_read_discrete_output.grid(column=0, row=6, padx=5, pady=5)
lbl_read_discrete_output_address.grid(column=0, row=7, padx=5, pady=5)
ent_read_discrete_output_address.grid(column=1, row=7, padx=5, pady=5)
btn_read_discrete_output_address.grid(column=2, row=7, padx=5, pady=5)
ent_read_discrete_output_value.grid(column=3, row=7, padx=5, pady=5)
class client:
def __init__(self):
pass
def read_discrete_output(self, address):
data = self._client.read_coils(address-1, 1).bits[0:1]
if not data[0]:
#Update entry field 'ent_read_discrete_output_value' with "FALSE"
else:
#Update entry field 'ent_read_discrete_output_value' with "TRUE"
def main():
#Create GUI object
root = Tk()
app = GUI(root)
root.mainloop()
if __name__ == '__main__':
main()
Any help would be greatly appreciated!
You can solve that problem, this way:
import tkinter as tk
from tkinter import *
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
class GUI:
def __init__(self, master):
self.master = master
#GUI Controls
lbl_read_discrete_output = Label(self.master, text="Read boolean register")
lbl_read_discrete_output_address = Label(self.master, text="Address:")
self.ent_read_discrete_output_address = Entry(self.master)
btn_read_discrete_output_address = Button(self.master, text='READ', command=lambda: device.read_discrete_output(int(self.ent_read_discrete_output_address.get())))
self.ent_read_discrete_output_value = Entry(self.master, state='disabled')
#GUI Layout
lbl_read_discrete_output.grid(column=0, row=6, padx=5, pady=5)
lbl_read_discrete_output_address.grid(column=0, row=7, padx=5, pady=5)
self.ent_read_discrete_output_address.grid(column=1, row=7, padx=5, pady=5)
btn_read_discrete_output_address.grid(column=2, row=7, padx=5, pady=5)
self.ent_read_discrete_output_value.grid(column=3, row=7, padx=5, pady=5)
self.x=self.ent_read_discrete_output_address.get()
print(self.x)
device=clientx(self.ent_read_discrete_output_value,self.ent_read_discrete_output_address.get())
class clientx():
def __init__(self,ent,address):
self.address=address
self.ent=ent
def read_discrete_output(self, address):
with ModbusClient('127.0.0.1') as client:
data = self.client.read_coils(address-1, 1).bits[0:1]
if not data[0]:
self.ent.config(state="disabled")
else:
self.ent.config(state="disabled")
def main():
#Create GUI object
root = tk.Tk()
app = GUI(root)
root.mainloop()
if __name__ == '__main__':
main()
Let me know if this works.