Python Drawing Portion of Image When Mouse Hover - python

My question relates to Python GTK
I have an image -a JPG - which I draw onto a drawing area. I want to reveal a portion of the image -say a 10pix by 10 px square -only where the mouse pointer is currently at. Everything 10 x 10 px square away from the mouse should hidden i.e. black.
I'm am new to PyGtk please can anyone help?
Thanks

#!/usr/bin/python
import os
import sys
import gtk
MASK_COLOR = 0x000000
def composite(source, start_x=345, start_y=345):
width = 50
height = 50
alpha = 255
dest = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8 ,800,800)
dest.fill(MASK_COLOR)
source.composite(dest,
start_x,
start_y,
width,
height,
0,
0,
1,
1,
gtk.gdk.INTERP_NEAREST,
alpha)
return dest
def it_moved(widget, event, window, masked, original):
r = window.get_display().get_window_at_pointer()
masked.set_from_pixbuf(composite(original.get_pixbuf(), r[1], r[2]))
return True
if __name__ == '__main__':
window = gtk.Window()
eb = gtk.EventBox()
original = gtk.Image()
original.set_from_file(sys.argv[1])
masked = gtk.Image()
masked.set_from_pixbuf(composite(original.get_pixbuf()))
eb.add(masked)
eb.set_property('events', gtk.gdk.POINTER_MOTION_MASK)
eb.connect('motion_notify_event', it_moved, window, masked, original)
window.add(eb)
window.set_size_request(800,800)
window.show_all()
gtk.main()
This should do something like you describe. I chose to show a 50x50 area since yours was kinda small to see under the pointer. I didn't hide that either.

Related

Kivy. Python. It is possible to resize the main window such as the ratio between width and height remains constant during the process?

I try to create a video player in kivy and I need that this player to maintain its main window's initial proportions between width and height when the user performs the resize event over it.
I tried this piece of code:
from kivy.core.window import Window
#These are the initial values and I need to maintain this ratio, w/h, constant all the way as long as the resize event is kicked on by my mouse.
w = 350
h = round(w/16*9) + 60
Window.size = (w,h)
def reSize(*args):
# print(f'{args[1]} ;{args[2]}')
w = args[1]
h = w/16*9 + 60
Window.size = (w,h)
return True
Window.bind(on_resize = reSize)
Window.minimum_height = round(w/16*9) + 60
Window.minimum_width = w
and the result is hideous.
A huge window appears filling half of my screen and is completely inoperable.
I tried to find an event like onSizeChanged, like in matplot for example, but there isn't one in kivy framework.
Any suggestions or hints, please?

Image not getting drawn on tkinter canvas

