returning the clicked date from ttkcalendar widget - python-2.7

I am trying to use this calendar widget code within an existing tkinter. I want to have the clicked date returned, so that I can do things with it. I have tried calling the pressed function like so
from ttkcalendar import *
def clicked(event):
print cal.selection()
...
root = Tk()
cal=Calendar(mainframe)
cal.bind("<Button-1>",clicked)
However this returns a Type Error: 'datetime.datetime' object not callable. Suggestions? I am sure there is a correct way to do this...thanks in advance!

Method selection() has decorator #property, thus you should do as follows:
def clicked(event):
print cal.selection
# i.e. not cal.selection()

Related

how to call event from another module in tkinter

i made a test app for reasons like this. I am trying to have the ButtonRelease-1 event call a function inside another file. I am getting a syntax when trying to run the app.
TypeError: listb() takes exactly 2 arguments (1 given)
this is pretty strait forward syntax but i cannot fix it in this specific situation. I am basically just having the event get the clicked info printed. It's the event that is no working because function inside other file is not reconizing the event?
anyways, curious how to fix this code so it works. The function has to stay in another file. This would be easy if it was in same file but it cannot be.
start.py
from Tkinter import *
import example_funcs as EF
class Page_three(Frame):
def __init__(self):
Frame.__init__(self)
self.pack()
self.listboxs()
def listboxs(self):
self.z = Listbox(self)
self.z.grid()
for item in range(1,10):
self.z.insert(END, item)
self.z.bind("<ButtonRelease-1>", EF.listb(self))
root = Tk()
app = Page_three()
app.mainloop()
example_funcs.py
from Tkinter import *
import Tkinter as tk
def listb(self, event):
selection = self.z.curselection()
print selection
self is used so variables can be called inside the function, if do not call self as instance it will have syntax of not finding my listbox variable.
Passing EF.listb(self) doesn't do what you want it to do. It doesn't partially bind the self parameter to the instance you're calling it from, then let the event paramter get filled in by the callback. Instead, it just calls the function immediately (before the bind call is made) and you get an error about using the wrong number of arguments.
There are a few different ways you could fix this issue.
One option would be to manually bind the self parameter to the listb function using functools.partial:
import example_funcs as EF
import functools
class Page_three(Frame):
...
def listboxs(self):
...
self.z.bind("<ButtonRelease-1>", functools.partial(EF.listb, self)) # bind self
Another approach would be to make listb an actual method in your class, so that you can reference it as a method on self. That could look like this:
import example_funcs as EF
class Page_three(Frame):
...
def listboxs(self):
...
self.z.bind("<ButtonRelease-1>", self.listb) # refer to a method without calling it
listb = EF.listb # add the function from the other module as a method on this class
If listb isn't used anywhere else though, then defining it in another module and copying it over here would be pretty silly. You should just move the definition into this class instead of adding a reference to it after the fact. On the other hand, if listb is being used in several different classes, it suggests that the classes should be using some kind of inheritance to share the method, rather than crudely copying references to the one definition around.

Closing Tkinter GUI from another function A and passes Tkinter variable to function A

