Python Tkinter error - can't invoke "bind" command - python

I'm trying to bind a button to a simple function.
This is my code:
from Tkinter import *
root=Tk()
def printName(event):
print 'hi my name is Beni'
button_1.bind("<Button-1>",printName)
button_1.pack()
root.mainloop()
The error I get is:
TclError: can't invoke "bind" command: application has been destroyed
Any ideas?

You need to define button_1.
For example:
button_1 = Button(root, text="ButtonName")
So your entire code snippet would be:
from Tkinter import *
root=Tk()
def printName(event):
print('hi my name is Beni')
button_1 = Button(root, text="ButtonName")
button_1.bind("<Button-1>",printName)
button_1.pack()
root.mainloop()

Related

I have a weird problem with tkinter when using python

I am trying to learn how to use Tkinter, but whenever I want to execute my code I always get this problem: (NameError: name 'label' is not defined) or (NameError: name 'button' is not defined).
As a beginner, it seems to me that the problem is with my code editor. (BTW I am using VScode)
this is my code:
from tkinter import *
root = Tk()
mylabel = label(root, text='Hello World')
mylabel.pack()
root.mainloop()
And as I said, this also happens with this one:
from tkinter import *
root = Tk()
mybutton = button(root, text='Hello World')
mybutton.pack()
root.mainloop()
you have caps error its Button and Label not button and label

Properly assigning a function with arguments to a button in Tkinter

I have two files:
functions.py
import tkinter as tk
class funcs():
def func1(entry):
entry.delete(0, tk.END)
main.py
import tkinter as tk
import functions as f
root = tk.Tk()
entrybox = tk.Entry(master=root).grid()
button = tk.Button(master=root, command=f.funcs.func1(entrybox)).grid()
root.mainloop()
In main.py, I have assigned the command func1 with the argument entrybox to the widget button.
My intent is to have the entry argument represent an entry widget I want to manipulate.
This line of code is broken:
button = tk.Button(master=root, command=f.funcs.func1(entrybox)).grid()
The problem is that when I run the program, the function is called immediately and does not get assigned to the button.
I am looking for a way to assign a function with arguments to a button in tkinter.
You can use an anonymous function:
tk.Button(
master=root,
command=lambda: f.funcs.func1(entrybox)
)
Python recognizes the broken line of code as an immediate call, so you have to do lambda:
button = tk.Button(master=root, command=lambda: f.funcs.func1(entrybox)).grid()
and as far as I know that will get rid of the problem.

Trying to run .ahk files in tkinter

this is my first time here so if I break some unwritten rules please don't shoot me
I've been trying build an app for editing, reading and opening .ahk files. The last one gives me problems.
this code kind of does what I want except it fires the command immediately after opening the app.
from tkinter import *
from tkinter import filedialog
import os
import threading
root = Tk()
def openfile():
os.system( r'\Users\merijn\PycharmProjects\infoprojectP3\venv\Scripts\ahkScript1.ahk')
def func():
print("hello")
btn1 = Button(text='programma', command=threading.Thread(target=openfile).start())
btn2 = Button(text='ander ding', command=func)
btn1.pack()
btn2.pack()
root.mainloop()
Any help would be much appreciated!
Change the following line (it just assigns the result of threading.Thread(...) to command option):
Button(text="run program1", command=threading.Thread(target=lambda: os.system(r'\Users\merijn\PycharmProjects\infoprojectP3\venv\Scripts\ahkScript1.ahk').start()))
to
Button(text="run program1", command=lambda: threading.Thread(target=lambda: os.system(r'\Users\merijn\PycharmProjects\infoprojectP3\venv\Scripts\ahkScript1.ahk')).start())
or
Button(text="run program1", command=lambda: threading.Thread(target=os.system, args=[r'\Users\merijn\PycharmProjects\infoprojectP3\venv\Scripts\ahkScript1.ahk']).start())
Same for buttons of run program2 and run program3.
Update: based on your updated code, you need to change the following line:
btn1 = Button(text='programma', command=threading.Thread(target=openfile).start())
to
btn1 = Button(text='programma', command=lambda: threading.Thread(target=openfile).start())

Linking tkinter GUI with functions in a different module

I want to link GUI (1. modul) with the functions that are in a different module. Basically I need to link GUI with the program.
I created a very easy example:
modul1:
from modul2 import *
from tkinter import *
window = Tk()
window.title('Program')
window.geometry("300x300")
text_input= StringVar()
#result
result=Entry(window, textvariable=text_input)
result.place(x=6,y=15)
#Button
button=Button(window, text='X')
button.config(width=5, height=2, command=lambda: test())
button.place(x=10,y=70)
window.mainloop()
modul2:
import modul1
def test():
global text_input
text_input.set('hello')
EXPECTED:
This program should write "hello" into Entry window after clicking on a button.
RESULT: ERROR:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Ondrej\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:/Users/Ondrej/Desktop/VUT FIT/IVS\modul1.py", line 17, in <lambda>
button.config(width=5, height=2, command=lambda: test())
NameError: name 'test' is not defined
Does anybody know where the problem is?
Thank you in advance for the help.
Yes, the problem you actually have is to do with a circular import. Modul1 imports Modul2 and Modul2 imports Modul1. a way you could solve this is to give the textinput as a parameter to the test function in modul2 like this:
modul1.py:
import modul2
from tkinter import *
window = Tk()
window.title('Program')
window.geometry("300x300")
text_input = StringVar()
# result
result = Entry(window, textvariable=text_input)
result.place(x=6, y=15)
# Button
button = Button(window, text='X')
button.config(width=5, height=2, command=lambda: modul2.test(text_input))
button.place(x=10, y=70)
window.mainloop()
modul2.py:
def test(text_input):
text_input.set('hello')
Unfortunately python really doesn't like you to do circular imports and this is good as this would actually mean an infinite loop. When would it stop importing the other file?
Edit: there would be a very convoluted way to make a class in a third module and set attributes on that, and then import this third module in both modul1 and modul2 to share variables between them but please don't...
Edit2: an example of this:
Modul1.py:
from shared import SharedClass
import modul2
from tkinter import *
window = Tk()
window.title('Program')
window.geometry("300x300")
SharedClass.text_input = StringVar()
# result
result = Entry(window, textvariable=SharedClass.text_input)
result.place(x=6, y=15)
# Button
button = Button(window, text='X')
button.config(width=5, height=2, command=lambda: modul2.test())
button.place(x=10, y=70)
window.mainloop()
Modul2.py:
from shared import SharedClass
def test():
SharedClass.text_input.set('hello')
shared.py
class SharedClass:
pass
This works due to the way python loads imported classes. They all are the same. This makes it so if you set properties on the class (not the instances of it) you can share the properties.

Simple Button Hide on Click

Hello I'm obviously not too experienced with tkinter very much and I couldnt find anything on what I was looking for, maybe someone could help me
def hide(x):
x.pack_forget()
d=Button(root, text="Click to hide me!" command=hide(d))
d.pack()
I would like it so that on click the command runs but the button is not defined when calling the command
You can not use anything if you are still building. Must you use configure and lambda function:
from tkinter import *
def hide(x):
x.pack_forget()
root = Tk()
d=Button(root, text="Click to hide me!")
d.configure(command=lambda: hide(d))
d.pack()
root.mainloop()
First, define the button, then add the command with the config method.
from tkinter import *
root = Tk()
def hide(x):
x.pack_forget()
d=Button(root, text="Click to hide me!")
d.pack()
d.config(command=lambda: hide(d))
root.mainloop()

Categories