I would like to display a knapsack image on green canvas. The height and width of that canvas is 250X250 pixels.
And the size of the image is 260X280 pixels.
When I try to execute below code, I get the output as shown in screenshot above 1. The location of the code file and image file is same.
from tkinter.font import BOLD
from tkinter import *
import tkinter
from PIL import Image, ImageTk
root = Tk()
def draw():
global canvas
root.geometry('1080x720')
root.state('zoomed')
canvas = Canvas(root,bg='black',highlightthickness=0)
canvas.pack(fill=tkinter.BOTH, expand=True)
sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
canvas.create_line(int(sw*0.0000),int(sh*0.1736),int(sw*0.6510),int(sh*0.1736),fill='white')
canvas.create_line(int(sw*0.6510),int(sh*0.0000),int(sw*0.6510),int(sh*1.0000),fill='white')
canvas.create_line(int(sw*0.6510),int(sh*0.1157),int(sw*1.0000),int(sh*0.1157),fill='white')
canvas.create_line(int(sw*0.6510),int(sh*0.8101),int(sw*1.0000),int(sh*0.8101),fill='white')
UI_frame1 = Frame(canvas,bg='black',width=int(sw*0.6510),height=int(sh*0.1580))
canvas.create_window(0,0, anchor=NW,window=UI_frame1)
N = Label(UI_frame1,text='N',bg ='black',fg='white',font=(12))
N.grid(row=0,column=0, padx=139,pady=22)
weights = Label(UI_frame1,text='Weights',bg ='black',fg='white',font=(12))
weights.grid(row=0,column=1,padx=140,pady=22)
val = Label(UI_frame1,text='Values',bg ='black',fg='white',font=(12))
val.grid(row=0,column=2,padx=140,pady=22)
n = Entry(UI_frame1,bg='white',width=4,font=(12))
n.grid(row=1,column=0,padx=50,pady=17)
value_arr = Entry(UI_frame1,bg='white',font=(12))
value_arr.grid(row=1,column=1,padx=50,pady=17)
weight_arr = Entry(UI_frame1,bg='white',font=(12))
weight_arr.grid(row=1,column=2,padx=50,pady=17)
Label(canvas,text='i',bg='black',fg='white',font=(14)).place(x=150,y=185)
i = Label(canvas,text=" i ",bg='white',font=(12)).place(x=175,y=185)
Label(canvas,text='j',bg='black',fg='white',font=(14)).place(x=525,y=185)
j = Label(canvas,text=" j ",bg='white',font=(12)).place(x=550,y=185)
table = Canvas(canvas,bg='red',width=600,height=450)
table.place(x=75,y=300)
w = int(600/8)
h = int(450/5)
x=0
y=0
for r in range(5):
for c in range(8):
table.create_rectangle(x,y,x+w,y+h)
x+=w
y+=h
x=0
UI_frame2 = Frame(canvas,bg='blue',width=250,height=250)
canvas.create_window(835,630, anchor=CENTER,window=UI_frame2)
image_c = Canvas(UI_frame2,bg='green',highlightthickness=0,width=250,height=250)
image_c.grid(row=0,column=0,padx=0,pady=0)
photo = ImageTk.PhotoImage(file ='knapsack.png')
image_c.create_image(835,630,image=photo,anchor=NW)
draw()
root.mainloop()
I would like to cover the entire green canvas with single image of knapsack. I am not any error while running the GUI. Anyone could help me out, I'll be really thankful.
There are two problems:
First:
You display in position (835,630) but canvas has visible only (250, 250) - (top left corner is (0,0)) - so photo is in place which you can see.
Second:
There is bug in PhotoImage() which removes image from memory when it is assigned to local variable. One of solution is to use global photo to assign it to global variable.
def draw():
global canvas
global photo # use global variable
#... code ...
photo = ImageTk.PhotoImage(file='knapsack.png')
image_c.create_image(0, 0,image=photo, anchor=NW) # position (0,0)
Doc (on archive.org): PhotoImage - see Note at the botton of doc.
Other problem can be that image has big (transparent) margins around object and it may show object in differnt place then you may expect.
Screenshot shows photo in position (0,0) but object is in center of green canvas.

Image in Button tkinter

