binding two buttons to the same widget tkinter [duplicate] - python

This question already has answers here:
Binding Tkinter button: function takes exactly 1 positional argument (0 given)
(2 answers)
Closed 2 years ago.
Is it possible to bind two diff keys to the same widget and call a different function. I am getting error that dbase() missing positional argument event even though i have passed in event as an argument
UPDATE: So the actual error is when i bind 'Return' to an entry widget and then i try clicking the button, then i get the error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\nihaa\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
TypeError: dbase() missing 1 required positional argument: 'event'
Code:
def search():
log = Toplevel(root)
log.title('Search Book')
def dbase(event):
.....
def clicker(event):
....
def key_pressed(event):
....
entry1.bind_all('<Key>',key_pressed)
button1.bind('<Button-1>',clicker)
entry1.bind('<Return>',dbase)

When you press the button, it will call the function dbase.
But your function dbase need to pass an argument event, but at this time, it won't pass any arguments.That's why it will raise Exception(If you call the dbase by the .bind, it will pass a argument).To solve this issue, you need to bind a default argument for your event:
import tkinter
def dbase(event=None):
print("you are passing")
r = tkinter.Tk()
b = tkinter.Button(r,command=dbase)
r.bind_all("<Return>", dbase)
b.pack()
r.mainloop()
Or if you don't need the argument,use lambda in the bind:
import tkinter
def dbase():
print("you are passing")
r = tkinter.Tk()
b = tkinter.Button(r,command=dbase)
r.bind_all("<Return>", lambda e: dbase())
b.pack()
r.mainloop()
This could work when you press the button directly or press <Enter>.

Related

Getting "TypeError: insertstop() takes 0 positional arguments but 1 was given" when there are no arguments in my function calls

I'm very new to Python and I'm trying to put my first application together that takes in trip information and inserts it into a text box for export out to a document. It's gone pretty good until today when I tried to implement multiple ways of inserting text from an entrybox into a text block with tkinter.
I have an entry widget that inserts text into a text widget when a button is pressed. That's simple enough but I wanted to make it to where you could simply hit the enter key to do the same thing.
When I implement this function I get the error:
"Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Spyder\pkgs\tkinter_init_.py", line 1892, in __ call __
return self.func(*args)
TypeError: insertstop() takes 0 positional arguments but 1 was given"
I've looked the error up and it seems like it would pop up if I put in arguments in my function call but I don't have any arguments in any of my function calls. Also it seems like maybe this error is related to a class or something? I haven't learned about classes yet and only have a basic idea of what they are. Do I need a class to do this?
Coincidentally I also added the argument(self) in my function and that made pressing enter work but it made my insert stop button quit working.
I'm sure I've missed something very basic but I just can't figure out what.
Thanks for any help!
import time
import os
import sys
from tkinter import *
# Creates the Tkinter form named "screen"
screen = Tk()
screen.geometry("550x645")
screen.title("Test")
# Initialize frames
menuframe = Frame(screen,
height=60,width=600,bg="gray",pady=5)
inputframe = Frame(screen,
height=300,width=600,pady=5)
outputframe = Frame(screen,
height=290,width=600,pady=5)
# Packs the frames so they will display
menuframe.pack()
inputframe.pack()
outputframe.pack()
#==STOPBOX==#
stopbox=Text(inputframe,yscrollcommand=1,height= 10,width=20,
padx=3,pady=3,relief=GROOVE,bg="gray79")
stopbox.place(x=345, y=90)
def insertstop():
global stop_vanconv
stop_vanconv=(stop_entry.get())
stopbox.insert(END, stop_vanconv + "\n")
stop_entry.delete("0","end")
stoplist_label = Label(inputframe,
text="Type stop locations and press" + '\n' +
"the Add Stop button to insert a new stop.")
stoplist_label.place(x=100, y=150)
stop_entry = Entry(inputframe,
textvariable = " ")
stop_entry.place(x=150, y=190)
addstopbutton = Button(inputframe,text="Add Stop",padx=20,pady=0,
activebackground="darkslategray4",command=insertstop)
addstopbutton.place(x=160, y=220)
stop_entry.bind('<Return>',insertstop)
screen.mainloop()

Tkinter/Python - Simple Login Application NoneType Error [duplicate]

