I have a large list of environments loaded into an OptionMenu. When you open it, it will immediately close once you let go of the mouse button if the opened menu reaches outside of the screen. Is there any way to deal with this? (for example making it smaller and scrollable or deactivating said function) I tested this on Linux20.04 in case it is different on windows. Or can someone mention a dropdown-menu that doesn't have that problem.
#!/usr/bin/env python3
from tkinter import *
class Dropdown:
def __init__(self,options, master):
self.variable = StringVar(master)
self.variable.set(options[0]) # default value
self.menue = OptionMenu(master, self.variable, *options)
self.menue.pack()
typ = [
"Giftpflanze",
"Übernatürliche Pflanze",
"Heilpflanze",
"Nutzpflanze",
"Wehrende Pflanze",
"physische Wirkung",
"psychische Wirkung"
]
# Rad Suchschwierigkeit
# Rad Bestimmschwierigkeit
master = Tk()
d1 = Dropdown(typ,master)
def ok():
print ("value is:" + d1.variable.get())
button = Button(master, text="OK", command=ok)
button.pack()
mainloop()
So you can try it out on your own (just make sure it actually would reach out of your screen).
Here is a video: https://imgur.com/5Suqtiq
Related
when I click the button it call's cpuTemp function and it has a after loop init which causes my not responding window and it is show values of cpu percent in my python console so the question is why it is not working
'''
from tkinter import *
import psutil
import statistics
window = Tk()
# window size
screen_width = window.winfo_screenwidth()
screen_height = window.winfo_screenheight()
# window
window.attributes('-transparentcolor', 'blue')
window.resizable(True, True)
window.attributes('-alpha', 0.96)
window.config(cursor='crosshair')
window.attributes('-topmost', 0)
window.geometry(f"{screen_width}x{screen_height}+20+20")
window.state('zoomed')
window.title('Hello Python')
# windTemp
def cpuTemp(event):
#gettin temps
cpuTemps = [psutil.cpu_percent(0.5), psutil.cpu_percent(0.5), psutil.cpu_percent(0.5),
psutil.cpu_percent(0.5), psutil.cpu_percent(0.5)]
meanVal = statistics.mean(cpuTemps)
print(meanVal)
lbl.configure(text=f'{meanVal}%')
window.after(1000 , cpuTemp(event))
#button
btn = Button(window, text="This is Button widget", fg='blue')
btn.place(x=80, y=100)
btn.bind('<Button-1>', cpuTemp)
#label
lbl = Label(window , text='hi' , fg = "#0009ff0fc")
lblPlace = [ screen_width/2 , screen_height/2]
lbl.place(x=f'{lblPlace[0]}', y=f'{lblPlace[1]}')
window.mainloop()
# temp
this is not working can anyone fix this for me I would appreciate that.
it stills print in my pycharm consloe so why is my window not responding.
i am using pycharm as you might know now.
and I want to make this code working .
i am a python newbie so pls help it would mean a lot to me...
window.after(1000 , cpuTemp(event)) immediately runs cpuTemp(event) and passes the result to window.after. This creates an infinite loop since each call results in another call to the function.
The code needs to look something like this:
window.after(1000, cpuTemp, None)
The reason for None is that the function doesn't use the event, and the current event is relatively useless except for when the original event is being processed.
from tkinter import *
from tkinter.ttk import *
root = Tk()
listbox = None
listboxMultiple = None
listboxStr = None
listboxMultipleStr = None
def main():
global root
global listboxStr
global listboxMultipleStr
global listbox
global listboxMultiple
root.protocol("WM_DELETE_WINDOW", exitApplication)
root.title("Title Name")
root.option_add('*tearOff', False) # don't allow tear-off menus
root.geometry('1600x300')
listboxStr = StringVar()
listboxStr.set("ABCD")
listbox = Listbox(root, name="lb1", listvariable=listboxStr, width=120)
listbox.pack(side=LEFT)
listbox.bind("<<ListboxSelect>>", selectListItemCallback)
listboxMultipleStr = StringVar()
listboxMultipleStr.set("")
listboxMultiple = Listbox(root, name="lb2", listvariable=listboxMultipleStr, width=120)
listboxMultiple.pack(side=LEFT)
root.mainloop()
def selectListItemCallback(event):
global listboxMultipleStr
global listbox
global listboxMultiple
print("event.widget is {} and listbox is {} and listboxMultiple is {}\n".format(event.widget, listbox, listboxMultiple))
selection = event.widget.curselection()
listboxMultipleStr.set("")
if selection:
index = selection[0]
data = event.widget.get(index)
newvalue = "{}\n{}".format(data,"SOMETHING")
print("selected \"{}\"\n".format( data ))
print("newvalue is \"{}\"\n".format( newvalue ))
listboxMultiple.insert(END, "{}".format(data))
listboxMultiple.insert(END, "SOMETHING")
#listboxMultipleStr.set( newvalue )
else:
pass
def exitApplication():
global root
root.destroy()
if __name__ == "__main__":
main()
Using python3 on Windows 7. I've setup a callback "selectListItemCallback" for one of my two listbox widgets. And yet, when I click on the text in "lb1" it works as expected, I update "lb2" with the same selected text plus I add another line to "lb2".
The issue is, when I then select the item in "lb2", it still calls the callback and the event.widget is "lb1" and not "lb2".
My intent is to have a list of items in 'lb1' and when I select any of them, then 'lb2' gets filled with info related to the selected 'lb1' item. And, I don't want a selection callback invoked in my 'lb2' widget.
Can you see what I'm doing wrong that could be causing this strange behavior?
Thank you.
I've posted the code; and this does run on my Windows 7 machine using python3. Python 3.8.6 to be exact.
It is because the event fires when the first list box loses the selection when you click on the other list box. The event fires whenever the selection changes, not just when it is set.
If you don't want the first listbox to lose its selection when you click in the second listbox, set exportselection to False for the listboxes. Otherwise, tkinter will only allow one to have a selection at a time.
Whatever I do to my checkbutton, it does not seem to set the variable.
Here's the parts of the code that are involved:
class Window:
def __init__(self):
self.manualb = 0 #to set the default value to 0
def setscreen(self):
#screen and other buttons and stuff set here but thats all working fine
manual = tkr.Checkbutton(master=self.root, variable=self.manualb, command=self.setMan, onvalue=0, offvalue=1) #tried with and without onvalue/offvalue, made no difference
manual.grid(row=1, column=6)
def setMan(self):
print(self.manualb)
#does some other unrelated stuff
It just keeps printing 0. Am I doing something wrong? Nothing else does anything to manual.
You're looking for IntVar()
IntVar() has a method called get() which will hold the value of the widget you assign it to.
In this particular instance, it will be either 1 or 0 (On or off).
You can use it something like this:
from tkinter import Button, Entry, Tk, Checkbutton, IntVar
class GUI:
def __init__(self):
self.root = Tk()
# The variable that will hold the value of the checkbox's state
self.value = IntVar()
self.checkbutton = Checkbutton(self.root, variable=self.value, command=self.onClicked)
self.checkbutton.pack()
def onClicked(self):
# calling IntVar.get() returns the state
# of the widget it is associated with
print(self.value.get())
app = GUI()
app.root.mainloop()
This is because you need to use one of tkinter's variable classes.
This would look something like the below:
from tkinter import *
root = Tk()
var = IntVar()
var.trace("w", lambda name, index, mode: print(var.get()))
Checkbutton(root, variable=var).pack()
root.mainloop()
Essentially IntVar() is a "container" (very loosely speaking) which "holds" the value of the widget it's assigned to.
Im trying to make a little program that endlessly prints out numbers inside GUI window, I can not find a way to print the out put of the function in a text box inside the GUI window instead of the python shell, please help, here is my code so far...
import sys
from tkinter import *
root = Tk()
def number(event):
x = 420
while True:
x +=420
print(x^70)
button_1 = Button(root, text="Start...")
button_1.bind("<Button-1>", number)
button_1.pack()
root.mainloop()
Thanks Harvey
You'll find it hard to constantly insert a value into a widget. The widget does not update with each insert. You can think of it has having a temporary variable for it. It can be accessed during the loop (as shown with print). However you'll notice that the widget itself doesn't update until the loop is over. So if you have while True then your widget will never update, and so you won't have the numbers streaming into the widget.
import sys
from tkinter import *
root = Tk()
def number():
x = 420
while x < 8400: # Limit for example
x +=420
textbox.insert(END, str(x^70)+'\n')
print(textbox.get(1.0, END)) # Print current contents
button_1 = Button(root, text="Start...", command=number) #Changed bind to command, bind is not really needed with a button
button_1.pack()
textbox = Text(root)
textbox.pack()
root.mainloop()
I'm writing a python script that requires the user to enter the name of a folder. For most cases, the default will suffice, but I want an entry box to appear that allows the user to over-ride the default. Here's what I have:
from Tkinter import *
import time
def main():
#some stuff
def getFolderName():
master = Tk()
folderName = Entry(master)
folderName.pack()
folderName.insert(END, 'dat' + time.strftime('%m%d%Y'))
folderName.focus_set()
createDirectoryName = folderName.get()
def callback():
global createDirectoryName
createDirectoryName = folderName.get()
return
b = Button(master, text="OK and Close", width=10, command=callback)
b.pack()
mainloop()
return createDirectoryName
getFolderName()
#other stuff happens....
return
if __name__ == '__main__':
main()
I know next to nothing about tkInter and have 2 questions.
Is over-riding the default entry using global createDirectoryName within the callback function the best way to do this?
How can I make the button close the window when you press it.
I've tried
def callback():
global createDirectoryName
createDirectoryName = folderName.get()
master.destroy
but that simply destroys the window upon running the script.
I don't know how experienced are you in Tkinter, but I suggest you use classes.
try:
from tkinter import * #3.x
except:
from Tkinter import * #2.x
class anynamehere(Tk): #you can make the class inherit from Tk directly,
def __init__(self): #__init__ is a special methoed that gets called anytime the class does
Tk.__init__(self) #it has to be called __init__
#further code here e.g.
self.frame = Frame()
self.frame.pack()
self.makeUI()
self.number = 0 # this will work in the class anywhere so you don't need global all the time
def makeUI(self):
#code to make the UI
self.number = 1 # no need for global
#answer to question No.2
Button(frame, command = self.destroy).pack()
anyname = anynamehere() #remember it alredy has Tk
anyname.mainloop()
Also why do you want to override the deafult Entry behavior ?
The solution would be to make another button and bind a command to it like this
self.enteredtext = StringVar()
self.entry = Entry(frame, textvariable = self.enteredtext)
self.entry.pack()
self.button = Button(frame, text = "Submit", command = self.getfolder, #someother options, check tkitner documentation for full list)
self.button.pack()
def getfolder(self): #make the UI in one method, command in other I suggest
text = self.enteredtext.get()
#text now has whats been entered to the entry, do what you need to with it