Tktinter Menu with functionality in separate file - python

It's my first time trying tkinter.
I'm trying to make a menu with the command section in another file.
However it seems to run the command immediately as I open the program and doesn't wait till I click the menu button.
following is the code for my main:
import data
import loginPage
import menuFunc
from tkinter import *
import tkinter as tk
class main(Tk):
def __init__(self):
super().__init__()
self.geometry("1000x700") #size of the window
self.resizable(False,False) #dont let the user resize (might mess up layout of GUI)
def Menu(self):
myMenu = Menu(self)
self.config(menu=myMenu)
#Create a menu items
optionMenu= Menu(myMenu)
myMenu.add_cascade(label="Options", menu=optionMenu)
optionMenu.add_command(label="Exit", command = self.destroy)
addMenu= Menu(myMenu)
myMenu.add_cascade(label="Add", menu=addMenu)
addMenu.add_command(label="New Book", command = menuFunc.addBook(self))
addMenu.add_command(label="New customer", command = menuFunc.addCustomer(self))
addMenu.add_command(label="New employee", command = menuFunc.addEmployee(self))
def Label(self):
self.backGroundImage = PhotoImage(file = "Background.png") #photoimage for background
self.backGroundImageLabel = Label(self, image = self.backGroundImage) #import the image as a label
self.backGroundImageLabel.place(x=0, y=0) #placement
# self.canvas = Canvas(self, width=550,height = 400) #show a canvas in front of background
#self.canvas.place(x=75, y=70)
if __name__=="__main__":
Main = main()
Main.Label()
Main.Menu()
#Login.Entry()
#Login.Button()
Main.mainloop()
This is my code in the other file menuFunc.py
from tkinter import *
import tkinter as tk
global addBookFrame
def addBook(window):
addBookFrame = Frame(window, bg = "red")
addBookFrame.pack(fill="both",expand = 1)
def addCustomer(window):
addCustomerFrame = Frame(window, bg = "blue")
addCustomerFrame.pack(fill="both",expand = 1)
def addEmployee(window):
addEmployeeFrame = Frame(window, bg = "yellow")
addEmployeeFrame.pack(fill="both",expand = 1)
def hideFrames(frame):
for widget in frame.winfo_children():
widget.destroy()
I get the following result:
enter image description here
How can I make it so that the function only runs when I press the appropriate menu button?

Put:
command = menuFunc.addBook
command = menuFunc.addCustomer
command = menuFunc.addEmployee
In place of:
command = menuFunc.addBook(self)
command = menuFunc.addCustomer(self)
command = menuFunc.addEmployee(self)

Related

Can't use .withdraw() from Tkinter

So I am doing my first programming class this semester and for our exam I am creating this very basic Lightroom clone.
I am using opencv for the image processing and Tkinter as GUI. Everything kind of works so far, but I am struggling to hide the main menu (Tkinter GUI) when the image is opened (OpenCV GUI).
I want to call the .withdraw method for the TKinter root window from the innit function of the image processing class. Image opens -> Menu hides. I think these pictures might help:
Here the GUI initializes
from tkinter import *
import Panels
def createpanels(amount=10):
img1 = "thumbnail.jpg"
for i in range(0, amount):
Panel = (Panels.Panel("Image A", img1, i + 1, 5))
button_edit = Button(window, text="Bild Bearbeiten", command=Panel.showpath)
button_edit.grid(column=i + 1, row=6, pady = 10)
def hidegui():
window.withdraw()
def showgui():
window.deiconify()
if __name__ == "__main__":
window = Tk()
window.title("File Explorer")
window.config(background="white")
current_value = tk.DoubleVar()
createpanels()
button_exit = Button(window, text = "Exit", command = exit)
button_exit.grid(column=11, row=5, padx=10, pady=10)
window.mainloop()
Here I am trying to call the withdraw method
from tkinter import *
from tkinter import messagebox
import TkinterGUI as gui
import Filter
import Goldencut as g
from PIL import Image
import Filter as f
class Image:
counter = 0
def __init__(self, path):
self.path = path
self.img = cv.imread(self.path)
self.imgcopy = self.img.copy()
self.gc = self.img.copy()
cv.namedWindow("Image", cv.WINDOW_NORMAL)
cv.namedWindow("Controlls", cv.WINDOW_NORMAL)
gui.hidegui()
Unfortunately this is not working and I get this error message:
Error
I am pretty sure this is an absolute beginner mistake and easy to fix, but I just can't fix it myself. Any help very appreciated :)
window = Tk() use outside of function like this
here is the complete code because you are calling an undefined class name
from tkinter import *
import Panels
window = Tk() # use here
def createpanels(amount=10):
img1 = "thumbnail.jpg"
for i in range(0, amount):
Panel = (Panels.Panel("Image A", img1, i + 1, 5))
button_edit = Button(window, text="Bild Bearbeiten", command=Panel.showpath)
button_edit.grid(column=i + 1, row=6, pady = 10)
def hidegui():
window.withdraw()
def showgui():
window.deiconify()
if __name__ == "__main__":
window.title("File Explorer")
window.config(background="white")
current_value = tk.DoubleVar()
createpanels()
button_exit = Button(window, text = "Exit", command = exit)
button_exit.grid(column=11, row=5, padx=10, pady=10)
window.mainloop()

