how to draw on any window from a widget in python - python

I am new in python and i want to create a script in python which can let me draw or paint in my desktop or on any window like web browser etc.....
Can anybody tell me which library in python can i use to achieve something this.
As i want to draw directly on the desktop screen and not in any canvas or particular (seperate window for drawing)
From tkinter.colorchooser or something else.
The example image is shown below that's how i want.
how can i get a widget like this with only color option and default pen to draw.

Use python in-built library Tkinter.
from tkinter import *
from tkinter.colorchooser import askcolor
class Paint(object):
DEFAULT_PEN_SIZE = 5.0
DEFAULT_COLOR = 'black'
def __init__(self):
self.root = Tk()
self.pen_button = Button(self.root, text='pen', command=self.use_pen)
self.pen_button.grid(row=0, column=0)
self.brush_button = Button(self.root, text='brush', command=self.use_brush)
self.brush_button.grid(row=0, column=1)
self.color_button = Button(self.root, text='color', command=self.choose_color)
self.color_button.grid(row=0, column=2)
self.eraser_button = Button(self.root, text='eraser', command=self.use_eraser)
self.eraser_button.grid(row=0, column=3)
self.choose_size_button = Scale(self.root, from_=1, to=10, orient=HORIZONTAL)
self.choose_size_button.grid(row=0, column=4)
self.c = Canvas(self.root, bg='white', width=600, height=600)
self.c.grid(row=1, columnspan=5)
self.setup()
self.root.mainloop()
def setup(self):
self.old_x = None
self.old_y = None
self.line_width = self.choose_size_button.get()
self.color = self.DEFAULT_COLOR
self.eraser_on = False
self.active_button = self.pen_button
self.c.bind('<B1-Motion>', self.paint)
self.c.bind('<ButtonRelease-1>', self.reset)
def use_pen(self):
self.activate_button(self.pen_button)
def use_brush(self):
self.activate_button(self.brush_button)
def choose_color(self):
self.eraser_on = False
self.color = askcolor(color=self.color)[1]
def use_eraser(self):
self.activate_button(self.eraser_button, eraser_mode=True)
def activate_button(self, some_button, eraser_mode=False):
self.active_button.config(relief=RAISED)
some_button.config(relief=SUNKEN)
self.active_button = some_button
self.eraser_on = eraser_mode
def paint(self, event):
self.line_width = self.choose_size_button.get()
paint_color = 'white' if self.eraser_on else self.color
if self.old_x and self.old_y:
self.c.create_line(self.old_x, self.old_y, event.x, event.y,
width=self.line_width, fill=paint_color,
capstyle=ROUND, smooth=TRUE, splinesteps=36)
self.old_x = event.x
self.old_y = event.y
def reset(self, event):
self.old_x, self.old_y = None, None
if __name__ == '__main__':
Paint()

Related

Is there any way to make tkinter Radiobutton transparent on tkinter canvas?