This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 5 years ago.
I am trying to develop a simple login desktop app with tkinter lib. My code is working but when I'm trying to login with correct username and password it's giving the NoneType error. I am writing my codes on Pycharm. Here is my code:
from tkinter import *
window=Tk()
rootname = "Casca"
rootpasswd = "12345"
def loginfunc():
passwd=plogin.get()
name=ulogin.get()
if name==rootname and passwd==rootpasswd:
print("Successfull Login")
else:
print("Unauthorized User")
username=Label(text="Username:",font="Consolas,20").grid(row=0,column=0)
ulogin=Entry(font="Consolas,20",width=8).grid(row=0,column=1)
passwd=Label(text="Password:",font="Consolas,20").grid(row=1,column=0)
plogin=Entry(font="Consolas,20",width=8,show="*").grid(row=1,column=1)
sremember=Checkbutton(text="I forgot my password",font="Consolas,20").grid(row=2,column=0,columnspan=2)
login=Button(text="Login",font="Consolas,20",command=loginfunc).grid(row=3,column=0)
window=mainloop()
And here is the error:
Exception in Tkinter callback
Traceback (most recent call last):
File "BLABLABLA", line 1699, in __call__
return self.func(*args)
File "BLABLABLA", line 9, in loginfunc
passwd=plogin.get()
AttributeError: 'NoneType' object has no attribute 'get'
Entry() returns the instance of the tkinter entry widget
Entry().grid() returns NoneType.
Change your code as shown below
from tkinter import *
window=Tk()
rootname = "Casca"
rootpasswd = "12345"
def loginfunc():
passwd=plogin.get()
name=ulogin.get()
if name==rootname and passwd==rootpasswd:
print("Successfull Login")
else:
print("Unauthorized User")
username=Label(text="Username:",font="Consolas,20").grid(row=0,column=0)
ulogin=Entry(font="Consolas,20",width=8)
ulogin.grid(row=0,column=1)
passwd=Label(text="Password:",font="Consolas,20").grid(row=1,column=0)
plogin=Entry(font="Consolas,20",width=8,show="*")
plogin.grid(row=1,column=1)
sremember=Checkbutton(text="I forgot my password",font="Consolas,20").grid(row=2,column=0,columnspan=2)
login=Button(text="Login",font="Consolas,20",command=loginfunc).grid(row=3,column=0)
window=mainloop()
You will have to do the same thing with the checkbox to get it's value.
You should also consider IntVar and StringVar variables to store the contents of these widgets.
When you do plogin = Entry(...).grid(...) you replace plogin with the result of .grid(), which is None. To fix this, you could do:
plogin = Entry(...)
plogin.grid(...)
and similar for all the other widgets.

How can the variable be used by other functions in TkfileDialog?

