This question already has an answer here:
Create image in button
(1 answer)
Closed 3 years ago.
For the buttons, I want to change the "text" to be "images"
e.g picture of a eraser instead of text saying eraser.
Here is the Section of Code:
def __init__(self):
self.root = Tk()
self.choose_size_button = Scale(self.root, from_=1, to=15, orient=HORIZONTAL)
self.choose_size_button.grid(row=0, column=1)
self.draw_button = Button(self.root, text='Draw', command=self.use_draw)
self.draw_button.grid(row=0, column=2)
self.color_button = Button(self.root, text='Colour', command=self.choose_color)
self.color_button.grid(row=0, column=3)
self.eraser_button = Button(self.root, text='Eraser', command=self.use_eraser)
self.eraser_button.grid(row=0, column=4)
self.c = Canvas(self.root, bg='white', width=650, height=600)
self.c.grid(row=1, columnspan=5)
self.setup()
self.root.mainloop()
You should use the tinkter to perform your task. You can pass image argument to the button.
For example:
import Tkinter as tk
class View(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
self.image = tk.PhotoImage(file="anyfile.gif")
b = tk.Button(self, text=" ", image=self.image)
b.pack(side="top")
if __name__ == "__main__":
root = tk.Tk()
view = View(root)
view.pack(side="top", fill="both", expand=True)
root.mainloop()
You can use image argument of Button in tkinter.
For example; see this snippet:-
from tkinter import *
from PIL import ImageTk, Image
root = Tk()
img = ImageTk.PhotoImage(Image.open('your_image_path'))
b = Button(root, command = print('hello'), image = img)
b.pack()
b.place()
Related
I'm trying to make a sub window for configuration settings. But the text in the sub window is invisible. I am reading correctly but I cannot see the text. Below is my sample code with the problem:
import tkinter as tk
from tkinter import ttk
from tkinter import Menu
class Frames:
def __init__(self):
self.port_com = None
def main_frame(self, win):
# Main Frame
main = ttk.LabelFrame(win, text="")
main.grid(column=0, row=0, sticky="WENS", padx=10, pady=10)
return main
def dut_configuration_frame(self, win):
# Configuration Frame
dut_config_frame = ttk.LabelFrame(win, text="Config")
dut_config_frame.grid(column=0, row=0, sticky='NWS')
# Port COM
ttk.Label(dut_config_frame, text="Port COM").grid(column=0, row=0)
self.port_com = tk.StringVar()
ttk.Entry(dut_config_frame, width=12, textvariable=self.port_com).grid(column=0, row=1, sticky=tk.EW)
self.port_com.set(value="COM7")
print(self.port_com.get())
class ConfigFrames:
def __init__(self):
self.port_com = None
def main_frame(self, win):
# Main Frame
main = ttk.LabelFrame(win, text="")
main.grid(column=0, row=0, sticky="WENS", padx=10, pady=10)
return main
def configuration_frame(self, win):
# Configuration Frame
dut_config_frame = ttk.LabelFrame(win, text="Config")
dut_config_frame.grid(column=0, row=0, sticky='NWS')
# Port COM
ttk.Label(dut_config_frame, text="Port COM").grid(column=0, row=0)
self.port_com = tk.StringVar()
ttk.Entry(dut_config_frame, width=12, textvariable=self.port_com).grid(column=0, row=1, sticky=tk.EW)
self.port_com.set(value="COM5")
print(self.port_com.get())
def menu_bar(win):
def _config():
config_frame = ConfigFrames()
config_window = tk.Tk()
config_window.title("Sub window")
config_window.geometry("200x200")
config_window.resizable(0, 0)
main = config_frame.main_frame(config_window)
config_frame.configuration_frame(main)
config_window.mainloop()
# Menu
menuBar = Menu(win)
win.config(menu=menuBar)
settingsMenu = Menu(menuBar, tearoff=0)
settingsMenu.add_command(label="Config", command=_config)
menuBar.add_cascade(label="Settings", menu=settingsMenu)
frames = Frames()
win = tk.Tk()
win.title("Main window")
win.geometry("200x200")
win.resizable(0, 0)
menu_bar(win)
main = frames.main_frame(win)
frames.dut_configuration_frame(win)
win.mainloop()
As you can see in main window it is visible, but in sub window it is invisible.
And printing in console is correct:
When i want to layout my frames the Labels don't show up. I can't seem to solve it. For some reason it does show op the entries that i've made. Can somebody please help me.
import tkinter as tk
from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
class main_screen():
def __init__(self, master):
self.master = master
self.master.title("Roboframe")
self.master.geometry("650x650")
self.create_frames()
self.create_entries()
def create_frames(self):
self.top = Frame(self.master).grid(row=0,column=0)
self.bottom = Frame(self.master).grid(row=0, column=0)
self.set_paths = LabelFrame(self.master, text="Set Path", padx=10, pady=10).grid(row=0,column=0)
self.options = LabelFrame(self.master, text="Options", padx=10, pady=10).grid(row=0,column=0)
def create_entries(self):
python_path = StringVar(self.set_paths, "C:/Python37/python.exe")
robot_path = StringVar(self.set_paths, "C:/ws/cmge.automation/RobotFrameworkCMGE")
self.set_path_python = Entry(self.set_paths, width=60, textvariable=python_path).grid(row=0,column=0)
self.set_path_robot = Entry(self.set_paths, width=60, textvariable=robot_path).grid(row=1, column=0)
root = tk.Tk()
app = main_screen(root)
root.mainloop()
Output of code shown above
The thing i'm rewritting the code for because it is a mess
The second picture i've also made myself. But the code is a giant mess.
You have to make an object of the widget not the grid function of the widget. Grid returns nothing so naturally none of them will show up. I believe this is what you wanted:
import tkinter as tk
from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
class main_screen():
def __init__(self, master):
self.master = master
self.master.title("Roboframe")
self.master.geometry("650x650")
self.create_frames()
self.create_entries()
def create_frames(self):
# you have grided all of your frames and label frames on the same row and column
self.top = Frame(self.master)
self.top.grid(row=0,column=0)
self.bottom = Frame(self.master)
self.bottom.grid(row=0, column=0)
self.set_paths = LabelFrame(self.master, text="Set Path", padx=10, pady=10)
self.set_paths.grid(row=0,column=0)
self.options = LabelFrame(self.master, text="Options", padx=10, pady=10)
self.options.grid(row=0,column=0)
def create_entries(self):
python_path = StringVar(self.set_paths, "C:/Python37/python.exe")
robot_path = StringVar(self.set_paths, "C:/ws/cmge.automation/RobotFrameworkCMGE")
self.set_path_python = Entry(self.set_paths, width=60, textvariable=python_path)
self.set_path_python.grid(row=0,column=0)
self.set_path_robot = Entry(self.set_paths, width=60, textvariable=robot_path)
self.set_path_robot.grid(row=1, column=0)
root = tk.Tk()
app = main_screen(root)
root.mainloop()
Also a couple of things:
You have imported tkinter twice in two different ways, just use one of them
You are griding both of the LabelFrames and frames on the same row and column but since "self.options" does not contain anything it is not going to show up, be careful later on
This will display both LabelFrames, the second with a dummy Entry widget.
import tkinter as tk
from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
class main_screen():
def __init__(self, master):
self.master = master
self.master.title("Roboframe")
self.master.geometry("650x650")
self.create_frames()
self.create_entries()
def create_frames(self):
self.set_paths = LabelFrame(self.master, text="Set Path", padx=10, pady=10)
self.set_paths.grid(row=0,column=0)
self.options = LabelFrame(self.master, text="Options", padx=10, pady=10)
self.options.grid(row=1,column=0)
def create_entries(self):
python_path = StringVar(self.set_paths, "C:/Python37/python.exe")
robot_path = StringVar(self.set_paths, "C:/ws/cmge.automation/RobotFrameworkCMGE")
self.set_path_python = Entry(self.set_paths, width=60, textvariable=python_path)
self.set_path_python.grid(row=0,column=0)
self.set_path_robot = Entry(self.set_paths, width=60, textvariable=robot_path)
self.set_path_robot.grid(row=1, column=0)
self.test = Entry(self.options, width=60)
self.test.grid(row=1, column=1)
root = tk.Tk()
app = main_screen(root)
root.mainloop()
as a practice, I am trying to make the code for gui, and implemted a method named as get_me() to search. In this code, I imported wikipedia, and tried to search about google, and i am supposed to get the information about google. but I got some error saying "entry is not defined" which is located on line 34
import tkinter as tk
import os, sys
import wikipedia
class GuiTest():
def __init__(self,root):
self.root = root
self.root.title('CHOI')
frame3 = tk.Frame(root)
label1=tk.Label(frame3,text='please enter your name')
entry = tk.Entry(frame3)
label1.pack(padx=5, pady=5,expand=True, fill='both',side='left')
entry.pack(padx=5, pady=5,expand=True, fill='both',side='left')
btn1=tk.Button(frame3, text = 'search',command=self.get_me)
btn1.pack(padx=6, pady=6,expand=True, fill='both', side='right')
frame3.pack(padx=5,pady=5, expand=True, fill='both')
frame1=tk.Frame(root)
btn2=tk.Button(frame1,text='exit',command = self.exit)
btn2.pack(padx=7, pady=7, fill='both', side='bottom')
frame1.pack(padx=7, pady=7, fill='both')
frame2 = tk.Frame(root)
scroll=tk.Scrollbar(frame2)
scroll.pack(side='right', fill='both')
answer = tk.Text(frame2, width=30, height=10, yscrollcommand = scroll.set)
scroll.config(command=answer.yview)
answer.pack(side='bottom')
frame2.pack()
root.mainloop()
def exit(self):
sys.exit(0)
def get_me(self):
entry_value = entry.get()
answer_value = wikipedia.summary(entry_value)
answer.insert(INSERT, answer_value)
if __name__=="__main__":
root =tk.Tk()
bapp = GuiTest(root)
bapp.mainloop
Change entry to self.entry in __init__ function
self.entry = tk.Entry(frame3)
#do self.entry wherever entry was there
#and then in get_me() function do self.entry
entry_value = self.entry.get()
I have mainly 2 problems in the code:
1) it is showing error "no such directory or file exists" though I have used the same path for an image to another program (though I specified a constant path to only one image) and the images file, this program and the other program, all are in the same working directory
2) it doesn't wait for the wait function, it just executes till 16 and then opens the GUI. I want it to show all the images one by one and change only when I press the 'Next' button
Please suggest any changes in the code which may be required to satisfy the above.
I have Python 3.5.2 in a Windows 10 system.
Thanks in advance
import sys
import tkinter as tk
from PIL import Image,ImageTk,ImageFilter,ImageOps
from msvcrt import getch
def wait():
getch()
return
def classify_obj():
print("In Development")
return
src = "ímages/"
root = tk.Tk()
root.wm_title("Classify Image")
for i in range(1,17):
frame1 = tk.Frame(root, width=500, height=400, bd=2)
frame1.grid(row=1, column=0)
cv1 = tk.Canvas(frame1, height=390, width=490, background="white", bd=1, relief=tk.RAISED)
cv1.grid(row=1,column=0)
im = Image.open(src+str(i)+".jpg")
if (490-im.size[0])<(390-im.size[1]):
width = 490
height = width*im.size[1]/im.size[0]
else:
height = 390
width = height*im.size[0]/im.size[1]
im.thumbnail((width, height), Image.ANTIALIAS)
photo = ImageTk.PhotoImage(im)
cv1.create_image(0, 0, image=photo, anchor='nw')
claButton = tk.Button(master=root, text='Classify', height=2, width=10, command=classify_obj)
claButton.grid(row=0, column=1, padx=2, pady=2)
frame2 = tk.Frame(root, width=500, height=400, bd=1)
frame2.grid(row=1, column=1)
cv2 = tk.Canvas(frame2, height=390, width=490, bd=2, relief=tk.SUNKEN)
cv2.grid(row=1,column=1)
broButton = tk.Button(master=root, text='Next', height=2, width=8, command=wait)
broButton.grid(row=0, column=0, padx=2, pady=2)
print(i)
tk.mainloop()
So on of the big problems with getting the next image the way you are trying to do it is the for loop. What is happening is you have told python the check everything in that loop and perform those functions.
I think one better way would be to first create this program as a class. This way we can avoid calling global variables anywhere in the program. Then inside said class on __init__ we create a list of every photo image inside of our image folder. (Note: I have only tested this with .jpg images). Now that we have a list of all the file names we can then use that list to get a count of how many image files we are working with. With this count we can create a counter that lets us select the next index in the list thus selecting the next image in said list.
By creating all our variables as an attribute of the class we can interact with those attributes without having to declare them as global.
Take the following example. Just change the src variable to your file path.
remember to use . in your file path if your folder is inside your main python workspace. Example: I have a folder called TestImages inside the same directory as my main.py so I can make this variable: src = "./TestImages/".
Take a look at the code below:
import tkinter as tk
from PIL import Image,ImageTk
import os
class ImageClassifyer(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.root = parent
self.root.wm_title("Classify Image")
src = "./TestImages/"
self.list_images = []
for d in os.listdir(src):
self.list_images.append(d)
self.frame1 = tk.Frame(self.root, width=500, height=400, bd=2)
self.frame1.grid(row=1, column=0)
self.frame2 = tk.Frame(self.root, width=500, height=400, bd=1)
self.frame2.grid(row=1, column=1)
self.cv1 = tk.Canvas(self.frame1, height=390, width=490, background="white", bd=1, relief=tk.RAISED)
self.cv1.grid(row=1,column=0)
self.cv2 = tk.Canvas(self.frame2, height=390, width=490, bd=2, relief=tk.SUNKEN)
self.cv2.grid(row=1,column=0)
claButton = tk.Button(self.root, text='Classify', height=2, width=10, command=self.classify_obj)
claButton.grid(row=0, column=1, padx=2, pady=2)
broButton = tk.Button(self.root, text='Next', height=2, width=8, command = self.next_image)
broButton.grid(row=0, column=0, padx=2, pady=2)
self.counter = 0
self.max_count = len(self.list_images)-1
self.next_image()
def classify_obj(self):
print("In Development")
def next_image(self):
if self.counter > self.max_count:
print("No more images")
else:
im = Image.open("{}{}".format("./TestImages/", self.list_images[self.counter]))
if (490-im.size[0])<(390-im.size[1]):
width = 490
height = width*im.size[1]/im.size[0]
self.next_step(height, width)
else:
height = 390
width = height*im.size[0]/im.size[1]
self.next_step(height, width)
def next_step(self, height, width):
self.im = Image.open("{}{}".format("./TestImages/", self.list_images[self.counter]))
self.im.thumbnail((width, height), Image.ANTIALIAS)
self.root.photo = ImageTk.PhotoImage(self.im)
self.photo = ImageTk.PhotoImage(self.im)
if self.counter == 0:
self.cv1.create_image(0, 0, anchor = 'nw', image = self.photo)
else:
self.im.thumbnail((width, height), Image.ANTIALIAS)
self.cv1.delete("all")
self.cv1.create_image(0, 0, anchor = 'nw', image = self.photo)
self.counter += 1
if __name__ == "__main__":
root = tk.Tk()
MyApp = ImageClassifyer(root)
tk.mainloop()
There are lots of issues with the current code. I tried to make it work with as little change as possible. The fundamental problem was that the button binding to wait() goes against the principle of having a GUI. So in short, here is a framework from which to get started...
import tkinter as tk
from PIL import Image,ImageTk,ImageFilter,ImageOps
from msvcrt import getch
src = 'images/'
i = 1
def showImage():
global i
# You need to do file exists error checking here.
try:
im = Image.open(src+str(i)+".jpg")
except:
print("No image file named", src+str(i)+".jpg")
return
if (490-im.size[0])<(390-im.size[1]):
width = 490
height = width*im.size[1]/im.size[0]
else:
height = 390
width = height*im.size[0]/im.size[1]
im.thumbnail((width, height), Image.ANTIALIAS)
photo = ImageTk.PhotoImage(im)
label.configure(image=photo)
label.image = photo
i += 1
return
def classify_obj():
print("In Development")
return
root = tk.Tk()
root.wm_title("Classify Image")
frame1 = tk.Frame(root, width=500, height=400, bd=2)
frame1.grid(row=1, column=0)
cv1 = tk.Canvas(frame1, height=390, width=490, background="white", bd=1, relief=tk.RAISED)
label = tk.Label(cv1)
cv1.create_window(0, 0, anchor='nw', window=label)
cv1.grid(row=1,column=0)
claButton = tk.Button(master=root, text='Classify', height=2, width=10, command=classify_obj)
claButton.grid(row=0, column=1, padx=2, pady=2)
frame2 = tk.Frame(root, width=500, height=400, bd=1)
frame2.grid(row=1, column=1)
cv2 = tk.Canvas(frame2, height=390, width=490, bd=2, relief=tk.SUNKEN)
cv2.grid(row=1,column=1)
broButton = tk.Button(master=root, text='Next', height=2, width=8, command=showImage)
broButton.grid(row=0, column=0, padx=2, pady=2)
showImage()
tk.mainloop()
I was working on setting the background image and upon that image adding the labels, buttons and all. everything is coming, but not on the background image, its like this:
And my code is:
from Tkinter import Tk, Frame, BOTH
import Tkinter
from PIL import Image, ImageTk
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("PISE")
self.pack(fill=BOTH, expand=1)
root = Tk()
root.geometry("1111x675+300+300")
app = Example(root)
im = Image.open('wood.png')
tkimage = ImageTk.PhotoImage(im)
Tkinter.Label(root,image = tkimage).pack()
custName = StringVar(None)
yourName = Entry(app, textvariable=custName)
yourName.pack()
relStatus = StringVar()
relStatus.set(None)
labelText = StringVar()
labelText.set('Accuracy Level')
label1 = Label(app, textvariable=labelText, height=2)
label1.pack()
radio1 = Radiobutton(app, text='100%', value='1', variable = relStatus, command=beenClicked1).pack()
radio2 = Radiobutton(app, text='50%', value='5', variable = relStatus, command=beenClicked5).pack()
root.mainloop()
How to fit the background image properly?
Thanks in advance!
You should use place() for placing the image & then use grid() (personally i prefer grid) or pack() for other widgets.
from Tkinter import Tk, Frame, BOTH
import Tkinter
from PIL import Image, ImageTk
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("PISE")
self.pack(fill=BOTH, expand=1)
root = Tk()
root.geometry("1111x675+300+300")
app = Example(root)
im = Image.open('Test1.png')
tkimage = ImageTk.PhotoImage(im)
myvar=Tkinter.Label(root,image = tkimage)
myvar.place(x=0, y=0, relwidth=1, relheight=1)
custName = StringVar(None)
yourName = Entry(root, textvariable=custName)
yourName.pack()
relStatus = StringVar()
relStatus.set(None)
labelText = StringVar()
labelText.set('Accuracy Level')
label1 = Label(root, textvariable=labelText, height=2)
label1.pack()
def beenClicked1():
pass
def beenClicked5():
pass
radio1 = Radiobutton(root, text='100%', value='1', variable = relStatus, command=beenClicked1).pack()
radio2 = Radiobutton(root, text='50%', value='5', variable = relStatus, command=beenClicked5).pack()
root.mainloop()
The reason the widgets were not visible was because you were using two different parents ,i.e, app(its an Instance of class Example,so don't use this) and root.