I am having a problem in making a login image to a button. I have succeeded in making the image with a transparent background, but I can't succeed to make the button with transparent background.
I attached a screenshot that shows what I mean. The upper 'login' is a image (with transparent background), the lower is Login button but there is a white background around it. I want to make a button with transparent background.
self.login_image = Image.open('images/LoginButton.png')
self.login_image = ImageTk.PhotoImage(self.login_image)
self.main_screen_canvas.create_image(700, 300, image=self.login_image)
self.login_button = Button(self.main_screen_canvas, borderwidth=0, image=self.login_image)
self.login_button.place(x=300,y=400)
What should I do?
BackgroundImage
LoginButtonImage
Here's how to do what I was suggesting in the comment which uses the technique shown in another answer of mine to simulate a tkinter Button on a Canvas that has a transparent image placed on it (instead of text).
One issue I ran into was that fact that your 2421 × 1210 pixel background image was larger than my screen. To deal with it I added a fitrect() helper function to determine a new smaller size for it that would fit. I wrote it a long time ago, but have found it handy to have around many times (like now). Note that in the code ll and ur refer to the lower-left and upper-right corners of the rectangles involved.
Here's the resulting code:
from PIL import Image, ImageTk
import tkinter as tk
class CanvasButton:
""" Create left mouse button clickable canvas image object.
The x, y coordinates are relative to the top-left corner of the canvas.
"""
flash_delay = 100 # Milliseconds.
def __init__(self, canvas, x, y, image_source, command, state=tk.NORMAL):
self.canvas = canvas
if isinstance(image_source, str):
self.btn_image = tk.PhotoImage(file=image_source)
else:
self.btn_image = image_source
self.canvas_btn_img_obj = canvas.create_image(x, y, anchor='nw', state=state,
image=self.btn_image)
canvas.tag_bind(self.canvas_btn_img_obj, "<ButtonRelease-1>",
lambda event: (self.flash(), command()))
def flash(self):
self.set_state(tk.HIDDEN)
self.canvas.after(self.flash_delay, self.set_state, tk.NORMAL)
def set_state(self, state):
""" Change canvas button image's state.
Normally, image objects are created in state tk.NORMAL. Use value
tk.DISABLED to make it unresponsive to the mouse, or use tk.HIDDEN to
make it invisible.
"""
self.canvas.itemconfigure(self.canvas_btn_img_obj, state=state)
def fitrect(r1_ll_x, r1_ll_y, r1_ur_x, r1_ur_y, r2_ll_x, r2_ll_y, r2_ur_x, r2_ur_y):
""" Find the largest rectangle that will fit within rectangle r2 that has
rectangle r1's aspect ratio.
Note: Either the width or height of the resulting rect will be
identical to the corresponding dimension of rect r2.
"""
# Calculate aspect ratios of rects r1 and r2.
deltax1, deltay1 = (r1_ur_x - r1_ll_x), (r1_ur_y - r1_ll_y)
deltax2, deltay2 = (r2_ur_x - r2_ll_x), (r2_ur_y - r2_ll_y)
aspect1, aspect2 = (deltay1 / deltax1), (deltay2 / deltax2)
# Compute size of resulting rect depending on which aspect ratio is bigger.
if aspect1 > aspect2:
result_ll_y, result_ur_y = r2_ll_y, r2_ur_y
delta = deltay2 / aspect1
result_ll_x = r2_ll_x + (deltax2 - delta) / 2.0
result_ur_x = result_ll_x + delta
else:
result_ll_x, result_ur_x = r2_ll_x, r2_ur_x
delta = deltax2 * aspect1
result_ll_y = r2_ll_y + (deltay2 - delta) / 2.0
result_ur_y = result_ll_y + delta
return result_ll_x, result_ll_y, result_ur_x, result_ur_y
def btn_clicked():
""" Prints to console a message every time the button is clicked """
print("Button Clicked")
background_image_path = 'background_image.jpg'
button_image_path = 'button_image.png'
root = tk.Tk()
root.update_idletasks()
background_img = Image.open(background_image_path) # Must use PIL for JPG images.
scrnwidth, scrnheight = root.winfo_screenwidth(), root.winfo_screenheight()
bgrdwidth, bgrdheight = background_img.size
border_width, border_height = 20, 20 # Allow room for window's decorations.
# Determine a background image size that will fit on screen with a border.
bgr_ll_x, bgr_ll_y, bgr_ur_x, bgr_ur_y = fitrect(
0, 0, bgrdwidth, bgrdheight,
0, 0, scrnwidth-border_width, scrnheight-border_height)
bgr_width, bgr_height = int(bgr_ur_x-bgr_ll_x), int(bgr_ur_y-bgr_ll_y)
# Resize background image to calculated size.
background_img = ImageTk.PhotoImage(background_img.resize((bgr_width, bgr_height)))
# Create Canvas same size as fitted background image.
canvas = tk.Canvas(root, bd=0, highlightthickness=0, width=bgr_width, height=bgr_height)
canvas.pack(fill=tk.BOTH)
# Put background image on Canvas.
background = canvas.create_image(0, 0, anchor='nw', image=background_img)
# Put CanvasButton on Canvas centered at the bottom.
button_img = tk.PhotoImage(file=button_image_path)
btn_x, btn_y = (bgr_width/2), (bgr_height-button_img.height())
canvas_btn1 = CanvasButton(canvas, btn_x, btn_y, button_img, btn_clicked)
root.mainloop()
And here's the result of running it:

Using Pyglet to scale gif to screen

Anyone can bring some clarity to my code as to why when I attempt to scale my gif to full screen half the screen is white while the other is the gif(animation)? This is using the Pyglet python module.
Here's my code along with an image of the issue:
'Load animation'
animation = pyglet.image.load_animation('Goober#13427G.gif')
animSprite = pyglet.sprite.Sprite(animation)
# 'Scale image to screen *harcoded*'
# animSprite.scale_x = 3.2
# animSprite.scale_y = 1.71
' Get display and create a fullscreen window while scaling gif to screen'
display = pyglet.canvas.Display()
screen = display.get_screens()
H_ratio = max(animSprite.height, screen[1].height) / min(animSprite.height, screen[1].height)
W_ratio = max(animSprite.width, screen[1].width) / min(animSprite.width, screen[1].width)
animSprite.scale = min(H_ratio, W_ratio)
window = pyglet.window.Window(width=screen[1].width, height=screen[1].height, fullscreen=True, screen=screen[1])
r, g, b, alpha = 1, 1, 1, .5
pyglet.gl.glClearColor(r, g, b, alpha)
#window.event
def on_draw():
window.clear()
animSprite.draw()
pyglet.app.run()
```[Gif with second half of screen to the right is white][1]
[1]: https://i.stack.imgur.com/JsbJy.jpg
Try scaling each axis.
animSprite.scale_x = W_ratio
animSprite.scale_y = H_ratio

PyGame - Getting the size of a loaded image

Hello, even though you might think there was a similar question, mine is pretty different than this.
I am trying to load an image from a directory, and set my screen size (automatically) to the size of the image being loaded as "background".
import pygame
import sys
from pygame.locals import *
image_resources = "C:/Users/user/Desktop/Pygame App/image_resources/"
class load:
def image(self, image):
self.image = image
return (image_resources + image)
def texture(self, texture):
self.texture = texture
return (image_resources + texture)
bg = load().image("bg_solid_black.jpg")
pygame.init()
#screen = pygame.display.set_mode((width,height),0,32)
#background = pygame.image.load(bg).convert()
#width = background.get_width()
#height = background.get_height()
The image that I loaded with my "load()" class is set to the variable "bg" and I want to use the size of whatever I load as "bg" to determine the size of the window. If you try to move
background = pygame.image.load(bg).convert()
width = background.get_width()
height = background.get_height()
On top of this:
screen = pygame.display.set_mode((width,height),0,32)
PyGame returns an error, in which it states that the display mode is not set. If I do it like this:
screen = pygame.display.set_mode((width,height),0,32)
background = pygame.image.load(bg).convert()
width = background.get_width()
height = background.get_height()
of course, this is not true, since variables "width" and "height" are not defined for the use of "pygame.display.set_mode()".
I can not seem to figure this out, I though of solving through an OO manner, but I just can not seem to figure it out. Any help?
Thanks :)
Before you use convert() on any surface, screen has to be initialized with set_mode().
You can load image and get its size before set_mode() but convert() has to be used after you initialize the display, like so:
import pygame
pygame.init()
image = pygame.image.load("file_to_load.jpg")
print(image.get_rect().size) # you can get size
screen = pygame.display.set_mode(image.get_rect().size, 0, 32)
image = image.convert() # now you can convert
The code I use is this:
import pygame
import os
import random
WIDTH = 750
HEIGHT = 600
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
#Image Load
BG = pygame.image.load(os.path.join("assets", "background_space.png"))

Categories