Related
As it's in title, I have get into problem of getting text of an screenshot that's updating every less than second. But unfortunately am not getting any return value from image_to_string. What am doing wrong? My codes are bellow:
def WindowScreenshot(window_title=None):
if window_title:
hwnd = win32gui.FindWindow(None, window_title)
if hwnd:
x, y, x1, y1 = win32gui.GetClientRect(hwnd)
x, y = win32gui.ClientToScreen(hwnd, (x,y))
x1, y1 = win32gui.ClientToScreen(hwnd, (x1 - x, y1 - y))
im = pyautogui.screenshot(region=(x + 50, y + 147, x1 - 665, y1 - 528))
im.save("images/1.png")
else:
print("Window not fount!")
else:
im = pyautogui.screenshot()
im.save("images/1.png")
Screenshot is saving properly (updating quick)
while True:
# So here on loop am getting screenshot from a window title
im = WindowScreenshot("Windowed Projector (Preview)")
img = Image.open("images/1.png")
text = pytesseract.image_to_string(img)
print(text)
I managed to find in someone who made a class for rounded buttons in tkinter that works great. However the issue I have is there is always a white border.
I've tried reading through all of the code and changing all of the colour values but to no avail.
Here is an excerpt of the code working, I've tried to format it as nicely as I could:
from tkinter import Tk, Canvas
class RoundedButton(Canvas):
def __init__(self, master=None, text: str = "", radius=25, btnforeground="#007CEE", btnbackground="#ffffff",
clicked=None, font=("Righteous", 25), *args, **kwargs):
super(RoundedButton, self).__init__(master, *args, **kwargs)
self.config(bg=self.master["bg"])
self.btnbackground = btnbackground
self.btnforeground = btnforeground
self.clicked = clicked
self.radius = radius
self.rect = self.round_rectangle(0, 0, 0, 0, tags="button", radius=radius, fill=btnbackground)
self.text = self.create_text(0, 0, text=text, tags="button", fill=btnforeground, font=font,
justify="center")
self.tag_bind("button", "<ButtonPress>", self.border)
self.tag_bind("button", "<ButtonRelease>", self.border)
self.bind("<Configure>", self.resize)
text_rect = self.bbox(self.text)
if int(self["width"]) < text_rect[2] - text_rect[0]:
self["width"] = (text_rect[2] - text_rect[0]) + 10
if int(self["height"]) < text_rect[3] - text_rect[1]:
self["height"] = (text_rect[3] - text_rect[1]) + 10
def round_rectangle(self, x1, y1, x2, y2, radius=25, update=False,
**kwargs): # if update is False a new rounded rectangle's id will be returned else updates existing rounded rect.
# source: https://stackoverflow.com/a/44100075/15993687
points = [x1 + radius, y1,
x1 + radius, y1,
x2 - radius, y1,
x2 - radius, y1,
x2, y1,
x2, y1 + radius,
x2, y1 + radius,
x2, y2 - radius,
x2, y2 - radius,
x2, y2,
x2 - radius, y2,
x2 - radius, y2,
x1 + radius, y2,
x1 + radius, y2,
x1, y2,
x1, y2 - radius,
x1, y2 - radius,
x1, y1 + radius,
x1, y1 + radius,
x1, y1]
if not update:
return self.create_polygon(points, **kwargs, smooth=True)
else:
self.coords(self.rect, points)
def resize(self, event):
text_bbox = self.bbox(self.text)
if self.radius > event.width or self.radius > event.height:
radius = min((event.width, event.height))
else:
radius = self.radius
width, height = event.width, event.height
if event.width < text_bbox[2] - text_bbox[0]:
width = text_bbox[2] - text_bbox[0] + 30
if event.height < text_bbox[3] - text_bbox[1]:
height = text_bbox[3] - text_bbox[1] + 30
self.round_rectangle(5, 5, width - 5, height - 5, radius, update=True)
bbox = self.bbox(self.rect)
x = ((bbox[2] - bbox[0]) / 2) - ((text_bbox[2] - text_bbox[0]) / 2)
y = ((bbox[3] - bbox[1]) / 2) - ((text_bbox[3] - text_bbox[1]) / 2)
self.moveto(self.text, x, y)
def border(self, event):
if event.type == "4":
self.itemconfig(self.rect, fill="#DE8500")
self.itemconfig(self.text, fill='#ffffff')
if self.clicked is not None:
self.clicked()
else:
self.itemconfig(self.rect, fill=self.btnbackground)
self.itemconfig(self.text, fill=self.btnforeground)
window = Tk()
window.geometry("1440x872")
window.configure(bg="#007CEE")
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=0)
download_button_1.place(
x=409,
y=383,
width=621.0,
height=105.0
)
window.mainloop()
EDIT: Furas' answer works perfect, for anyone interested in using this rounded button class I would reccommend changing the splinesteps to a higher value at self.create_polygon to help with smoothing
return self.create_polygon(points, **kwargs, smooth=True, splinesteps=10000)
On Linux works for me
highlightthickness=0
or set color of background
highlightbackground="#007CEE"
eventually
borderwidth=-1
Doc for Canvas (page effbot.org on archive.org) shows all config options.
Before:
After:
2023.01.28:
Using: Pop!_OS 22.04 LTS //Python 3.10.6// Tcl/Tk V.8.6
"borderwidth=-1" did not seem to work, but "highlightthickness=0" appeared to do exactly what I expected.
Resulting button with rounded corners
And I used an exact copy of the code posted in the original question (by: Cai Allin,Mar 10, 2022 at 21:21)
My only changes were in the block for the "Rounded button".
First I tested to change the "borderwidth"
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=-1,
)
But this did not result in any visible change.
I then tested to just below the "borderwidth" add:
highlightthickness=0
And this change succeeded in removing the "white border", and it worked regardless whether the settings for the "borderwidth" was "-1" or "0"
I managed to find in someone who made a class for rounded buttons in tkinter that works great. However the issue I have is there is always a white border.
I've tried reading through all of the code and changing all of the colour values but to no avail.
Here is an excerpt of the code working, I've tried to format it as nicely as I could:
from tkinter import Tk, Canvas
class RoundedButton(Canvas):
def __init__(self, master=None, text: str = "", radius=25, btnforeground="#007CEE", btnbackground="#ffffff",
clicked=None, font=("Righteous", 25), *args, **kwargs):
super(RoundedButton, self).__init__(master, *args, **kwargs)
self.config(bg=self.master["bg"])
self.btnbackground = btnbackground
self.btnforeground = btnforeground
self.clicked = clicked
self.radius = radius
self.rect = self.round_rectangle(0, 0, 0, 0, tags="button", radius=radius, fill=btnbackground)
self.text = self.create_text(0, 0, text=text, tags="button", fill=btnforeground, font=font,
justify="center")
self.tag_bind("button", "<ButtonPress>", self.border)
self.tag_bind("button", "<ButtonRelease>", self.border)
self.bind("<Configure>", self.resize)
text_rect = self.bbox(self.text)
if int(self["width"]) < text_rect[2] - text_rect[0]:
self["width"] = (text_rect[2] - text_rect[0]) + 10
if int(self["height"]) < text_rect[3] - text_rect[1]:
self["height"] = (text_rect[3] - text_rect[1]) + 10
def round_rectangle(self, x1, y1, x2, y2, radius=25, update=False,
**kwargs): # if update is False a new rounded rectangle's id will be returned else updates existing rounded rect.
# source: https://stackoverflow.com/a/44100075/15993687
points = [x1 + radius, y1,
x1 + radius, y1,
x2 - radius, y1,
x2 - radius, y1,
x2, y1,
x2, y1 + radius,
x2, y1 + radius,
x2, y2 - radius,
x2, y2 - radius,
x2, y2,
x2 - radius, y2,
x2 - radius, y2,
x1 + radius, y2,
x1 + radius, y2,
x1, y2,
x1, y2 - radius,
x1, y2 - radius,
x1, y1 + radius,
x1, y1 + radius,
x1, y1]
if not update:
return self.create_polygon(points, **kwargs, smooth=True)
else:
self.coords(self.rect, points)
def resize(self, event):
text_bbox = self.bbox(self.text)
if self.radius > event.width or self.radius > event.height:
radius = min((event.width, event.height))
else:
radius = self.radius
width, height = event.width, event.height
if event.width < text_bbox[2] - text_bbox[0]:
width = text_bbox[2] - text_bbox[0] + 30
if event.height < text_bbox[3] - text_bbox[1]:
height = text_bbox[3] - text_bbox[1] + 30
self.round_rectangle(5, 5, width - 5, height - 5, radius, update=True)
bbox = self.bbox(self.rect)
x = ((bbox[2] - bbox[0]) / 2) - ((text_bbox[2] - text_bbox[0]) / 2)
y = ((bbox[3] - bbox[1]) / 2) - ((text_bbox[3] - text_bbox[1]) / 2)
self.moveto(self.text, x, y)
def border(self, event):
if event.type == "4":
self.itemconfig(self.rect, fill="#DE8500")
self.itemconfig(self.text, fill='#ffffff')
if self.clicked is not None:
self.clicked()
else:
self.itemconfig(self.rect, fill=self.btnbackground)
self.itemconfig(self.text, fill=self.btnforeground)
window = Tk()
window.geometry("1440x872")
window.configure(bg="#007CEE")
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=0)
download_button_1.place(
x=409,
y=383,
width=621.0,
height=105.0
)
window.mainloop()
EDIT: Furas' answer works perfect, for anyone interested in using this rounded button class I would reccommend changing the splinesteps to a higher value at self.create_polygon to help with smoothing
return self.create_polygon(points, **kwargs, smooth=True, splinesteps=10000)
On Linux works for me
highlightthickness=0
or set color of background
highlightbackground="#007CEE"
eventually
borderwidth=-1
Doc for Canvas (page effbot.org on archive.org) shows all config options.
Before:
After:
2023.01.28:
Using: Pop!_OS 22.04 LTS //Python 3.10.6// Tcl/Tk V.8.6
"borderwidth=-1" did not seem to work, but "highlightthickness=0" appeared to do exactly what I expected.
Resulting button with rounded corners
And I used an exact copy of the code posted in the original question (by: Cai Allin,Mar 10, 2022 at 21:21)
My only changes were in the block for the "Rounded button".
First I tested to change the "borderwidth"
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=-1,
)
But this did not result in any visible change.
I then tested to just below the "borderwidth" add:
highlightthickness=0
And this change succeeded in removing the "white border", and it worked regardless whether the settings for the "borderwidth" was "-1" or "0"
I am working on creating a drawing program. Presently I can DRAG and DRAW in a rectangle. While outside of the rectangle, I want to create several colours boxes to select different colours and send that colour into this Tkinter function :
win.bind('<B1-Motion>', motion)
The issue is that I am unsure how to do it. When I try to send the "colour" into the motion event, I get an error because I am unsure how to send an additional argument into it.
from graphics import *
import time
win = GraphWin("mouse", 500, 500)
win.master.attributes('-topmost', True)
rect=Rectangle(Point(20,20), Point(200,300))
rect.draw(win)
def motion(event): # how can I enter another argument?
x1, y1 = event.x, event.y
if (x1>20 and x1<200) and (y1>20 and y1<300):
point1 = Point(x1, y1)
point1.setFill("blue") # want to send a value into here
point1.draw(win)
else:
pass
def drawingit():
coord = win.checkMouse()
if coord == None:
print("nothing clicked")
elif (coord.getX()>20 and coord.getX()<200) and (coord.getY()>20 and coord.getY()<300):
win.bind('<B1-Motion>', motion)
else:
point1 = Point(coord.getX(), coord.getY())
point1.setFill("red")
point1.draw(win)
time.sleep(.04)
while True:
drawingit()
win.mainloop()
EDIT : added green colour rectangle
from graphics import *
import time
win = GraphWin("mouse", 500, 500)
win.master.attributes('-topmost', True)
rect=Rectangle(Point(20,20), Point(200,300))
rect.draw(win)
rectorange=Rectangle(Point(20,430), Point(200,460))
rectorange.setFill("green")
rectorange.draw(win)
pick_colour="black"
def motion(event):
x1, y1 = event.x, event.y
if (x1>20 and x1<200) and (y1>20 and y1<300):
point1 = Point(x1, y1)
point1.setFill(pick_colour)
point1.draw(win)
else:
pass
def drawingit():
coord = win.checkMouse()
if coord == None:
print("nothing clicked")
#time.sleep(0.5)
elif (coord.getX()>20 and coord.getX()<200) and (coord.getY()>20 and coord.getY()<300):
win.bind('<B1-Motion>', motion)
elif (coord.getX()>20 and coord.getX()<200) and (coord.getY()>430 and coord.getY()<460):
pick_colour="green"
else:
point1 = Point(coord.getX(), coord.getY())
point1.setFill("black")
point1.draw(win)
time.sleep(.04)
while True:
drawingit()
win.mainloop()
I am new to GUI programming. I want to create something that can load an image and then I can either measure the part of the picture I want and can load it into a cropping method or have to return the area of the crop. Does anyone have suggestions for accomplishing that?
I have a program with PySimpleGUI that can load an image, but I am not sure where to go from there to get the capacity to measure the item.
Using sg.Graph to load your image, and set drag_submits=True and enable_events=True to generate events when mouse click or drag. It will return the coordinate of mouse, then you can get the position of mouse or width/height of selected area.
following code to demo.
import base64
from io import BytesIO
from PIL import Image
import PySimpleGUI as sg
def update(x0, y0, x1, y1):
"""
Update rectangle information
"""
print(repr(x0), repr(y0), repr(x1), repr(y1))
window['-START-'].update(f'Start: ({x0}, {y0})')
window['-STOP-' ].update(f'Start: ({x1}, {y1})')
window['-BOX-' ].update(f'Box: ({abs(x1-x0+1)}, {abs(y1-y0+1)})')
# Generate an image with size (400, 400)
imgdata = base64.b64decode(sg.EMOJI_BASE64_HAPPY_LAUGH)
image = Image.open(BytesIO(imgdata))
im = image.resize((400, 400), resample=Image.CUBIC)
with BytesIO() as output:
im.save(output, format="PNG")
data = output.getvalue()
layout = [
[sg.Graph((400, 400), (0, 0), (400, 400), key='-GRAPH-',
drag_submits=True, enable_events=True, background_color='green')],
[sg.Text("Start: None", key="-START-"),
sg.Text("Stop: None", key="-STOP-"),
sg.Text("Box: None", key="-BOX-")],
]
window = sg.Window("Measure", layout, finalize=True)
graph = window['-GRAPH-']
graph.draw_image(data=data, location=(0, 400))
x0, y0 = None, None
x1, y1 = None, None
colors = ['blue', 'white']
index = False
figure = None
while True:
event, values = window.read(timeout=100)
if event == sg.WINDOW_CLOSED:
break
elif event in ('-GRAPH-', '-GRAPH-+UP'):
if (x0, y0) == (None, None):
x0, y0 = values['-GRAPH-']
x1, y1 = values['-GRAPH-']
update(x0, y0, x1, y1)
if event == '-GRAPH-+UP':
x0, y0 = None, None
if figure:
graph.delete_figure(figure)
if None not in (x0, y0, x1, y1):
figure = graph.draw_rectangle((x0, y0), (x1, y1), line_color=colors[index])
index = not index
window.close()