This question is about programming in Python 2.7.x
I wanted to code a programme where there are two functions exist: one of those is a method to get input from the user, and the other one is to show the input. Both are supposed to be done in GUI. Let's call the first function as GET TEXT function, and the second as SHOW TEXT function; my strategy is to open a GUI, show a text box, and put a button to go to SHOW TEXT function. Then, the first line of the SHOW TEXT function is to close the window opened by the GET TEXT function, get the value of the input text, and print it in another GUI.
So, I tried doing this,
from Tkinter import *
import tkMessageBox
def texttobeenteredhere():
application = Tk()
textbox = Text(application)
textbox.pack()
submitbutton = Button(application, text="OK", command=showinputtext)
submitbutton.pack()
application.mainloop()
def showinputtext():
application.quit()
thetext = textbox.get()
print "You typed", thetext
texttobeenteredhere()
I got errors that I could not comprehend, but I hope you get my idea even though my explanation could be really bad. Please suggest a solution to my problem, where the GET TEXT function and SHOW TEXT function have to exist separately in the code.
EDIT:
Thanks Josselin for introducing the syntax class in python. What I actually wanted to say was, I want the programme to open a window to get input from the user, and then close the window, and finally open another window to show the input text. I am honestly new to this, but through my prior knowledge and guessing, I tried to modify the code to meet my expectation.
import Tkinter as tk
global passtext
class application(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.textbox = tk.Text(self)
self.textbox.pack()
self.submitbutton = tk.Button(self, text="OK", command=self.showinputtext)
self.submitbutton.pack()
self.mainloop()
def showinputtext(self):
self.thetext = self.textbox.get("1.0", "end-1c")
print "You typed:", self.thetext
self.destroy()
class showtext(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.setthetext = tk.StringVar()
self.setthetext.set(passtext)
self.showthetext = tk.Label(self, textvariable=self.setthetext)
self.showthetext.pack()
self.submitbutton = tk.Button(self, text="OK", command=self.destroy)
self.submitbutton.pack()
self.mainloop()
# Launch the GUI
app = application()
# Access the entered text after closing the GUI
passtext = app.thetext
text = showtext()
My English can sometimes be not understandable, but this question is answered. Thank you very much.
There are 2 main problems in your code:
First, in your showinputtext function, you want to access elements of your GUI, but they are not defined within the scope of the function.
Second, when reading the content of a tk.Text widget, the .get() method takes 2 arguments (see this link).
To fix the first problem, the best is to define your application as a class, with an inner function taking the class instance self as input argument, such that application widgets can be called within the function.
Code:
import Tkinter as tk
class application(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.textbox = tk.Text(self)
self.textbox.pack()
self.submitbutton = tk.Button(self, text="OK", command=self.showinputtext)
self.submitbutton.pack()
self.mainloop()
def showinputtext(self):
self.thetext = self.textbox.get("1.0", "end-1c")
print "You typed:", self.thetext
self.destroy()
# Launch the GUI
app = application()
# Access the entered text after closing the GUI
print "you entered:", app.thetext

the message in the message box is not printing the addition of the two numbers

from Tkinter import *
from tkMessageBox import *
root=Tk()
Label(root,text="first").grid(row=0)
Label(root,text="second").grid(row=2)
e1=Entry(root)
e1.grid(row=0,column=2)
e2=Entry(root)
e2.grid(row=2,column=2)
a=e1.get()
b=e2.get()
def add():
c=a+b
s=showinfo(title="answers",message='addition='+c)
You seem to be getting the value from the entry widget immediately after creating the widget. You need to wait until the user types something in.
You also seem to have the problem that nothing is calling add, so it seems to be impossible for the message to even show up at all.

Trace not working on Python TKinter checkbutton control

I'm doing my own tweak on the technique from this post, using a canvas vs. a text widget to get some finer control over the scrolling behavior. My code appears below.
All is working as I want it but for some reason the trace I'm using to track the checkbutton values isn't working. No errors of any kind show up in the console window. But I don't get the expected printed message (from _cbWasClicked) when I click one any of the checkbuttons. As best I can tell the method is just never invoked.
I know it's got to be a simple and obvious bug but I'm stumped. I've used print statements to confirm that the 100 IntVars get instantiated as expected. Then I deliberately misspelled the method name in the .trace and this time it generated an error. So when I yank those diagnostic tweaks all should be working.... it just isn't. Can someone tell me what I'm missing?
Environment is Python 2.7 on Windows 7.
import Tkinter as tk
class myCheckList(tk.Frame):
def __init__(self, root, *args, **kwargs):
tk.Frame.__init__(self, root, *args, **kwargs)
self.root = root
self.vsb = tk.Scrollbar(self, orient="vertical")
self.canvas = tk.Canvas(self, width=200, height=290,
relief=tk.GROOVE,bd=3,
scrollregion=(0,0,0,2020),
yscrollcommand=self.vsb.set,
yscrollincrement=20)
basecolor = self.canvas.cget('background')
self.vsb.config(command=self.canvas.yview)
self.canvas.grid(row=0,column=0,sticky=tk.NSEW,padx=(0,0),pady=0)
self.vsb.grid(row=0,column=1,sticky=tk.NS,padx=(0,0),pady=0)
for i in range(100):
cbv = tk.IntVar()
cbv.trace('w',self._cbWasClicked)
cb = tk.Checkbutton(self, background=basecolor,
variable=cbv,
text="Checkbutton #%s" % i)
self.canvas.create_window(5,20*i+5,anchor=tk.NW,window=cb)
self.canvas.bind_all('<MouseWheel>',
lambda event: self.canvas.yview_scroll(-1*event.delta/120, tk.UNITS))
def _cbWasClicked(self,*args):
print 'checkbox clicked'
if __name__ == "__main__":
root = tk.Tk()
myCheckList(root).grid(row=0,column=0,sticky=tk.W,padx=0,pady=0)
root.mainloop()
Found it, after much wrestling and experimenting. It turns out that the trace works perfectly when I add a couple of lines to the class's __init__:
self.status = []
...and then, inside the loop...
self.status.append((cb,cbv))
...which tells me that garbage collection is the culprit. By creating a list and storing the object references in it, they couldn't be garbage-collected and so the .trace remains effective.
First off, you should prepend self. to cbv and cb within the FOR cycle.
Secondly, even then it is going to work only for the very last checkbox, because with each iteration you overwrite the variable cbv again and again.
As a workaround I used a list of vaiables (self.li) generated one step before the cycle. This way you can link each checkbox to its own variable:
self.li = ['cbv' + str(i) for i in range(100)]
for i in range(100):
self.li[i] = tk.IntVar()
self.cb = tk.Checkbutton(self, background=basecolor,
variable=self.li[i],
text="Checkbutton #%s" % i)
self.li[i].trace('w', self._cbWasClicked)
self.canvas.create_window(5,20*i+5,anchor=tk.NW,window=self.cb)
...
This code worked fine for me.
You will then need to identify each checkbox somehow. You can do it using the internal variable name which is passed as the first param to the callback function in the trace method (What are the arguments to Tkinter variable trace method callbacks?):
def _cbWasClicked(self, name, *args):
print('checkbox %s clicked:' % name)
In the output you'll get something like this:
checkbox PY_VAR10 clicked:
checkbox PY_VAR99 clicked:
checkbox PY_VAR0 clicked:

subclassing sorl-thumbnail `ThumbnailBackend` class, and overriding _get_thumbnail_filename does not work

I intend to subclass the ThumbnailBackend class from sorl.thumbnail.base. What I need to do is to override the _get_thumbnail_filename method, to add some stuff to the filename generated by the original (parent) method. To do so, I wrote something like this:
from sorl.thumbnail.base import ThumbnailBackend
class MyThumbnailBackend(ThumbnailBackend):
def _get_thumbnail_filename(self, source, geometry_string, options):
oldpath = super(ThumbnailBackend,self)._get_thumbnail_filename(source, geometry_string, options)
oldpathlist = oldpath.split('/')
# get the last item of 'oldpathlist' and
# sufix it with useful info...
# join the items with the modified one...
return newpath
There should be something I'm missing with python inheritance, because I keep getting the following error:
AttributeError at /location/of/the/caller/class/
'super' object has no attribute '_get_thumbnail_filename'
If I'm right, I'm importing this class, in the first line: from sorl.thumbnail.base import ThumbnailBackend which definitely has a _get_thumbnail_filename method.
What am I doing wrong?
Thank you very much!
You have to call super with the current class, change super(ThumbnailBackend, self) to super(MyThumbnailBackend, self), like this
class MyThumbnailBackend(ThumbnailBackend):
def _get_thumbnail_filename(self, source, geometry_string, options):
return super(MyThumbnailBackend, self)._get_thumbnail_filename(source, geometry_string, options)