I want to make radiobutton transparent on canvas image to make it look good, I tried passing lots of option parameters to radiobutton to somehow make it look better but nothing works.
Here is the code I am working with...
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
from PIL import ImageTk, Image
from tkinter import messagebox
class GUI_Prog:
def __init__(self):
root = Tk()
root.title("Risk Analysis")
root.geometry("1100x630")
r = IntVar()
#Setting up Canvas :
my_canvas = Canvas(root, width=1100, height=630)
my_canvas.pack(fill="both", expand=True)
#Background :
img = Image.open("diagnosis.png")
img = img.resize((1100,630), Image.ANTIALIAS)
bg = ImageTk.PhotoImage(img)
my_canvas.create_image(0,0,image=bg,anchor="nw")
#Creating title text :
my_canvas.create_text(540,40,text="Risk Analysis", font=("Times, 30"), fill = "white")
my_canvas.create_text(140,100,text="1) Do you smoke?", font=("helvetica, 15"), fill = "black")
but_1 = Radiobutton(root, text="yes", variable=r, value=1)
my_canvas.create_window(60, 150, window=but_1)
but_2= Radiobutton(root, text="no", variable=r, value=2)
my_canvas.create_window(150, 150, window=but_2)
mainloop()
obj = GUI_Prog()
Well I created my own RadioButton class but it only works on tkinter.Canvas:
from tkinter import *
from tkinter import ttk
from tkinter.ttk import *
from PIL import ImageTk, Image
from tkinter import messagebox
# Taken from: https://stackoverflow.com/a/17985217/11106801
def _create_circle(self, x, y, r, **kwargs):
return self.create_oval(x-r, y-r, x+r, y+r, **kwargs)
Canvas.create_circle = _create_circle
class Radiobutton:
def __init__(self, canvas, text="", variable=None, value=0, radius=10,
fill="black"):
self.canvas = canvas
self.variable = variable
self.fill = fill
self.text = text
self.value = value
self.radius = radius
self.variable.trace("w", self.redraw)
self.circle = None
def put(self, x, y):
self.x = x
self.y = y
self.canvas.create_circle(x, y, self.radius, outline=self.fill)
self.canvas.create_text(x + 2*self.radius, y, text=self.text,
fill=self.fill, anchor="w")
self.redraw()
self.canvas.bind("<Button-1>", self.select, add=True)
def select(self, event):
if (self.x - event.x)**2 + (self.y - event.y)**2 <= self.radius**2:
self.variable.set(self.value)
self.redraw()
def create_circle(self):
self.circle = self.canvas.create_circle(self.x, self.y, self.radius-4,
outline=self.fill,
fill=self.fill)
def redraw(self, *args):
if self.value == self.variable.get():
if self.circle is None:
self.create_circle()
else:
if self.circle is not None:
self.canvas.delete(self.circle)
self.circle = None
class GUI_Prog:
def __init__(self):
root = Tk()
root.title("Risk Analysis")
root.geometry("1100x630")
r = IntVar()
#Setting up Canvas:
my_canvas = Canvas(root, width=1100, height=630)
my_canvas.pack(fill="both", expand=True)
#Background:
img = Image.open("diagnosis.png")
img = img.resize((1100, 630), Image.ANTIALIAS)
bg = ImageTk.PhotoImage(img)
my_canvas.create_image(0, 0, image=bg, anchor="nw")
#Creating title text:
my_canvas.create_text(540, 40, text="Risk Analysis",
font=("Times", 30), fill="white")
my_canvas.create_text(140, 100, text="1) Do you smoke?",
font=("helvetica", 15), fill="black")
but_1 = Radiobutton(my_canvas, text="yes", variable=r, value=1,
fill="white")
but_1.put(60, 150)
but_2 = Radiobutton(my_canvas, text="no", variable=r, value=2,
fill="white")
but_2.put(150, 150)
r.set(1)
root.mainloop()
obj = GUI_Prog()
You create it as normal but you pass in the <tkinter.Canvas> as its master. After that you can just call .put with the position where you want it to be created. This is a very patchy solution so if someone else posts a better solution, I will delete this.

tkinter canvas won't update object's color after click on the object