How to delete popup window in tkinter?

I have a sequence of pop up windows. I intended to close the window once i have completed the desired task. I am using a "askokcancel" button to get users confirmation whether the activity has completed. The problem is, every time the user presses ok, the focus goes back to the main starting window and rest of the pop up windows goes to the background while staying active. I want to either close the pop up windows or keep the focus to the second last window. Below is my code:
import tkinter as tk
from tkinter import ttk, StringVar, messagebox
from tkinter.filedialog import askopenfilename
from mytest import *
from tkinter import *
class myclass:
def __init__(self, master):
self.master = master
self.frame1 = tk.Frame(self.master)
self.button1 = tk.Button(self.frame1, text = 'select me first', width = 25, command = self.buttonFunc)
self.button1.pack()
self.quitButton = tk.Button(self.frame1, text = 'Quit', width = 25, command = self.close_windows1)
self.quitButton.pack()
self.frame1.pack()
self.master.geometry("200x200+60+60")
def buttonFunc(self):
self.top = tk.Toplevel(self.master)
self.button2 = tk.Button(self.top,text="Select second",command=self.anotherButtonFunc)
self.button2.pack()
self.quitButton = tk.Button(self.top, text = 'Quit', width = 25, command = self.close_windows2)
self.quitButton.pack()
self.master.geometry("200x200+60+60")
def anotherButtonFunc(self):
self.top2 = tk.Toplevel(self.top)
self.newClass = myClassExt(self.top2)
def close_windows1(self):
self.master.destroy()
def close_windows2(self):
self.top.destroy()
class myClassExt():
def __init__(self, top2):
self.top3 = top2
self.frame2 = tk.Frame(self.top3)
self.button3 = tk.Button(self.frame2, text = 'select me third', width = 25, command = self.buttonFunc)
self.button3.pack()
self.quitButton = tk.Button(self.frame2, text = 'Quit', width = 25, command = self.close_windows4)
self.quitButton.pack()
self.frame2.pack()
self.top3.geometry("200x200+60+60")
def buttonFunc(self):
ok = messagebox.askokcancel(message='Press OK to Confirm?')
if not ok:
pass
else:
messagebox.showinfo("Success","Well done")
self.close_windows4()
def close_windows4(self):
self.top3.destroy()
if __name__ == "__main__":
root = tk.Tk()
myclass = myclass(root)
root.mainloop()
From this made up example, i somehow want to either close window number 2 after user presses OK or keep the focus on window 2 rather than window 1. Please guide
There is no way to close a message box, although you can easily make your own. You just have to make a new tkinter window, and set an image, title, and text, then add a close button, and return the tk window. I made a function like this myself, for this very reason. Here is the function:
def mymessage(title, text, spacing = 25, buttonText = "Close", image = None):
tk2 = Tk()
tk2.resizable(0, 0)
tk2.title(title)
if image != None:
image = Label(tk2, image = PhotoImage(file = image))
image.pack()
spacer = Frame(tk2, relief = FLAT, bd = 0, width = 200, height = 25)
spacer.pack()
label = Label(tk2, text = text)
label.pack()
button = Button(tk2, text = buttonText, width = 5, height = 1, command = tk2.destroy)
button.pack()
return tk2
After calling the function, it returns the tk window, for easy destruction.

Tkinter Canvas: Itemconfig failed update color

