Tkinter image not adding to text widget - python

I am trying to make text widget that get images from reddit then displaying it on a text widget, but for some reason, with no error, the image is not displaying on the widget.
This is the part of my code that get the image from reddit and adding it on the widget.
subreddit = reddit.subreddit("MinecraftMemes")
filtered = [x for x in subreddit.top() if not x.stickied and not x.is_self]
url = filtered[random.randint(0, len(filtered) - 1)].url
url_type = self.get_url_type(url)
urllib.request.urlretrieve(url,f"minecraft{url_type}")
image = Image.open(f"minecraft{url_type}")
image.save('minecraft.png')
img = tkinter.PhotoImage(file=r"minecraft.png")
self.text_widget.image_create(END,image=img)
print("activated")
The activated is printed, the minecraft.png is seen on file explorer, so it is the part of the code with tkinter that is not working

I believe the issue is that the image is an object and it gets discarded when the code executes, so you might want to do self.img.

Related

TypeError: 'PngImageFile' object is not callable

I am trying to put images into a scrollable frame. These images are stored locally which i am successful in retiring corresponding to their id. However the issue I am running into is that i cant work out how to resize them properly so they fit on the canvas. I am coding in Python 3.10 and using tkinter to create the GUI.
def open_image(location):
photo = Image.open('D:\ShopifyApp\designs\\'+ str(location))
resized = photo((10,5), Image.Resampling.LANCZOS)
image = ImageTk.PhotoImage(resized)
return image
This is the code that fetches the image, location is the name of the file, all the images are JPGs (I dont know if thats the issue).
for i in range(len(orderDF)):
Label(myframe, text = str(orderDF.loc[i]['orderID'])).pack()
prodImg = find_pic(orderDF.loc[i]['productID'])
img = open_image(prodImg)
Label(myframe,image=img).pack()
This is my loop which grabs the image location and sends it to open_image to later be put in label.

yview_moveto going to incorrect position when used after updating ScrolledText contents