I am working on a project which kind of basic paint in python and I'm stuck on this flood fill part, it won't update the color of the object and there's no error so I can't figure out which part is wrong.
from tkinter import *
from tkinter.colorchooser import askcolor
coords = {"x1":0,"y1":0,"x2":0,"y2":0}
lines = []
class Filling():
def __init__(self, main):
self.main = main
self.main.title('Filling')
self.main.geometry("800x620")
btncir=Button(main, text="CIRCLE", fg='black', width=8, command=self.circle)
btncir.place(x=10, y=200)
btnfill=Button(main, text="FILL", fg='black', width=8, command=self.clickfillrec)
btnfill.place(x=10, y=250)
btnclear=Button(main, text="COLOR", fg='black', width=8, command=self.color_choice)
btnclear.place(x=10, y=300)
self.canvas = Canvas(self.main, bg='white', bd=5, relief=RIDGE, height=600, width=700)
self.canvas.place(x=80, y=0)
def circle(self):
self.canvas.bind("<ButtonPress-1>", self.circle_click)
self.canvas.bind("<B1-Motion>", self.drag)
def circle_click(self, e):
coords["x1"] = e.x
coords["y1"] = e.y
lines.append(self.canvas.create_oval(coords["x1"],coords["y1"],coords["x1"],coords["y1"]))
def drag(self, e):
coords["x2"] = e.x
coords["y2"] = e.y
self.canvas.coords(lines[-1], coords["x1"],coords["y1"],coords["x2"],coords["y2"])
def color_choice(self):
self.DEFAULT_COLOR = self.color
self.color = askcolor()
def clickfillrec(self):
self.canvas.bind("<Button-1>", self.ffillrec)
self.canvas.bind("<B1-Motion>", self.nothing)
def nothing(self, event):
pass
def ffillrec(self, event):
item = self.canvas.find_closest(event.x, event.y)
x = event.x
y = event.y
current_color = self.canvas.itemcget(item, 'fill')
if (x > 0) and (self.canvas.itemcget((event.x-1, event.y), 'fill')) == current_color:
self.canvas.itemconfig((event.x-1, event.y), fill = self.color)
if (y > 0) and (self.canvas.itemcget((event.x, event.y-1), 'fill')) == current_color :
self.canvas.itemconfig((event.x, event.y-1), fill = self.color)
if (x < self.canvas.winfo_screenwidth()) and (self.canvas.itemcget((event.x+1, event.y), 'fill')) == current_color :
self.canvas.itemconfig((event.x+1, event.y), fill = self.color)
if (y < self.canvas.winfo_screenheight()) and (self.canvas.itemcget((event.x, event.y+1), 'fill')) == current_color :
self.canvas.itemconfig((event.x, event.y+1), fill = self.color)
main = Tk()
p = Filling(main)
main.mainloop()
I tried main.update() and self.canvas.update_idletasks() but still doesn't work

How to make child Tkinter object trigger a change in parent's widget