I've to change the color of the rectangle created with the Canvas item.
I've looked at other questions but I didn't find an answer to my problem.
I am recording a microphone using a USB Sound card. Once the record is started I want to put a RED light and, once it is finished, back it to green.
Here's the code:
main.py:
import tkinter as tk
from GUI import Demo1
def main():
root = tk.Tk()
app = Demo1(root)
root.mainloop()
if __name__ == '__main__':
main()
GUI.py:
class Demo1:
def __init__(self, master):
#Set geometry and title
self.master = master
self.master.title("DAQ - Sound Pressure Level")
self.master.geometry("480x320")
# Canvas zone
self.canvas = tk.Canvas(self.master,width=40,height=20,background='white')
self.canvas.grid(row=0,column=3)
self.frame = Frame(self.master)
self.frame.grid(row=0,column=3)
self.rect1 = self.canvas.create_rectangle(0,0,40,20, fill="green")
#canvas.bind(func=changecolor(canvas))
#set buttons
self.quitbutton = tk.Button(self.master, text = 'Quit', width = 10, command = self.close_windows)
self.quitbutton.grid(column=1,row=0)
self.startbutton = tk.Button(self.master, text = 'Start', width = 10, command = lambda: self.startacquisition())
self.startbutton.grid(column=0,row=0)
#self.zerobutton = tk.Button(self.master,text = 'Zero', width = 10, command = lambda: self.zerocalibration())
#self.zerobutton.grid(column=2,row=0)
#self.livebutton = tk.Button(self.master,text="Live/Stop", command=lambda: self.gui_handler, bg="red", fg="white")
#self.livebutton.grid(column=2,row=0)
def startacquisition(self):
chunk = 8192 # Record in chunks
print("Changing rect color to red")
self.canvas.itemconfig(self.rect1,fill='red')
p = pyaudio.PyAudio() # Create an interface to PortAudio
[....recording stuff...]
[...preparing plot...]
plt.show()
self.canvas.itemconfig(self.rect1,fill='green')
So when I press the START button it calls startacquisition(self) function. What happend is that the color doesn't upgrade until I close all the plot.
Why?
Thanks for your help.

Image in tkinter window by clicking on button

I need help about this program, this program should open image in new tkinter window by clicking on button, but it doesn't it just opens new window without image.
Where is the problem?
Using: python 3.3 and tkinter
This is program:
import sys
from tkinter import *
def button1():
novi = Toplevel()
canvas = Canvas(novi, width = 300, height = 200)
canvas.pack(expand = YES, fill = BOTH)
gif1 = PhotoImage(file = 'image.gif')
canvas.create_image(50, 10, visual = gif1, anchor = NW)
mGui = Tk()
button1 = Button(mGui,text ='Sklop',command = button1, height=5, width=20).pack()
mGui.mainloop()
create_image needs a image argument, not visual to use the image, so instead of visual = gif1, you need image = gif1. The next problem is that you need to store the gif1 reference somewhere or else it'll get garbage collected and tkinter won't be able to use it anymore.
So something like this:
import sys
from tkinter import * #or Tkinter if you're on Python2.7
def button1():
novi = Toplevel()
canvas = Canvas(novi, width = 300, height = 200)
canvas.pack(expand = YES, fill = BOTH)
gif1 = PhotoImage(file = 'image.gif')
#image not visual
canvas.create_image(50, 10, image = gif1, anchor = NW)
#assigned the gif1 to the canvas object
canvas.gif1 = gif1
mGui = Tk()
button1 = Button(mGui,text ='Sklop',command = button1, height=5, width=20).pack()
mGui.mainloop()
It's also probably not a good idea to name your Button the same name as the function button1, that'll just cause confusion later on.
from tkinter import *
root = Tk()
root.title("Creater window")
def Img():
r = Toplevel()
r.title("My image")
canvas = Canvas(r, height=600, width=600)
canvas.pack()
my_image = PhotoImage(file='C:\\Python34\\Lib\idlelib\\Icons\\Baba.gif', master= root)
canvas.create_image(0, 0, anchor=NW, image=my_image)
r.mainloop()
btn = Button(root, text = "Click Here to see creator Image", command = Img)
btn.grid(row = 0, column = 0)
root.mainloop()

How to add a scrollbar to a window with tkinter?

