I was trying to create some nested widgets within file widget however exit is appearing above open. I tried changing the index but still the problems persists any idea how to fix this?
#!/usr/bin/python3
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
import sys
class GuiBaseClass():
def __init__(self,root):
# create widgets
self.root=root
root.title('GUIBASECLASS V0.1')
root.option_add('*tearOff', False)
self.menu=dict()
self.menubar = tk.Menu(root)
#File
menu_file = tk.Menu(self.menubar)
self.menubar.add_cascade(menu=menu_file,label='File',underline=0)
menu_file.add_separator()
menu_file.add_command(label='Exit', command=self.Exit,underline=0)
#Edit
menu_edit = tk.Menu(self.menubar)
self.menubar.add_cascade(menu=menu_edit,label='Edit',underline=0)
#Help
menu_help = tk.Menu(self.menubar)
menu_help.add_command(label='About', command=self.About, underline=0)
self.menubar.add_cascade(menu=menu_help,label ='Help',underline=0)
#config
root.config(menu=self.menubar)
self.menu['menubar'] = self.menubar
self.menu['File'] = menu_file
self.menu['Edit'] = menu_edit
self.menu['Help'] = menu_help
self.frame = ttk.Frame(root)
self.frame.pack(fill='both',expand=True)
# public functions
def mainLoop(self):
self.root.mainloop()
def getFrame(self):
return(self.frame)
def getMenu(self,entry):
if entry in self.menu:
return (self.menu[entry])
else:
# we create a new one
last = self.menu['menubar'].index('end')
self.menu[entry]= tk.Menu(self.menubar)
self.menu['menubar'].insert_cascade(
last, menu=self.menu[entry],label=entry)
return(self.menu[entry])
# private functions
def Exit(self,ask=True):
res = tk.messagebox.askyesno(title='Are you sure',message='Really quit the application')
if res:
sys.exit(0)
pass
def About(self):
print('print GUIBASECLASS V0.1')
if __name__ == '__main__':
root=tk.Tk()
bapp = GuiBaseClass(root)
# example for using the BaseClass in other applications
mnu=bapp.getMenu('Edit')
mnu.add_command(label='Copy',command=lambda: print('Copy'))
# example for using getFrame
frm=bapp.getFrame()
btn=ttk.Button(frm,text="Button X",command=lambda: sys.exit(0))
btn.pack()
bapp.mainLoop()
#!/usr/bin/python3
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog
from tkinter import messagebox
from GuiBaseClass import GuiBaseClass
import os , sys
class PumlEditor(GuiBaseClass):
def __init__(self, root):
super().__init__(root)
# Create the File menu and add a "Open..." option
mnu_file = self.getMenu('File')
mnu_file.add_command(0, label='Open...', underline=0, command=self.fileOpen)
mnu_file.add_separator()
# Create the main text area
frame = self.getFrame()
#insert tk.Text
self.text = tk.Text(frame, wrap='word', undo=True)
self.text.insert('end', 'Hello start writing, please...')
self.text.delete('1.0','end')
self.text.pack(fill='both', expand=True)
def fileOpen(self, filename=''):
# Open a file dialog to select a file to open
if filename == "":
filename = filedialog.askopenfilename()
if filename != "":
self.text.delete('1.0','end')
file = open(filename,'r')
for line in file:
self.text.insert('end',line)
if __name__ == '__main__':
root = tk.Tk()
root.geometry("300x200")
pedit = PumlEditor(root)
# Create the PumlEditor instance and start the main loop
root.title("PumlEditor 2022")
if len(sys.argv)>1:
if os.path.exits(sys.arg[1]):
pedit.fileOpen(sys.argv[1])
pedit.mainLoop()
Open to appear before exit in files widget
I have a project in Pyhton with some windows/form on Win11, but when I try to link a window with another one, they overlap. I want to show a window one at a time, but I don't see anything in the code to achieve this behaviour.
The forms were created with VB6 and then transformed into python code through TKinter Designer complement.
I have tried to close the parent window afte the call of the child one but with no results
Here is an example of the code:
Window 'Configuration':
import os, sys
if sys.version_info[0] == 2:
from Tkinter import *
from tkFont import Font
from ttk import *
#Usage:showinfo/warning/error,askquestion/okcancel/yesno/retrycancel
from tkMessageBox import *
#Usage:f=tkFileDialog.askopenfilename(initialdir='E:/Python')
#import tkFileDialog
#import tkSimpleDialog
else: #Python 3.x
from tkinter import *
from tkinter.font import Font
from tkinter.ttk import *
from tkinter.messagebox import *
#import tkinter.filedialog as tkFileDialog
#import tkinter.simpledialog as tkSimpleDialog #askstring()
import ConfGeneral, ConfCorte, ConfMedidasCorte
class Application_ui(Frame):
#The class will create all widgets for UI.
def __init__(self, master=None):
Frame.__init__(self, master)
self.master.title('Seleccione configuracion')
self.master.geometry('470x363')
self.createWidgets()
def createWidgets(self):
self.top = self.winfo_toplevel()
self.style = Style()
self.cmd_ConfGeneralVar = StringVar(value='General')
self.style.configure('Tcmd_ConfGeneral.TButton', font=('MS Sans Serif',18,'bold'))
self.cmd_ConfGeneral = Button(self.top, text='General', textvariable=self.cmd_ConfGeneralVar, command=self.cmd_ConfGeneral_Cmd, style='Tcmd_ConfGeneral.TButton')
self.cmd_ConfGeneral.setText = lambda x: self.cmd_ConfGeneralVar.set(x)
self.cmd_ConfGeneral.text = lambda : self.cmd_ConfGeneralVar.get()
self.cmd_ConfGeneral.place(relx=0.085, rely=0.11, relwidth=0.309, relheight=0.311)
self.cmd_ConfTiposCorteVar = StringVar(value='Tipos de Corte')
self.style.configure('Tcmd_ConfTiposCorte.TButton', font=('MS Sans Serif',18,'bold'))
self.cmd_ConfTiposCorte = Button(self.top, text='Tipos de Corte', textvariable=self.cmd_ConfTiposCorteVar, command=self.cmd_ConfTiposCorte_Cmd, style='Tcmd_ConfTiposCorte.TButton')
self.cmd_ConfTiposCorte.setText = lambda x: self.cmd_ConfTiposCorteVar.set(x)
self.cmd_ConfTiposCorte.text = lambda : self.cmd_ConfTiposCorteVar.get()
self.cmd_ConfTiposCorte.place(relx=0.579, rely=0.11, relwidth=0.309, relheight=0.311)
self.cmd_MedidasCorteVar = StringVar(value='Medidas de Corte')
self.style.configure('Tcmd_MedidasCorte.TButton', font=('MS Sans Serif',18,'bold'))
self.cmd_MedidasCorte = Button(self.top, text='Medidas de Corte', textvariable=self.cmd_MedidasCorteVar, command=self.cmd_MedidasCorte_Cmd, style='Tcmd_MedidasCorte.TButton')
self.cmd_MedidasCorte.setText = lambda x: self.cmd_MedidasCorteVar.set(x)
self.cmd_MedidasCorte.text = lambda : self.cmd_MedidasCorteVar.get()
self.cmd_MedidasCorte.place(relx=0.323, rely=0.573, relwidth=0.309, relheight=0.311)
class Application(Application_ui):
#The class will implement callback function for events and your logical code.
def __init__(self, master=None):
Application_ui.__init__(self, master)
def cmd_ConfGeneral_Cmd(self, event=None):
ConfGeneral.Application()
def cmd_ConfTiposCorte_Cmd(self, event=None):
ConfCorte.Application()
def cmd_MedidasCorte_Cmd(self, event=None):
ConfMedidasCorte.Application()
if __name__ == "__main__":
top = Tk()
Application(top).mainloop()
Window 'General Configuration'
import os, sys
myDir = os.getcwd()
sys.path.append(myDir)
from pathlib import Path
path = Path(myDir)
a=str(path.parent.absolute())
sys.path.append(a)
import src.Controlador.Transacciones as Transacciones
import Configuraciones as Configuraciones
if sys.version_info[0] == 2:
from Tkinter import *
from tkFont import Font
from ttk import *
#Usage:showinfo/warning/error,askquestion/okcancel/yesno/retrycancel
from tkMessageBox import *
#Usage:f=tkFileDialog.askopenfilename(initialdir='E:/Python')
#import tkFileDialog
#import tkSimpleDialog
else: #Python 3.x
from tkinter import *
from tkinter.font import Font
from tkinter.ttk import *
from tkinter.messagebox import *
#import tkinter.filedialog as tkFileDialog
#import tkinter.simpledialog as tkSimpleDialog #askstring()
class Application_ui(Frame):
#The class will create all widgets for UI.
def __init__(self, master=None):
Frame.__init__(self, master)
self.master.title('Configuración General')
self.master.geometry('402x311')
self.createWidgets()
def createWidgets(self):
self.top = self.winfo_toplevel()
self.style = Style()
self.cmd_RegresarVar = StringVar(value='Regresar')
self.style.configure('Tcmd_Regresar.TButton', font=('MS Sans Serif',14))
self.cmd_Regresar = Button(self.top, text='Regresar', textvariable=self.cmd_RegresarVar, command=self.cmd_Regresar_Cmd, style='Tcmd_Regresar.TButton')
self.cmd_Regresar.setText = lambda x: self.cmd_RegresarVar.set(x)
self.cmd_Regresar.text = lambda : self.cmd_RegresarVar.get()
self.cmd_Regresar.place(relx=0.597, rely=0.643, relwidth=0.301, relheight=0.209)
self.cmd_GuardarVar = StringVar(value='Guardar')
self.style.configure('Tcmd_Guardar.TButton', font=('MS Sans Serif',14))
self.cmd_Guardar = Button(self.top, text='Guardar', textvariable=self.cmd_GuardarVar, command=self.cmd_Guardar_Cmd, style='Tcmd_Guardar.TButton')
self.cmd_Guardar.setText = lambda x: self.cmd_GuardarVar.set(x)
self.cmd_Guardar.text = lambda : self.cmd_GuardarVar.get()
self.cmd_Guardar.place(relx=0.08, rely=0.643, relwidth=0.301, relheight=0.209)
self.txt_EmailAdminVar = StringVar(value='')
self.txt_EmailAdmin = Entry(self.top, textvariable=self.txt_EmailAdminVar, font=('MS Sans Serif',12))
self.txt_EmailAdmin.setText = lambda x: self.txt_EmailAdminVar.set(x)
self.txt_EmailAdmin.text = lambda : self.txt_EmailAdminVar.get()
self.txt_EmailAdmin.place(relx=0.517, rely=0.437, relwidth=0.42, relheight=0.08)
self.txt_NombreAdminVar = StringVar(value='')
self.txt_NombreAdmin = Entry(self.top, textvariable=self.txt_NombreAdminVar, font=('MS Sans Serif',12))
self.txt_NombreAdmin.setText = lambda x: self.txt_NombreAdminVar.set(x)
self.txt_NombreAdmin.text = lambda : self.txt_NombreAdminVar.get()
self.txt_NombreAdmin.place(relx=0.517, rely=0.283, relwidth=0.42, relheight=0.08)
self.lbl_EmailAdminVar = StringVar(value='Correo electrónico:')
self.style.configure('Tlbl_EmailAdmin.TLabel', anchor='w', font=('MS Sans Serif',12))
self.lbl_EmailAdmin = Label(self.top, text='Correo electrónico:', textvariable=self.lbl_EmailAdminVar, style='Tlbl_EmailAdmin.TLabel')
self.lbl_EmailAdmin.setText = lambda x: self.lbl_EmailAdminVar.set(x)
self.lbl_EmailAdmin.text = lambda : self.lbl_EmailAdminVar.get()
self.lbl_EmailAdmin.place(relx=0.06, rely=0.444, relwidth=0.42, relheight=0.068)
self.lbl_NombreAdminVar = StringVar(value='Nombre administrador:')
self.style.configure('Tlbl_NombreAdmin.TLabel', anchor='w', font=('MS Sans Serif',12))
self.lbl_NombreAdmin = Label(self.top, text='Nombre administrador:', textvariable=self.lbl_NombreAdminVar, style='Tlbl_NombreAdmin.TLabel')
self.lbl_NombreAdmin.setText = lambda x: self.lbl_NombreAdminVar.set(x)
self.lbl_NombreAdmin.text = lambda : self.lbl_NombreAdminVar.get()
self.lbl_NombreAdmin.place(relx=0.06, rely=0.289, relwidth=0.42, relheight=0.068)
self.lbl_TituloVar = StringVar(value='Configuración General')
self.style.configure('Tlbl_Titulo.TLabel', anchor='w', font=('MS Sans Serif',18,'bold'))
self.lbl_Titulo = Label(self.top, text='Configuración General', textvariable=self.lbl_TituloVar, style='Tlbl_Titulo.TLabel')
self.lbl_Titulo.setText = lambda x: self.lbl_TituloVar.set(x)
self.lbl_Titulo.text = lambda : self.lbl_TituloVar.get()
self.lbl_Titulo.place(relx=0.04, rely=0.051, relwidth=0.719, relheight=0.132)
self.codigoAdmin = 0
class Application(Application_ui):
#The class will implement callback function for events and your logical code.
def __init__(self, master=None):
Application_ui.__init__(self, master)
self.BuscarConfBD(self)
def cmd_Regresar_Cmd(self, event=None):
Configuraciones.Application()
def cmd_Guardar_Cmd(self, event=None):
Transacciones.GuardarConfGeneral(self.txt_NombreAdminVar.get(), self.txt_EmailAdminVar.get(), self.codigoAdmin)
self.BuscarConfBD(self)
def BuscarConfBD(self, event=None):
registro = Transacciones.BuscarConfGeneral()
for dato in registro:
self.codigoAdmin = dato[0]
self.txt_NombreAdminVar.set(dato[1])
self.txt_EmailAdminVar.set(dato[2])
if __name__ == "__main__":
top = Tk()
Application(top).mainloop()
I want to show the plot canvas in the top right side of UI (using Tkinter python3). I wrote the following code but I got the following error:
canvas = FigureCanvasTkAgg(fig, master=root) NameError: name 'root' is not defined
My code is:
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import sys
class GUI(tk.Frame):
def __init__(self, master = None):
self.root = tk.Tk()
self.root.geometry("500x500")
tk.Frame.__init__(self, master)
self.createWidgets()
def start(self):
self.root.mainloop()
def createWidgets(self):
fig = plt.figure(figsize=(8, 8))
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().grid(row=0, column=1)
canvas.show()
def main():
appstart = GUI()
appstart.start()
if __name__ == "__main__":
main()
I made some changes to your code, deleting some unnecessary
references such as:
import tkinter.ttk as ttk
from tkinter import *
from matplotlib.figure import Figure
import sys
self.root = tk.Tk()
tk.Frame.__init__(self, master)
that you dont' use and I think only confuse yourself.
I've even simplified your script and add this code below to show to you wath is "self"
print(type(self))
for item in dir(self):
print(type(item),item)
I've add even a toolbar to the plot and some data to plot something.
Regards
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import numpy as np
class GUI(tk.Tk):
def __init__(self):
super().__init__()
self.title("Hello World")
self.geometry("500x500")
self.createWidgets()
print(type(self))
for item in dir(self):
print(type(item),item)
def createWidgets(self):
t = np.arange(0, 3, .01)
f0 = tk.Frame()
fig = plt.figure(figsize=(8, 8))
fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))
canvas = FigureCanvasTkAgg(fig, f0)
toolbar = NavigationToolbar2Tk(canvas, f0)
toolbar.update()
canvas._tkcanvas.pack(fill=tk.BOTH, expand=1)
f0.pack(fill=tk.BOTH, expand=1)
def main():
appstart = GUI()
appstart.mainloop()
if __name__ == "__main__":
main()
In your code you should use self.root if your intent is to use the root window:
canvas = FigureCanvasTkAgg(fig, master=self.root)
... or maybe just self, if your intent is to have it appear inside the frame. I'm not entirely sure what you are intending to do
canvas = FigureCanvasTkAgg(fig, master=self)
Somewhat unrelated, if you're explicitly creating a root window, you should be passing that to tk.Frame.__init__ rather than master.
tk.Frame.__init__(self, self.root)
I am trying to plot in real-time to a tkinter window in python3.
I am attempting to wrap my window in a class.
my code shows the graph, but data is not being plotted. Here is the code:
#! /usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.animation as animation
import tkinter
import time
import numpy as np
matplotlib.use("TkAgg")
class Window(tkinter.Frame):
def __init__(self, master = None):
tkinter.Frame.__init__(self, master)
self.master = master
self.master.grid()
self.fig = Figure(figsize=(5,5), dpi=100)
self.ax = self.fig.add_subplot(111)
self.t, self.y = [], []
self.init_window()
self.ani = animation.FuncAnimation(self.fig, self.animate, interval=1000)
def init_window(self):
# set window title
self.master.title("PlotSomething")
# run show_graph
self.show_graph()
def animate(self):
self.t.append(time.time())
self.y.append(np.random.random())
self.ax.clear()
self.ax.plot(self.t,self.y)
def show_graph(self):
canvas = FigureCanvasTkAgg(self.fig, self.master)
canvas.get_tk_widget().grid(row=1, column=1)
canvas.draw()
def client_exit(self):
sys.exit()
def main(args):
root = tkinter.Tk()
app = Window(root)
root.mainloop()
return 0
if __name__=="__main__":
sys.exit(main(sys.argv[1:]))
Please let me know what the issue is.
Bonus if you can help me get the real-time plot stuff into a separate class that I can call with my tkinter window.
I obviously need some learning on how to create and call classes using tkinter.
As always thank you for your support!
I have a class GUI, where I set up all my widgets etc. for my GUI. I use threading to start a process from another class. This works fine, as long that other process just runs through. In some cases, I need to wait for a user input to proceed. I used tkmessagebox for this, but the messagebox doesn't appear and blocks the GUI without any error message. (It works when not started through the GUI).
Here's part of my code:
GUI part
from Tkinter import *
import Tkinter as ttk
import ttk
from tkMessageBox import *
from GUI_reader import Commandline_Reader
import threading
import Queue
class GUI:
def __init__(self,master):
self.master = master
self.argString='ds'
## self.workerThread()
button = ttk.Button(text='start', command=self.go).grid()
...
def go(self):
self.thread = threading.Thread(target=self.workerThread)
self.thread.daemon = True
self.thread.start()
...
def workerThread(self):
...
reader = Commandline_Reader(master, self.argString)
if reader.connect():
print 'success'
reader.run()
print 'success'
if __name__ == '__main__':
root = Tk()
client = GUI(root)
root.mainloop()
class commandline_reader:
import tkMessageBox
...
class Commandline_Reader:
def __init__(self, master, argString='')
self.master = master
...
def connect(self)
...
def run(self):
...
tkMessageBox.askokcancel('Calibration', 'Hit ok to start calibration', parent= self.master)
...
if __name__ == '__main__':
reader = Commandline_Reader(self,master)
if not reader.connect():
exit(-1)
if not reader.run():
exit(-2)