My code :-
def load():
label.configure(text="Error")
button = tkinter.Button(main,width=8,text="Continue >", command="load")
and the window is running perfectly but the callback is not running, I have tried many kind of callbacks like printing configuring etc. but didn't worked. What is solution?
The command argument is expecting to have a function, Not a string.
Instead of string, use the the function.
Instead of:
button = tkinter.Button(main,width=8,text="Continue >", command="load")
write:
button = tkinter.Button(main,width=8,text="Continue >", command=load)
In your code you passed load as a string .So it doesn't work. Because command in the sense what command should be performed when the component Button is clicked.
So try to change it don't pass it as a string .
Change it as
button = tkinter.Button(main,width=8,text="Continue >", command=load)
Related
I want to generate a button for each .py document in a file, and each button give a different argument to the function
for name in files:
if name[-3:]=='.py':
a=name[:-3]
button=Button(barre, text=a, command=python_file(a))
button.pack()
def python_file(name):
text = Text(barre)
text.insert(name)
os.popen("python3 "+a+".py","r")
It basicly write the name of the python file and execute. But, I need to give a different name to each button, just like : button1, button2 (...).
Also when I run my code, It execute the function each time thee is a new python file.
Thx for helping !!
Change the command argument in your button to:
button=Button(barre, text=a, command=lambda a=a: python_file(a))
The argument passing to your function is the one which is the last value in the for loop. To pass the current value, you need to specify it through the lambda function.
Also, change the os.popen method like this to fully execute the code inside the file.
c = os.popen("python3 "+a+".py","r")
print(c.read())
I am unable to pass any parameter to a function called by a guizero widget either with the attribute "command" at initialization or by invoking an event.
This works as expected (no parameters passed):
from guizero import App, PushButton
def go():
print (10)
app = App(title="Test")
button = PushButton(app, text = "Click Here", command = go)
app.display()
but the following prints the number 10 once, before the button is clicked and then when I click, nothing happens
from guizero import App, PushButton
def go(n):
print (n)
app = App(title="Test")
button = PushButton(app, text = "Click Here", command = go(10))
app.display()
The same result I get with this:
from guizero import App, PushButton
def go(n):
print (n)
app = App(title="Test")
button = PushButton(app, text = "Click Here")
button.when_clicked = go(10)
app.display()
What am I missing?
Thanks in advance!
from guizero import App, PushButton
def go(n):
print (n)
app = App(title="Test")
button = PushButton(app, text = "Click Here", command = lambda: go(10))
app.display()
Whenever you write go(10) anywhere, you are invoking the function go. You might think you are passing go with arguments, but you aren't because the parentheses next to go() invoke the function right then and there. If you want to pass the function go to another function, and go should also be passed with some arguments, then you need to wrap the function go and pass the wrapped function as the argument "command". Using a lambda function to wrap go(10) is one such way of doing this.
The reason this works is that the lambda function is NOT invoked right then and there. You are saying that that command() should invoke the declared anonymous lambda function eventually, and when that lambda function is called it will itself call go(10). You are declaring an anonymous lambda function, NOT invoking it. The lambda function will be invoked later on as command().
In all GUI frameworks command= (or similar) expects callback - it means function's name without () and without parameters.
If you use go(10) then it does
result = go(10)
PushButton( ...., command=result)
so it executes go(10) before you even click button - and it assign result to command=. Because go() returns None so you get PushButton( ...., command=None) and when you click button then you get nothing.
You have to create new function which you can run without ()
def go_10():
go(10)
PushButton( ...., command=go_10)
Or you can use lambda to create function directly in command=
PushButton( ...., command=lambda:go(10))
I found the solution!
Using a lambda function is a clever way to work around the callback limitation but I found a more proper way to pass arguments to a function by using the widget properties (pun not intended). As it turns out I missed a very brief reference to the property args that can be set at instantiation and is used to pass a list to the function called by command
So here is my solution:
from guizero import App, PushButton
def go(n):
print (n)
app = App(title="Test")
button = PushButton(app, text = "Click Here", args = [10], command = go)
app.display()
As expected, it prints '10' every time you click the button and not before.
Thanks for all the other answers!
Newbie programmer here. I am building a tk based desktop app and ran into an issue:
I have a main window with several stuff in it including two tabs:
global nBook
nBook = ttk.Notebook(self, name="book")
nBook.place(x=300,y=400)
frameOne = ttk.Frame(nBook, width=100, height=100)
frameTwo = ttk.Frame(nBook, width=100, height=100)
nBook.add(frameOne, text='T1')
nBook.add(frameTwo, text='T2')
frameOne.bind("<<NotebookTabChanged>>", self.routine())
frameTwo.bind("<<NotebookTabChanged>>", self.routine())
routine() is a function that SHOULD perform a check every time T2 is selected
def routine(self):
if str(nBook.index(nBook.select())) == "2":
# Do stuff
else:
pass
Problem is that it doesn't do anything when the tab is changed except for calling the routine function as soon as I open the app and never again. I just can't figure out what I'm doing wrong.
Could anyone point out the mistake(s) I'm making?
EDIT: Same issue if I try
nBook.bind("<<NotebookTabChanged>>", self.xbRoutine())
The error comes from the event binding statements: when using self.routine() the callback is called when the bind statement is executed, not when the event is triggered. To get the correct behavior, the second argument of bind should be the name of a function not a call to this function, so simply remove the parentheses.
Another error: when using bind, the callback function is expected to have a first argument (traditionnaly called event) storing the event parameters. So you should define your callback as:
def routine(self, event):
...
I had the same problem. The answer given by #sciroccorics is not complete.
What you bind is not the tab itself, but the notebook.
So, it should be
nBook.bind("<<NotebookTabChanged>>", self.xbRoutine)
Alternatively you could use lambda.
In your case this will look something like this:
frameOne.bind("<<NotebookTabChanged>>", lambda _: self.routine())
Don't forget the _, otherwise you will get a TypeError, since the event is passed as an argument.
lamba is really helpful if your function requires one or more arguments.
Pardon me for my simple question, but I don't understand some thing.
I want to give a few arguments from button which is located in popup window in one method to another method.
Example:
.py code
class GeneralForm(TabbedPanel):
def EDIT(self,D):
box1=BoxLayout(orientation='vertical')
t1=TextInput(text=GeneralForm.PARSE(self,D))
b2=Button(text='Save')
b3=Button(text='Cancel')
box2=BoxLayout()
box2.add_widget(b2)
box2.add_widget(b3)
box1.add_widget(t1)
box1.add_widget(box2)
popup = Popup(content=box1,auto_dismiss=False,size_hint=(.75,.75),title='Edit')
b2.bind(on_press=self.SAVE_EDIT) <====== There is a problem
b3.bind(on_press=popup.dismiss)
popup.open()
def SAVE_EDIT(self,instance):
!!! DOING SOMETHING !!!
https://s3.amazonaws.com/xasan/snapshot/stack1.png
What I want:
In method "EDIT" I have text input "t1". After changing text in this text input I press button "b2" which calls method SAVE_EDIT with two arguments.
So, I want to give the third agrument to "SAVE_EDIT" method which will return an edited text in t1.
Something like this:
.py code
class GeneralForm(TabbedPanel):
def EDIT(self,D):
box1=BoxLayout(orientation='vertical')
t1=TextInput(text=GeneralForm.PARSE(self,D))
b2=Button(text='Save')
b3=Button(text='Cancel')
box2=BoxLayout()
box2.add_widget(b2)
box2.add_widget(b3)
box1.add_widget(t1)
box1.add_widget(box2)
popup = Popup(content=box1,auto_dismiss=False,size_hint=(.75,.75),title='Edit')
b2.bind(on_press=self.SAVE_EDIT(t1.txt)) <====== There is a problem
b3.bind(on_press=popup.dismiss)
popup.open()
def SAVE_EDIT(self,instance,TEXT): <====== There is a problem
!!! DOING SOMETHING with TEXT!!!
Step-by-step:
Popen window was opened with some text in the text input.
We edited text, deleted something or added.
We are clicking on button "Save"(b2) and all text in txt input(t1) push to method "SAVE_EDIT" where we save,parse or do something else
with this text.
Thanks in advance.
You could use lambda:
on_press=lambda instance, text=t1.txt: self.SAVE_EDIT(instance, TEXT=text)
Or functools.partial():
on_press=partial(self.SAVE_EDIT, TEXT=t1.txt)
Both variants use t1.txt at the time of the bind call i.e., the value may be obsolete by the time you press the button.
To use the current most recent value:
on_press=lambda instance: self.SAVE_EDIT(instance, TEXT=t1.txt)
In this case, t1.txt is called each time the callback is invoked.
I have a button at my window. If I cklick it, I want to start the VLC and stream an URL.
def startstream():
args = ['C:/Program Files/VideoLAN/VLC/vlc.exe', 'http://dreambox:8001/1:0:19:7B:B:85:C00000:0:0:0:']
subprocess.call(args)
# Buttons
button_tnt = Button(fenster, text = "TNT Serie HD", command = startstream)
This works as I want.
The following one doesn't work like I want it and I have no idea why not.
def startstream(url):
args = ['C:/Program Files/VideoLAN/VLC/vlc.exe', url]
subprocess.call(args)
# Buttons
button_tnt = Button(fenster, text = "TNT Serie HD", command = startstream('http://dreambox:8001/1:0:19:7B:B:85:C00000:0:0:0:'))
With the first code, the window appears and nothing happen. If I click the button, the stream starts, perfect.
Second code: I run the script and the stream starts immediatelly. After I close the VLC I cannot reopen the stream over the button, it has no function.
But I want to use the second code. I have more than one button and so I can only change the argument for each button. With the first code I have to write a new function for every stream.
Please help me :(
Thanks!
You're executing startstream instead of assigning it*. To give it arguments, use the following:
button_tnt = Button(fenster,
text="TNT Serie HD",
command= lambda: startstream('http://dreambox:8001/1:0:19:7B:B:85:C00000:0:0:0:'))
*specifically, you're executing startstream(..) and assigning the result of that to command.
The lambda will instead create the function that command will call when clicked.
The reason is, that when constructing Button, purpose of command argument is to define a function to be called, when the button is called.
Your first example does that, it assigns name of a function to call.
In second you do not assign a function, but result of calling the startstream call. That is why it starts streaming immediately.
If you really want to assign a function using the url, you may do so this way:
from functools import partial
# Buttons
button_tnt = Button(fenster, text = "TNT Serie HD", command = partial(startstream, 'http://dreambox:8001/1:0:19:7B:B:85:C00000:0:0:0:'))
The partial will create a new function, which will call startstream with given parameter.
The trouble is that in your second example you're not passing arguments to startstream on click, you're calling startstream when you create your button.
button_tnt = Button(fenster,
text = "TNT Serie HD",
command = startstream('http://dreambox:8001/1:0:19:7B:B:85:C00000:0:0:0:'))
# ^ Invocation takes place right here.