I have a tkinter program:
import urllib.request
from tkinter import *
root = Tk()
root.iconbitmap(default='icon.ico')
root.wm_title('Got Skills\' Skill Tracker')
frame = Frame(width="500",height="500")
frame.pack()
def show():
name = "zezima"
page = urllib.request.urlopen('http://hiscore.runescape.com/index_lite.ws?player=' + name)
page = page.readlines()
skills = []
for line in page:
skills.append([line.decode("utf-8").replace("\n", "").split(",")])
skills = skills[0:25]
for item in skills:
toPrint = item[0][0],"-",item[0][1],"-",item[0][1],"\n"
w = Message(frame, text=toPrint)
w.pack()
menu = Menu(root)
root.config(menu=menu)
filemenu = Menu(menu)
menu.add_cascade(label="Commands", menu=filemenu)
filemenu.add_command(label="Show Skills", command=show)
root.mainloop()
When I run the above script, it shows this (which is good):
alt text http://img708.imageshack.us/img708/8821/tkinter1.png
When I click Commands > Show Skills, it turns into this. (Linked because it's tall.) It shows the right thing, but...I can imagine you see the problem.
Two questions:
-How do I add a scrollbar to the frame, and keep the frame a fixed size? (Ideally, keep the size of the first image, add the output of show(), add a scrollbar to the first image of the program.)
-With the following code:
for item in skills:
toPrint = item[0][0],"-",item[0][1],"-",item[0][2],"\n"
w = Message(frame, text=toPrint)
w.pack()
Is that the best way to output what I'm outputting? The list (skills) looks like [[1,2,3],[4,5,6]..], and I want to display 1-2-3 on a line, 4 - 5 - 6 on a line, etc.
But, I don't want that extra line in between them like there is now, and I was wondering if how I did it is the best way to go about doing it.
To add the scroll bars, use tkinter.tix.ScrolledWindow.
To remove extra space drop the extra "\n" and display a string, not a tuple. Here is the complete code:
import urllib.request
from tkinter import *
from tkinter.tix import *
root = Tk()
root.iconbitmap(default='icon.ico')
root.wm_title('Got Skills\' Skill Tracker')
frame = Frame(width="500",height="500")
frame.pack()
swin = ScrolledWindow(frame, width=500, height=500)
swin.pack()
win = swin.window
def show():
name = "zezima"
page = urllib.request.urlopen('http://hiscore.runescape.com/index_lite.ws?player=' + name)
page = page.readlines()
skills = []
for line in page:
skills.append([line.decode("utf-8").replace("\n", "").split(",")])
skills = skills[0:25]
for item in skills:
toPrint = item[0][0],"-",item[0][1],"-",item[0][1]
w = Message(win, text=' '.join(toPrint), width=500)
w.pack()
menu = Menu(root)
root.config(menu=menu)
filemenu = Menu(menu)
menu.add_cascade(label="Commands", menu=filemenu)
filemenu.add_command(label="Show Skills", command=show)
root.mainloop()
Here's a class for scrolling frames. Just pass the window object as traditional tkinter style and use obj.frame as window for new widgets.
class ScrollableFrame:
"""
# How to use class
from tkinter import *
obj = ScrollableFrame(master,height=300 # Total required height of canvas,width=400 # Total width of master)
objframe = obj.frame
# use objframe as the main window to make widget
"""
def __init__ (self,master,width,height,mousescroll=0):
self.mousescroll = mousescroll
self.master = master
self.height = height
self.width = width
self.main_frame = Frame(self.master)
self.main_frame.pack(fill=BOTH,expand=1)
self.scrollbar = Scrollbar(self.main_frame, orient=VERTICAL)
self.scrollbar.pack(side=RIGHT,fill=Y)
self.canvas = Canvas(self.main_frame,yscrollcommand=self.scrollbar.set)
self.canvas.pack(expand=True,fill=BOTH)
self.scrollbar.config(command=self.canvas.yview)
self.canvas.bind('<Configure>', lambda e: self.canvas.configure(scrollregion = self.canvas.bbox("all")))
self.frame = Frame(self.canvas,width=self.width,height=self.height)
self.frame.pack(expand=True,fill=BOTH)
self.canvas.create_window((0,0), window=self.frame, anchor="nw")
self.frame.bind("<Enter>", self.entered)
self.frame.bind("<Leave>", self.left)
def _on_mouse_wheel(self,event):
self.canvas.yview_scroll(-1 * int((event.delta / 120)), "units")
def entered(self,event):
if self.mousescroll:
self.canvas.bind_all("<MouseWheel>", self._on_mouse_wheel)
def left(self,event):
if self.mousescroll:
self.canvas.unbind_all("<MouseWheel>")

Categories