I intended to write a GUI to import URLs data then process these data,
so I had 2 buttons. Below is my code.
from Tkinter import *
root=Tk()
root.title('Videos Episodes')
root.geometry('500x300')
def OpenFile(): # import URLs data from local machine
paths=tkFileDialog.askopenfilename()
return paths
def read_files(paths): #read data from the directory from OpenFile
with open(paths) as myfile:
return data
Button(root,text='Input',command=OpenFile).pack()
Button(root,text='Process',command=read_files).pack()
root.mainloop()
My problem is that when 'Process' button clicked, error happened:
Exception in Tkinter callback Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1532, in __call__
return self.func(*args) TypeError: read_files() takes exactly 1 argument (0 given)
How can I fix the bug?
If you want to pass an argument (you didn't specify what), use a lambda:
Button(root,text='Process',command=lambda: read_files('whatever')).pack()
Perhaps, this is what you wanted to do (?):
Button(root,text='Process',command=lambda: read_files(OpenFile())).pack()
or alternatively, you meant to store the result of OpenFile (from clicking the other button) in a global variable, and pass that as argument of read_files...?

Tkinter callback function causing ValueError

I am having problem with the callback function of the tkinter trace method. I would like to have 2 entries and the value of each entry depends on the value of another. So if I change the value of one, the value of the other is changed. This is some simple code doing this:
from tkinter import *
class main():
def __init__(self, master):
self.a = DoubleVar(value=2.0)
self.b = DoubleVar()
self.b.trace("w",self.calc_c)
self.c = DoubleVar()
self.c.trace("w",self.calc_b)
Entry(master,textvariable=self.b).grid(row=0,column=0)
Entry(master,textvariable=self.c).grid(row=0,column=1)
def calc_b(self,name,index,mode):
self.b.set(self.c.get()/self.a.get())
def calc_c(self,name,index,mode):
self.c.set(self.b.get()*self.a.get())
root = Tk()
prog = main(root)
root.mainloop()
The program is actually working, returning the right values, but also an error is produced:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib64/python3.3/tkinter/__init__.py", line 1475, in __call__
return self.func(*args)
File "/home/anze/foo.py", line 22, in calc_c
self.c.set(self.b.get()*self.a.get())
File "/usr/lib64/python3.3/tkinter/__init__.py", line 332, in get
return getdouble(self._tk.globalgetvar(self._name))
ValueError: could not convert string to float:
Can someone please explain the meaning of this error?
Thank you!
I think the problem is that the widget is an Entry, which takes a string as input, and your value is a DoubleVar, but you have no validation in place to prevent the user entering an invalid value.
Your code works as long as the input value is a float. When you call get() in calc_c and calc_b after an invalid value was entered, tkinter tries to convert the string in the Entry into a float, fails and throws a ValueError exception.
You can catch the exception with a try-except block. In the try block you put the code that might raise an exception. The except block defines what happens when an exception is caught. You can also have an else block that defines what happens when no exception is caught.
Here's a simple example (with no else block) for calc_c that restores the previous value (calc_b would need to be modified in a similar way):
def calc_c(self,name,index,mode):
try:
self.c.set(self.b.get()*self.a.get())
except ValueError:
# here you can either complain to the user (message-box...)
# or just restore the last value using the other entry like so:
self.b.set(self.c.get()/self.a.get())
I believe your issue is that you are binding self.c to an Entry widget:
Entry(master,textvariable=self.c).grid(row=0,column=1)
But, the textvariable should be set to a Tkinter.StringVar. How about creating a new variable to hold the Entry's string value and then convert in your calc method:
from tkinter import *
class main():
def __init__(self, master):
self.a = DoubleVar(value=2.0)
self.b = DoubleVar()
self.b.trace("w",self.calc_c)
self.c = DoubleVar()
self.c_str = StringVar()
self.c.trace("w",self.calc_b)
Entry(master,textvariable=self.b).grid(row=0,column=0)
Entry(master,textvariable=self.c_str).grid(row=0,column=1)
def calc_b(self,name,index,mode):
self.c.set(float(self.c_str.get()))
self.b.set(self.c.get()/self.a.get())
def calc_c(self,name,index,mode):
self.c.set(self.b.get()*self.a.get())
root = Tk()
prog = main(root)
root.mainloop()
Note you'll probably want to do the same for the other Entry.
I had a similar error using Tk.scale(... resolution=0.1, ...).
When there was matplotlib used in the same script, the decimal number from scale was written with , instead of . and caused an error in getdouble().
I found a workaround by changing the regional settings of the os(kubuntu14.04) from German to US with . as default decimal seperator.
It not satisfying solution but may help to find the problem.

Why use different approaches rather than direct, when connecting signals?

I am working with Python 3.3 and PyQt 4.10.1. Below figure is from PyQt book.
Assume that there are 5 buttons as shown below. When clicked on each, they will change label's text a context that includes their button number. For example, when user clicks on the button with caption "Four" on it, it will change the label to You clicked button 'Four'
Instead of creating a signal slot for each of the buttons, a generalised method is created which accepts a paramater and partial() method is used:
...
self.label = QLabel("Click on a button.")
self.button1 = QPushButton("One")
...
self.button5 = QPushButton("Five")
self.connect(self.button1, SIGNAL("clicked()")
, partial(self.anyButton, "One"))
...
self.connect(self.button5, SIGNAL("clicked()")
, partial(self.anyButton, "Five"))
...
def anyButton(self, buttonNumber):
self.label.setText("You clicked button '%s'" % buttonNumber)
Whenever I want to change partial(self.anyButton, "One") to self.anyButton("One"), I get an error like below.
Traceback (most recent call last):
File "C:\Users\abdullah\Desktop\test.py", line 47, in <module>
form = Form()
File "C:\Users\abdullah\Desktop\test.py", line 20, in __init__
, self.anyButton("One"))
TypeError: arguments did not match any overloaded call:
QObject.connect(QObject, SIGNAL(), QObject, SLOT(), Qt.ConnectionType=Qt.AutoC
onnection): argument 3 has unexpected type 'NoneType'
QObject.connect(QObject, SIGNAL(), callable, Qt.ConnectionType=Qt.AutoConnecti
on): argument 3 has unexpected type 'NoneType'
QObject.connect(QObject, SIGNAL(), SLOT(), Qt.ConnectionType=Qt.AutoConnection
): argument 3 has unexpected type 'NoneType'
What is the reason for this? Why I cannot directly call the function? Also, why partial() method works?
partial returns you the function anyButton where the argument is substituted.
self.anyButton("One") gives you the value returned by the function.

Categories

Resources