Edit: thanks to #jasonharper's comments below I can ask a more informed question:
I have a main app, and a separate module snipping_tool.py that handles creating a new window with the option to screen-snip or select an image file. I want snipping_tool.py to provide an image to the main app, but currently I'm trying to retrieve the image too soon (before the snipping_tool window even opens).
How can I wait until the user selects or grabs an image before I try to assign MyNewObject.selected_image? Should I use a binding or some event handler? (I have limited experience with both). Or is there a simpler way?
Simplified Main App:
import tkinter as tk
import snipping_tool
class MinCodeEx:
def __init__(self, master):
self.master = master
self.ButtonA = tk.Button(width=60,height=40,command = lambda: self.UpdateImg(master))
self.ButtonA.pack()
def UpdateImg(self, master):
newDialog = snipping_tool.AcquireImage(self.master)
# self.ButtonA['image'] = newDialog.image_selected
#if newDialog.image_selected:
self.ButtonA.config(image=newDialog.image_selected)
print(newDialog.image_selected)
def main():
root = tk.Tk()
MinCodeEx(root)
root.mainloop()
if __name__ == '__main__':
main()
snipping_tool.py
returns None instead of an image file since I'm trying to retrieve the selected_image too soon.
import tkinter as tk
from PIL import ImageGrab, ImageTk, Image
import cv2
import numpy as np
from tkinter import filedialog
class ScreenSnip(tk.Toplevel):
def __init__(self, master):
super().__init__(master)
self.image = None
def get_snip(self):
self.configure(cursor='cross')
self.attributes('-fullscreen', True)
self.attributes('-alpha', 0.4)
self.canvas = tk.Canvas(self, bg='dark gray')
self.canvas.pack(fill='both', expand=True)
self.begin_x = 0
self.begin_y = 0
self.end_x = 0
self.end_y = 0
self.click_drag = False
self.canvas.create_rectangle(0, 0, 0, 0, outline='#0052d6', width=2, fill='white', tags='snip_rect')
self.canvas.bind('<ButtonPress-1>', self.mousePressEvent)
self.canvas.bind('<B1-Motion>', self.mouseMoveEvent)
self.canvas.bind('<ButtonRelease-1>', self.mouseReleaseEvent)
print('Capture the screen...')
def mousePressEvent(self, event):
self.begin_x = event.x
self.begin_y = event.y
print(self.begin_x,self.begin_y)
def mouseMoveEvent(self, event):
self.click_drag = True
self.end_x = event.x
self.cur_y = event.y
width = self.end_x - self.begin_x
height = abs(width * 2/3)
if self.cur_y < self.begin_y:
height *= -1
self.end_y = self.begin_y + height
self.canvas.coords('snip_rect', self.begin_x, self.begin_y, self.end_x, self.end_y)
def mouseReleaseEvent(self, event):
self.destroy()
self.master.update_idletasks()
self.master.after(100) # give time for screen to be refreshed so as not to see the blue box on the screenshot
if not self.click_drag: # if the user just clicks, instead of clicking and dragging
self.begin_x -= 300
self.begin_y += 200
self.end_x = self.begin_x + 600
self.end_y = self.begin_y - 400
x1 = min(self.begin_x, self.end_x)
y1 = min(self.begin_y, self.end_y)
x2 = max(self.begin_x, self.end_x)
y2 = max(self.begin_y, self.end_y)
self.img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
self.image = ImageTk.PhotoImage(self.img)
#self.img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
#cv2.imshow('Captured Image', self.img)
#cv2.waitKey(0)
font1 = ("arial", 18, "bold")
class AcquireImage:
def __init__(self, master):
self.master = master
self.nWin = tk.Toplevel(master)
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(self.nWin, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command =lambda: self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")#, padx=10, pady=10)
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command=lambda: self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")#, padx=10, pady=10)
self.image_selected = None
def show_dialogs(self, method): ################### THIS IS WHERE THE IMAGE IS SELECTED ###########
if method == 1:
ret = filedialog.askopenfilename()
if ret:
self.image_selected = ImageTk.PhotoImage(file = ret)
self.nWin.destroy()
elif method == 2:
newWin = ScreenSnip(self.nWin)
newWin.get_snip()
ret = newWin.image
if ret:
self.image_selected = ret
def main():
root = tk.Tk()
AcquireImage(root)
root.mainloop()
if __name__ == '__main__':
main()
#jasonharper was right. This solution is derived from his comments.
When I create an instance of AcquireImage I also pass ButtonA as a parameter so that I can modify its image. Within AcquireImage I first get a new image (either by snipping it, or with the file explorer) and then to avoid garbage collection immediately deleting it, I save it by assigning it to ButtonA.img. (I first create the .img part of ButtonA in the main program). Once I have the image, I can then assign it.
I probably could have also solved this issue by creating a function
within the main program that changes the image of whatever widget is
passed to it as a parameter. I could then pass this function to the
instance of AcquireImage with ButtonA as a parameter. It might
have looked something like this in the main program: def callback(i_file): ButtonA['image'] = i_file newDialog = snipping_tool.AcquireImage(self.master, self.callback) Later I
would have AcquireImage initialized/defined with
self.some_function as the second argument (after master), and I
could pass the image file to it. At least that's how I probably could
have done it.
This is how I actually solved it:
MAIN APP
import tkinter as tk
import snipping_tool
waitingforImage = True
class MinCodeEx:
global waitingforImage
def __init__(self, master):
self.master = master
self.ButtonA = tk.Button(width=60,height=40,command = lambda: self.UpdateImg())
self.ButtonA.pack()
self.ButtonA.img = None
def UpdateImg(self):
newDialog = snipping_tool.AcquireImage(self.master, self.ButtonA)
def main():
root = tk.Tk()
MinCodeEx(root)
root.mainloop()
if __name__ == '__main__':
main()
snipping_tool.py
import tkinter as tk
from PIL import ImageGrab, ImageTk, Image
from tkinter import filedialog
class ScreenSnip(tk.Toplevel):
def __init__(self, master, changeThis):
super().__init__(master)
self.image = None
self.master = master
self.changeThis = changeThis
def get_snip(self):
self.configure(cursor='cross')
self.attributes('-fullscreen', True)
self.attributes('-alpha', 0.4)
print("attempting to create tk.Canvas for get_snip")
self.canvas = tk.Canvas(self, bg='dark gray')
self.canvas.pack(fill='both', expand=True)
self.begin_x = 0
self.begin_y = 0
self.end_x = 0
self.end_y = 0
self.click_drag = False
self.canvas.create_rectangle(0, 0, 0, 0, outline='#0052d6', width=2, fill='white', tags='snip_rect')
self.canvas.bind('<ButtonPress-1>', self.mousePressEvent)
self.canvas.bind('<B1-Motion>', self.mouseMoveEvent)
self.canvas.bind('<ButtonRelease-1>', self.mouseReleaseEvent)
print('Capture the screen...')
def mousePressEvent(self, event):
self.begin_x = event.x
self.begin_y = event.y
print(self.begin_x,self.begin_y)
def mouseMoveEvent(self, event):
self.click_drag = True
self.end_x = event.x
self.cur_y = event.y
width = self.end_x - self.begin_x
height = abs(width * 2/3)
if self.cur_y < self.begin_y:
height *= -1
self.end_y = self.begin_y + height
self.canvas.coords('snip_rect', self.begin_x, self.begin_y, self.end_x, self.end_y)
def mouseReleaseEvent(self, event):
self.destroy()
self.master.update_idletasks()
self.master.after(100) # give time for screen to be refreshed so as not to see the blue box on the screenshot
if not self.click_drag: # if the user just clicks, instead of clicking and dragging
self.begin_x -= 300
self.begin_y += 200
self.end_x = self.begin_x + 600
self.end_y = self.begin_y - 400
x1 = min(self.begin_x, self.end_x)
y1 = min(self.begin_y, self.end_y)
x2 = max(self.begin_x, self.end_x)
y2 = max(self.begin_y, self.end_y)
self.img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
print("getting image grab")
self.changeThis.img = ImageTk.PhotoImage(self.img)
self.changeThis['image'] = self.changeThis.img
font1 = ("arial", 18, "bold")
class AcquireImage:
def __init__(self, master, changeThis):
self.master = master
self.changeThis = changeThis
self.nWin = tk.Toplevel(master)
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(self.nWin, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command =lambda: self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")#, padx=10, pady=10)
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command=lambda: self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")#, padx=10, pady=10)
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename() #filedialog.askopenfilename(initialdir='/home/user/images/')
self.changeThis.img = ImageTk.PhotoImage(file = ret)
self.changeThis['image'] = self.changeThis.img
elif method == 2:
print("attempting ScreenSnip")
newWin = ScreenSnip(self.master, self.changeThis)
newWin.get_snip()
self.nWin.destroy()
def main():
root = tk.Tk()
bt = tk.Button(root, width = 20, height = 20)
bt.pack()
ScreenSnip(root, bt)
#AcquireImage(root,bt)
root.mainloop()
if __name__ == '__main__':
main()
I still need to fix one unrelated thing -- the button doesn't fit the size of the image that I select or grab. It always ends up being a small square.

AttributeError: '_tkinter.tkapp' object has no attribute 'mousePressEvent'

I'm having trouble with two tkinter classes that I want to interact. I think it comes from my lack of understanding of the Tk.Toplevel. Instead of creating an entirely new full-screen window for screen-grabbing, my code gives an error:
AttributeError: '_tkinter.tkapp' object has no attribute 'mousePressEvent'
Can someone help me understand the hierarchy of parent-child relationships in my code? I'm not asking anyone to rewrite my code, I just want to understand what I already have, so I can figure out what's wrong. I haven't found many examples in SO of multiple classes that interact with multiple windows - so it's hard to grasp the inter-workings of inheritance.
This is the structure I think I have:
root
object: AquireImage
method: show_dialogs()
object: ScreenSnip
method: get_snip()
method: mousePressEvent()
method: mouseMoveEvent()
method: mouseReleaseEvent()
Is this accurate?
CODE
import tkinter as tk
from PIL import ImageGrab, ImageTk, Image
import cv2
import numpy as np
from tkinter import filedialog
class ScreenSnip(tk.Toplevel):
def __init__(self, master):
super().__init__(master)
def get_snip(self):
self.configure(cursor='cross')
self.attributes('-fullscreen', True)
self.attributes('-alpha', 0.4)
self.canvas = tk.Canvas(self, bg='dark gray')
self.canvas.pack(fill='both', expand=True)
self.begin_x = 0
self.begin_y = 0
self.end_x = 0
self.end_y = 0
self.click_drag = False
self.canvas.create_rectangle(0, 0, 0, 0, outline='#0052d6', width=2, fill='white', tags='snip_rect')
self.canvas.bind('<ButtonPress-1>', self.mousePressEvent)
self.canvas.bind('<B1-Motion>', self.mouseMoveEvent)
self.canvas.bind('<ButtonRelease-1>', self.mouseReleaseEvent)
print('Capture the screen...')
def mousePressEvent(self, event):
self.begin_x = event.x
self.begin_y = event.y
print(self.begin_x,self.begin_y)
def mouseMoveEvent(self, event):
self.click_drag = True
self.end_x = event.x
self.cur_y = event.y
width = self.end_x - self.begin_x
height = abs(width * 2/3)
if self.cur_y < self.begin_y:
height *= -1
self.end_y = self.begin_y + height
self.canvas.coords('snip_rect', self.begin_x, self.begin_y, self.end_x, self.end_y)
def mouseReleaseEvent(self, event):
self.destroy()
self.master.update_idletasks()
self.master.after(100) # give time for screen to be refreshed so as not to see the blue box on the screenshot
if not self.click_drag: # if the user just clicks, instead of clicking and dragging
self.begin_x -= 300
self.begin_y += 200
self.end_x = self.begin_x + 600
self.end_y = self.begin_y - 400
x1 = min(self.begin_x, self.end_x)
y1 = min(self.begin_y, self.end_y)
x2 = max(self.begin_x, self.end_x)
y2 = max(self.begin_y, self.end_y)
img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
self.img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
cv2.imshow('Captured Image', self.img)
cv2.waitKey(0)
font1 = ("arial", 18, "bold")
class AcquireImage:
def __init__(self, master):
self.master = master
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command =lambda: self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")#, padx=10, pady=10)
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command=lambda: self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")#, padx=10, pady=10)
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename() #filedialog.askopenfilename(initialdir='/home/user/images/')
if ret:
self.image_selected = ImageTk.PhotoImage(file = ret)
self.master.destroy()
elif method == 2:
newWin = ScreenSnip.get_snip(self.master)
ret = newWin.img
if ret:
self.image_selected = ImageTk.PhotoImage(file = ret)
def main():
root = tk.Tk()
AcquireImage(root)
root.mainloop()
if __name__ == '__main__':
main()
This answer is derived from #jasonharper's comment:
Instances of ScreenSnip would indeed have a mousePressEvent
attribute. But you never create any such instance; instead, you
attempt to call get_snip() on the class itself, which ends up
providing a completely inappropriate value for its self parameter.
The mistake I made was here:
newWin = ScreenSnip.get_snip(self.master)
I tried to create a new object newWin without putting the parent in the correct place, and while calling the method get_snip at the same time. This is what solved the issue:
newWin = ScreenSnip(self.master)
newWin.get_snip()
First create the object ScreenSnip from the class, with the parent
then call the method `get_snip'

having trouble in setting up a calendar in tkinter

i have a small ui programm and i need to display a calendar in it or a date picker . (NOTE : userid and password is root")**
i have tried this code :
from Tkinter import *
from PIL import Image, ImageTk
import ttkcalendar
class App():
def __init__(self):
pass
root = Tk()
root.configure(bg='black')
root.attributes('-alpha', 0.0)
def mainWindow(self):
self.root.geometry('{}x{}'.format(600,400))
self.root.attributes('-alpha', 1)
self.root.configure(bg='#404040')
self.ttkcal = ttkcalendar.Calendar(self.root,firstweekday=calendar.SUNDAY)
self.ttkcal.pack()
self.root.wm_title("time sheet management system")
# Create the toolbar as a frame
self.toolbar = Frame(self.root, borderwidth=1, relief='raised')
self.toolbar.configure( bg = '#838383')
# Load all the images first as PNGs and use ImageTk to convert
# them to usable Tkinter images.
self.img1 = Image.open('NewIcon.png')
self.useImg1 = ImageTk.PhotoImage(self.img1)
self.img2 = Image.open('LoadIcon.png')
self.useImg2 = ImageTk.PhotoImage(self.img2)
self.img3 = Image.open('SaveIcon.png')
self.useImg3 = ImageTk.PhotoImage(self.img3)
# Set up all the buttons for use on the toolbars.
newBtn = Button(self.toolbar, image=self.useImg1, command=self.callback)
newBtn.pack(side=LEFT, fill=X)
loadBtn = Button(self.toolbar, image=self.useImg2, command=self.callback)
loadBtn.pack(side=LEFT, fill=X)
saveBtn = Button(self.toolbar, image=self.useImg3, command=self.callback)
saveBtn.pack(side=LEFT, fill=X)
# Add the toolbar
self.toolbar.pack(side=TOP, fill=X)
"""
#create a frame
self.infoArea= Frame(self.root, borderwidth=2,height=40,width=100, relief='raised',bg='red')"""
self.root.mainloop()
"""
# Set up a Text box and scroll bar.
self.scrollbar = Scrollbar(self.root)
self.scrollbar.pack(side=RIGHT, fill=Y)
self.text = Text(self.root)
self.text.pack()
self.text.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.config(command=self.text.yview)"""
def loginClick(self):
self.userid = self.txt1.get()
self.password = self.txt2.get()
print self.userid,self.password
if self.password == 'root' and self.userid == 'root':
self.wi.destroy()
self.mainWindow()
def callback(self):
print "A button was pressed"
def login(self):
self.wi = Toplevel (self.root)
#self.wi.geometry('{}x{}'.format(200,200))
self.wi.configure(bg='#404040')
self.wi.overrideredirect(1)
self.wi.update_idletasks()
self.w = self.wi.winfo_screenwidth()
self.h = self.wi.winfo_screenheight()
self.size = tuple(int(_) for _ in self.wi.geometry().split('+')[0].split('x'))
self.x = self.w/2 - self.size[0]/2
self.y = self.h/2 - self.size[1]/2
self.wi.geometry("%dx%d+%d+%d" % (self.size + (self.x, self.y)))
self.wi.geometry('{}x{}'.format(400,200))
self.frame1 = Frame ( self.wi,bg='#404040' )
self.frame1.pack(side=BOTTOM,fill=X)
self.butt1 = Button(self.frame1,text= "Cancel" , bg = '#838383',fg='white',command = self.wi.destroy)
self.butt1.pack(side=RIGHT,padx=1)
self.butt2 = Button(self.frame1,text= "Login" ,bg = '#838383',fg='white',command = self.loginClick)
self.butt2.pack(side=RIGHT)
"""self.frame2 = Frame ( self.wi,bg='green' )
self.frame2.pack(side=BOTTOM,fill=BOTH)"""
self.lab1 = Label (self.wi,text='UserID',bg='#404040',fg='white')
#self.lab1.pack(side=LEFT,padx=60,pady=20)
self.lab1.place(x=60,y=20)
self.lab2 = Label (self.wi,text='Password',bg='#404040',fg='white')
#self.lab1.pack(side=LEFT,padx=60,pady=20)
self.lab2.place(x=60,y=60)
self.txt1 = Entry( self.wi)
self.txt1.place(x=140,y=20)
self.txt2 = Entry( self.wi,show='*')
self.txt2.place(x=140,y=60)
"""
self.label = Label(self.wi,text="UserID",bg='#838383',fg='white')
self.label.place("""
self.wi.mainloop()
if __name__ == "__main__":
a = App()
#a.root.mainloop()
a.login()
but it is giving error that "name calendar not defined". how can i solve this ?
or is there any other way to implement a calendar or date picker in tkinter.
The code is using calendar module, but it is not importing the module.
self.ttkcal = ttkcalendar.Calendar(self.root, firstweekday=calendar.SUNDAY)
^^^^^^^^^^^^^^^
Simply adding following import statement will solve the problem.
import calendar

Categories