I am making a software that involves making a text editor that the contents are being updated very often (every time the user types something it syncs the values in the text with something else)
The way that I do this is by saving the cursor position and scrollbar position and text (it is a ScrolledText widget)
self.scroll_data = self.text.yview()
text = self.text.get("1.0", tkinter.END)[:-1]
cursor = self.text.index(tkinter.INSERT)
After putting the text through the function that syncs it, I now have the string that should be in the ScrolledText widget (self.text)
Now That I have the text That should be in the widget I do this to put the text in and have it look to the user like nothing happened by replacing the text and resetting the cursor position and scroll bar position
self.text.delete("1.0", tkinter.END)
self.text.insert("1.0", self.mod.get_text()) # self.mod.get_text() is the text that we want
self.text.mark_set("insert", str(cursor))
self.text.yview_moveto(self.scroll_data[0])
I then call self.root.update() because I want the window the show the changes.
This is where I am having the problem, for some reason, because I am moving the scrollbar after resetting the text but not updating, it causes a weird bug where the scrollbar inches up whenever I type something. This doesn't happen every single time I tried it in the past but even old version are having this issue for me right now.
I way I found that somewhat fixes the issue is to call self.root.update() on the line before self.text.yview_moveto(self.scroll_data[0]) but that causes a visual glitch where the text jumps to the top for a short period of time every time you type a character.
Because it goes to the correct scrolling position when I do that it leads me to believe that it is a problem with calling yview_moveto before updating the screen after deleting and setting text.
This script is an example of the bug in action:
import tkinter
import tkinter.scrolledtext
root = tkinter.Tk()
x = tkinter.scrolledtext.ScrolledText(root)
x.pack()
last_text = ""
while True:
text = x.get("1.0", tkinter.END)[:-1]
changed = text != last_text
if changed:
text = "a" + text
scroll_data = x.yview()
cursor = x.index(tkinter.INSERT)
x.delete("1.0", tkinter.END)
x.insert("1.0", text)
x.mark_set("insert", cursor)
x.yview_moveto(scroll_data[0])
last_text = text
root.update()
If anyone knows how to solve this issue I would greatly appreciate if you would share your solution with me so I can ensure a smooth user experience for anyone using my tool
(this is a link to the github repo with my project https://github.com/hippolippo/Unity-Mod-Maker)
EDIT: I found out that the reason this happens is because some of the lines of text get automatically pushed to the next line because they are too long to fit on the screen. I still don't have a solution however

Why does the search image in my code doesn't work?

This is my code:
import pyautogui
images = ['colordonkergrijsDCphrasev2.png'] #the image I want it to find
while True:
for image in images: #search for the image in images
pos = pyautogui.locateOnScreen(image, region=(740,870, 50, 20)) #search on the screen for the image
if pos is not None: # this checks that the image was found
pyautogui.click(pos) # click the position of the image
I want that my code clicks on a special region when he is seeing that image.
But my code doesn't do that, my code clicks every time also when the image isn't there. The image I'm using is very similar as the background. But I added confidence = 1 and it still doesn't work
Does someone know how to fix it?
I use Python 3.9.4 64-bit.
I already read the docs but there isn't anything in there what can help me.
If you want to docs here it is: https://pyautogui.readthedocs.io/en/latest/screenshot.html

How to generate buttons with different images [duplicate]

This question already has an answer here:
How to add an Image to a widget? Why is the image not displayed?
(1 answer)
Closed 4 years ago.
So I'm writing basic stuff in python with tkinter and PIL and the problem here is that when I run the program, only the last button show the image of the item I asked him to show.
So my program was expected to extract name of items from lines containing the name of a game Champion in a txt document.
Each line in the document looks like "ItemName/stat1/stat2/stat3/ChampionName".
The code was then supposed to create buttons with a picture of the item on it(I made sure to name the pngs and the item name in the .txt the same and to put everything in the same folder) but in the end, only the last button had an image on it.
What I tried :
I tried to reduce the number of elements in the txt, it didn't work
I then thought that the problem was that the variable icon being updated, the image shown would disappear. So I tried to make an array but it didn't work either because what I put in isn't an int value, I know it's about the 'i' but I don't know if I can put something else appropriate.
My first attempt :
from PIL import Image, ImageTk
import tkinter as tk
itemwindo = tk.Tk()
itemwindo.title("Items")
data = open("Ressource.txt","r")
for line in data:
if 'Vi' in line:
(a,b,c,d,e) = line.split("/")
icon = ImageTk.PhotoImage(Image.open(a + '.png'))
bt = tk.Button(itemwindo,image=icon)
bt.pack()
itemwindo.mainloop()
And my second with arrays :
data = open("Ressource.txt","r")
imglist = arr.array('i')
for line in data:
if 'Vi' in line:
(a,b,c,d,e) = line.split("/")
icon = ImageTk.PhotoImage(Image.open(a + '.png'))
imglist.extend([icon])
p = len(imglist)
bt = tk.Button(itemwindo,image=imglist[p])
bt.pack()
itemwindo.mainloop()
I would like each button to display the picture of the affiliated item on it.
In the loop that cretes the buttons you use the same name for
every image. This creates a new object every iteration and the
previous buttons can no longer find a reference to the previous image.
To fix this you can assign the image attribute of the button
at creation and then it does no longer make any difference if you reuse the icon or bt name. Study the example below:
import tkinter as tk
itemwindo = tk.Tk()
file_list = ['beer.png', 'test.gif']
for file in file_list:
icon = tk.PhotoImage(file=file)
bt = tk.Button(itemwindo, image=icon)
bt.pack()
bt.image = icon # Save reference to icon in button
itemwindo.mainloop()

Printing main window in PyQt

I need to be able to save the main window of a pyqt app in a PS or similar file format so that I can send it to a printer. I would just make a built in screen shot function but my main window exceeds the size of my screen. Anyone know of a way to capture the window in it's entirety or is there a prebuilt class that could do this?
QPixmap has the static method grabWidget.
Pointing this method at your window will give you a pixmap that you can save to a file or use for printing.
If calling from inside your main window class:
sshot = QPixmap.grabWidget(self)
sshot.save('sshot.png')
QPixmap.grabWiget has been deprecated. We can instead use QWidget.grab() function instead to capture window. However, it only captures the currently visible parts of the screen which can be a problem when you have a window with a scroll area. So the only method/hack that worked for me was to use ScrollArea's page step functionality paired with widget grab.
# Get total pages in window
page_count = self.scrollArea.verticalScrollBar().maximum() / self.scrollArea.verticalScrollBar().pageStep()
image_list = []
# iterate through each page step
for i in range(int(round(page_count)) + 1):
step = self.scrollArea.verticalScrollBar().pageStep() * i
self.scrollArea.verticalScrollBar().setValue(step)
# capture and save each image
self.scrollArea.grab().save(f"page - {i}.jpg", quality=100)
# convert all images to Pillow Image() to later convert to pdf
image_list.append(Image.open(f"report_page - {i}.jpg"))
# save as pdf file
pdf_file_name = f'pdf_file.pdf'
image_list[0].save(pdf_file_name, "PDF", resolution=100.0, save_all=True, append_images=image_list[1:])
# delete images if not neccessary
for i in range(len(image_list)):
os.unlink(f"page - {i}.jpg")
P.s. Please let me know if there a more elegant solution to this problem

Categories