I followed a few tutorials and I am trying to implement a clean object oriented code for python gui. The idea of my project is opening an image and drawing circles on it with mouse click.
There are 2 issues:
1)
In the code below, the canvas does not render the image.the image should be taken from the user
In java there is a repaint function that is called by VM so that the contents of the frame can be updated. I couldn't find something in python (No, I am not willing to try adding timer function to redraw every second.)
2)
Besides HELLO is not printed even I press f key. The keylistener is also not working
I have done GUI with Java before but Python code looks very dirty comparing Java.
I would be grateful if you can help.
from tkinter import *
from PIL import Image, ImageTk
from tkinter import Tk, Canvas, Frame, BOTH
from tkinter import filedialog
class Example(Frame):
def __init__(self, container):
super().__init__()
self.container = container
self.canvas = None
self.initUI()
def initUI(self):
fname=filedialog.askopenfilename(title='"pen')
self.canvas = Canvas(self.container)
self.canvas.pack(anchor='nw', fill='both', expand=1)
self.canvas.focus_set()
self.canvas.bind("<ButtonRelease-1>", self.mouseReleased)
self.canvas.bind("<Key>", self.pressedkey)
image = Image.open(fname)
image = image.resize((400, 400))
image = ImageTk.PhotoImage(image)
image_id=self.canvas.create_image(0, 0, image=image, anchor='nw')
def mouseReleased(self, event):
self.canvas.create_oval(event.x-10, event.y-10, event.x+10, event.y+10, width=2, fill='blue')
def pressedkey(self,event):
pressedkey=str(repr(event.char))
print(pressedkey,type(pressedkey))
if pressedkey.__eq__("f"):
print("HELLO")
def main():
root = Tk()
ex = Example(root)
root.geometry("400x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()
Related
I would like to do scrolling in my photo editing program. But something is not working for me. The code was in theory based on one of the stackoverflow entries and I can't identify the problem. I have tried to remake it in various ways. _inbound_to_mousewheel prints nicely and so does _un_to_mousewheel. The one responsible directly for scrolling doesn't even print.
Is it possible to do a zoom in such a project, and if not, does it need to be rebuilt?
Main window file:
import sys
import tkinter as tk
from tkinter import filedialog, Frame
from PIL import ImageTk, Image
from gui.menu_bar import MenuBar
from gui.workspace import Workspace
def close_all_windows():
sys.exit()
class MainForm(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("myPhotoEditor by Sebastian KÄ…kolewski")
self.geometry("1000x850")
self.protocol("WM_DELETE_WINDOW", close_all_windows)
self.menu_bar = MenuBar(self)
self.config(menu=self.menu_bar)
# region Workspace
self.workspace_frame = Frame(self)
self.workspace_frame.pack(expand=True, fill="both", side="left")
self.workspace = Workspace(self.workspace_frame)
self.workspace.pack(fill="both", expand=True)
file_url = filedialog.askopenfilename()
img = Image.open(file_url)
self.workspace.image = ImageTk.PhotoImage(img)
self.workspace.create_image(0, 0, image=self.workspace.image, anchor='nw')
self.workspace_frame.bind('<Enter>', self._bound_to_mousewheel)
self.workspace_frame.bind('<Leave>', self._unbound_to_mousewheel)
# endregion
def _bound_to_mousewheel(self, event):
print("_bound_to_mousewheel")
self.workspace_frame.bind_all("<MouseWheel>", self._on_mousewheel)
def _unbound_to_mousewheel(self, event):
print("_unbound_to_mousewheel")
self.workspace_frame.unbind_all("<MouseWheel>")
def _on_mousewheel(self, event):
print("_on_mousewheel")
self.workspace_frame.yview_scroll(int(-1 * (event.delta / 120)), "units")
Workspace file:
from tkinter import Canvas, Scrollbar
class Workspace(Canvas):
def __init__(self, master=None):
Canvas.__init__(self, master)
self.master = master
workspace_hbar = Scrollbar(self.master, orient="horizontal")
workspace_hbar.pack(side="bottom", fill="x")
workspace_hbar.config(command=self.xview)
workspace_vbar = Scrollbar(self.master, orient="vertical")
workspace_vbar.pack(side="right", fill="y")
workspace_vbar.config(command=self.yview)
self.config(xscrollcommand=workspace_hbar.set, yscrollcommand=workspace_vbar.set)
I am trying to display a QR Code in a tkinter GUI, however when I execute this code:
import tkinter as tk
from PIL import Image,ImageTk
import pyqrcode
from tkinter.font import Font
import random
root=tk.Tk()
root.title("QR Lottery")
root.config(bg="white")
# Defining Fonts
TitleFont = Font(family="HEX:gon Staggered 2", size="48")
def generateQR():
num=random.randint(1,2)
if num==1:
QRCode=pyqrcode.create("You Win!")
QRCode.png("QRCode.png",scale=8)
img = Image.open('QRCode.png')
QRCodeImg = ImageTk.PhotoImage(img)
QRCodeLabel=tk.Label(image=QRCodeImg)
QRCodeLabel.grid(row=2,column=1)
else:
QRCode=pyqrcode.create("You Lose!")
QRCode.png("QRCode.png",scale=8)
img = Image.open('QRCode.png')
QRCodeImg = ImageTk.PhotoImage(img)
QRCodeLabel=tk.Label(image=QRCodeImg)
QRCodeLabel.grid(row=2,column=1)
#Labels
TitleLabel=tk.Label(text="qr lottery",bg="white",font=TitleFont)
TitleLabel.grid(row=1,column=1,columnspan=5)
ButtonQR=tk.Button(text="Generate!",bg="white",command=generateQR)
ButtonQR.grid(row=3,column=1)
root.mainloop()
The Image Label produced is a blank square. I am unsure of why this is, as I left the background color blank.
Question: The Image Label produced is a blank square. I am unsure of why this is
A:You must keep a reference to the image object in your Python program, by attaching it to another object.
Use the following:
Define your own widget QRCodeLabel by inherit from tk.Label.
Init only with parameter parent
class QRCodeLabel(tk.Label):
def __init__(self, parent, qr_data):
super().__init__(parent)
print('QRCodeLabel("{}")'.format(qr_data))
Create your QRCode with the passed qr_data and
save as PNG file.
qrcode = pyqrcode.create(qr_data)
tmp_png_file = "QRCode.png"
qrcode.png(tmp_png_file, scale=8)
Create a image object from the PNG file.
Tkinter can handle PNG image files by its own, no PIL needed.
NOTE: You have to use self.image to prevent garbage collection!
self.image = tk.PhotoImage(file=tmp_png_file)
Configure this Label with the self.image
self.configure(image=self.image)
Usage:
class App(tk.Tk):
def __init__(self):
super().__init__()
buttonQR = tk.Button(text="Generate!", bg="white", command=self.generateQR)
buttonQR.grid(row=2, column=0)
self.qr_label = None
def generateQR(self):
if self.qr_label:
self.qr_label.destroy()
self.qr_label = QRCodeLabel(self, random.choice(["You Win!", "You Lose!"]))
self.qr_label.grid(row=1, column=0)
if __name__ == "__main__":
App().mainloop()
Tested with Python: 3.5
I'm a beginner trying to use tkinter to create a GUI. I've adapted code from other sources for my own use.
At the moment I'm trying to display an image along with a button.
However, when running the code, only the image displays no matter where I move the button, the button isn't displayed.
Would be grateful for any help.
Additional functionality:
I'm looking to implement a function so that I can move the image around using coordinates, also a function that allows me to use .jpg instead of .png.
Thanks in advance!
Code:
from tkinter import *
from PIL import Image, ImageTk
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("WindowName")
self.pack(fill = BOTH, expand = 1)
quitButton = Button(self, text = "quit", command=self.client_exit)
quitButton.place(x=400,y=400)
self.showImg()
def client_exit(self):
exit() # Or another function
def showImg(self):
self.grid(row=0)
self.columnconfigure(0,weight=1)
self.rowconfigure(0,weight=1)
self.original = Image.open('wire.png')
resized = self.original.resize((200, 200),Image.ANTIALIAS)
self.image = ImageTk.PhotoImage(resized)
self.display = Label(self, image = self.image)
self.display.grid(row=0)
root = Tk()
root.geometry("600x600")
app = Window(root)
root.mainloop()
I am trying to develop a Python Tkinter widget that opens a window displaying a photo and allows the user to scroll through the photos using a scroll bar. For context, the idea is to be able to scroll through a timer-series of photographs.
So far I've been able to make a Tkinter canvas displaying an image, and a Tkinter "Scale" slider, but I am having trouble combining them to meet my goal. The result of the below code is an empty canvas window and a separate slider. The slider works and prints its position when moved, but no photo ever loads. I was hoping that when the bar was moved to position 3, photo 3 would load.
Any idea what I'm missing?
import Tkinter as tk
from PIL import ImageTk, Image
from Tkinter import *
class ImageCanvas(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.canvas = Canvas(self, width=720, height=480, bd=0)
self.canvas.grid(row=0, column=0, sticky='nsew', padx=4, pady=4)
self.root = tk.Tk()
self._job = NONE
self.slider = tk.Scale(self.root, from_=0, to=3, orient = "horizontal", command=self.updateValue)
self.slider.pack()
self.root.mainloop()
def updateValue(self, event):
if self._job:
self.root.after_cancel(self._job)
self._job = self.root.after(500, self.result)
def result(self):
self._job=None
print self.slider.get()
returnedValue = self.slider.get()
class ImgTk(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.main = ImageCanvas(self)
self.main.grid(row=0, column=0, sticky='nsew')
self.c = self.main.canvas
self.currentImage = {}
self.load_imgfile(images[ImageCanvas.returnedValue()])
def load_imgfile(self, filename):
self.img = Image.open(filename)
self.currentImage['data'] = self.img
self.photo = ImageTk.PhotoImage(self.img)
self.c.xview_moveto(0)
self.c.yview_moveto(0)
self.c.create_image(0, 0, image=self.photo, anchor='nw', tags='img')
self.c.config(scrollregion=self.c.bbox('all'))
self.currentImage['photo'] = self.photo
images = ['/Users/Evan/Documents/Temp/4744.png', '/Users/Evan/Documents/Temp/4750.png', '/Users/Evan/Documents/Temp/4757.png']
app = ImgTk()
A couple suggestions may get you on the right track. Move the self.root.mainloop() out of the ImageCanvas class and put it at the end, after app = ImgTk(), as simply mainloop(), so it only get's called ones per instance of your app.
Also, ImageCanvas class doesn't have a method called returnedValue, and the result method doesn't return any value. So, add return returnedValue to the result method. Then ImageCanvas.returnedValue() would need to be ImageCanvas.result(), or you could just say self.main.result().
After making these changes, the first image displays, more work will need to be done to get the other images to load.
I want to use Tkinter to display all the pictures in a specific directory, so I firstly code to show all the pictures from a given list
The code is:
import os
from Tkinter import *
from PIL import Image, ImageTk
class Application(Frame):
def add_pic_panel(self, pic):
img = ImageTk.PhotoImage(Image.open(pic))
label = Label(root, image = img)
print label
return label
def create_gui(self):
pics = ['1.jpg', '2.jpg']
for pic in pics:
self.add_pic_panel(pic)
pass
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.create_gui()
root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
Environment: Mac OS 10.9, Python 2.7.5
How could I display all the pictures in the list?
The code does not pack the label.
Should keep the reference for the image.
def add_pic_panel(self, pic):
img = ImageTk.PhotoImage(Image.open(pic))
label = Label(self.master, image=img)
label.img = img # to keep the reference for the image.
label.pack() # <--- pack
return label
BTW, add_pic_panel use root directly. It would be better to use self.master.
root.destroy() at the last line cause TclError when closing the window. Remove the line.