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.
Related
Please I am trying to create a UI but I coulld get the main window up and running. I want the left and right paned window to have defined width and the middle should cover remaining width. this is working for the left pane but it is not working for right pane. below is the code and the output. I am just learning tkinter and everything I read from the documentation does not work for me. PLease Is there anyone who could help.
`
import customtkinter
from tkinter import *
import tkinter.messagebox
customtkinter.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light"
customtkinter.set_default_color_theme("dark-blue") # Themes: "blue" (standard), "green", "dark-blue"
def addPage():
pass
def copyText():
pass
class App(customtkinter.CTk):
width = 1440
height = 1024
def __init__(self):
super().__init__()
self.geometry(f"{App.width}x{App.height}")
self.radio_var = tkinter.IntVar(value=0)
###Menus
self.myMenu = Menu(self)
self.config(menu=self.myMenu)
# File Menu
self.fileMenu = Menu(self.myMenu)
self.myMenu.add_cascade(label="File", menu=self.fileMenu)
self.fileMenu.add_command(label="add...", command=addPage)
# Edit Menu
self.editMenu = Menu(self.myMenu)
self.myMenu.add_cascade(label="Edit", menu=self.editMenu)
self.editMenu.add_command(label="Copy", command=copyText)
# define Frames
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
self.frameBody = customtkinter.CTkFrame(master=self)
self.frameBody.grid(row=0, column=0, sticky="nswe")
self.frameFooter = customtkinter.CTkFrame(master=self, height=25, fg_color="#a6a6a6", corner_radius=0)
self.frameFooter.grid(row=1, column=0, sticky="nswe")
# main panel body
self.paneBody = PanedWindow(self.frameBody)
self.paneBody.pack(fill="both", expand=True)
#other three panes
self.paneLeftBody = PanedWindow(self.paneBody, bg = 'red', width = 300)
self.paneBody.add(self.paneLeftBody)
self.paneMiddleBody = PanedWindow(self.paneBody,orient = 'vertical')
self.paneBody.add(self.paneMiddleBody)
self.paneRightBody = PanedWindow(self.paneBody, bg = 'black', width = 300)
self.paneBody.add(self.paneRightBody)
self.middleTopPane = customtkinter.CTkFrame(self.paneMiddleBody, fg_color='red')
self.paneMiddleBody.add(self.middleTopPane,sticky="nswe")
self.middleBottomPane = customtkinter.CTkFrame(self.paneMiddleBody, height=300)
self.paneMiddleBody.add(self.middleBottomPane)
if __name__ == "__main__":
app = App()
app.mainloop()
`
Output
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)
I want to build an app where you can change the background image by clicking a button. First, to put a background to my frame, I created the image as a label and then sub-classed every other label to the background label. Now when you click the button "Change Background", it changes the background. However, all the labels disappear. Buttons only appear when you hover over them by the cursor. Labels never appear!
My questions are:
Why does this happen?
How to fix it?
Here is a simple code to reproduce the issue:
import tkinter as tk
from PIL import ImageTk, Image
class App():
def __init__(self, root):
self.root = root
self.controlFrame = tk.Frame(root, width=900, height=600)
self.controlFrame.pack_propagate(0) # Prevents resizing
self.controlFrame.pack()
img = Image.open('images/outside.jpg').resize((900, 600))
self.background_image = ImageTk.PhotoImage(img)
self.background_label = tk.Label(self.controlFrame, image=self.background_image)
self.background_label.configure(image = self.background_image)
self.background_label.pack(fill="both", expand="yes")
self.changeButton = tk.Button(self.background_label, text="Change Background",
command = self.changeBK)
self.changeButton.place(x=400, y=300)
self.someButton = tk.Button(self.background_label, text="Some Button")
self.someButton.place(x=400, y=100)
self.someOtherButton = tk.Button(self.background_label, text="Some Other Button")
self.someOtherButton.place(x=400, y=450)
self.userMessage = tk.Label(self.background_label, text="Label", height = 3 , width= 14, bg="white")
self.userMessage.place(x=400, y= 200)
def changeBK(self):
img = Image.open('images/muddyPath.jpg').resize((900, 600))
self.background_image = ImageTk.PhotoImage(img)
self.background_label.configure(image = self.background_image)
def main():
win = tk.Tk() # Create a window
win.title("Using Multiple Layouts") # Set window title
win.geometry("900x600") # Set window size
win.resizable(False, False) # Both x and y dimensions ...
# Create the GUI as a Frame
# and attach it to the window ...
myApp = App(win)
# Call the GUI mainloop ...
win.mainloop()
if __name__ == "__main__":
main()
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.
Here is my program as of yet:
from tkinter import *
from collections import deque
class App():
def __init__(self, *images):
self.root = Tk()
self.root.title("Skin")
self.image_dict = {image: PhotoImage(file=image) for image in images}
self.image_queue = deque(images)
b = Button(self.root, text="Click here to see the diagram!", command=self.change_image)
b.pack(fill=X)
self.label = Label(self.root, image=self.image_dict["1.gif"])
self.label.image = self.image_dict["1.gif"]
self.label.pack()
def change_image(self):
self.image_queue.rotate(-1)
next_image = self.image_queue[0]
self.label.configure(image=self.image_dict[next_image])
self.label.image = self.image_dict[next_image]
if __name__ == "__main__":
app = App('1.gif', '2.gif')
app.root.mainloop()
What this does is when you run the scipt, a window comes up diplaying "1.gif", and a button. When you click the button, "1.gif" changes to "2.gif". "1.gif" is a blank diagram, "2.gif" is a diagram with labels showing what each part of the diagram is.
Now for the next stage of my program, I need some way to add multiple invisible buttons, or something like it, over each word on the diagram on "2.gif", and when you click on it, I need a seperate window to come up with text on it. Is there any way to implement that into my current program? I have no idea where to start. Thank you!
I think you will be better off using a Canvas to hold your image(s) rather
than a Label. You can then place 'hotspots' over the diagram and bind
events to them. eg. something like:
from tkinter import *
class App():
def __init__(self):
self.root = Tk()
self.messages = {}
self.canvas = Canvas(self.root, bd=0, highlightthickness=0)
self.image = PhotoImage(file='2.gif')
self.canvas.create_image(0,0, image=self.image, anchor='nw')
w,h = self.image.width(), self.image.height()
self.canvas.config(width=w, height=h)
self.canvas.pack()
self.balloon = b = Toplevel(self.root)
b.withdraw()
b.wm_overrideredirect(1)
self.msg = Label(b, bg='black', fg='yellow', bd=2, text='')
self.msg.pack()
self.set_up_hotspots()
def set_up_hotspots(self):
box1 = self.canvas.create_polygon(50,100,100,100,100,150,50,150,
outline='blue', fill='')
#note: outline can be '' also ;)
self.messages[box1] = "The machine head consists of a "\
"Flynn mechanism,\na Demmel crank, "\
"and a heavy-duty frobulator. "
box2 = self.canvas.create_polygon(150,100,200,100,200,150,150,150,
outline='red', fill='')
self.messages[box2] = "And now for something completely different"
for item in [box1, box2]:
for event, handler in [('<Enter>', self.on_hotspot_enter),
('<Leave>', self.on_hotspot_leave)]:
self.canvas.tag_bind(item, event, handler)
def on_hotspot_enter(self, event):
if not self.balloon.winfo_ismapped():
txt = self.messages[event.widget.find_withtag('current')[0]]
self.msg.config(text=txt)
x,y = event.x_root, event.y_root
self.balloon.geometry('+%d+%d' %(x+16,y))
self.balloon.deiconify()
def on_hotspot_leave(self, event):
if self.balloon.winfo_ismapped():
self.balloon.withdraw()
if __name__ == "__main__":
app = App()
app.root.mainloop()