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()
Related
I am creating a gui for my ML project but I am unable to successfully create a vertical scrollbar that actually works. Here's my code
import tkinter as tk
import tkinter.filedialog
from PIL import ImageTk, Image
class App:
def __init__(self, master):
frame = tk.Frame(master,width=500,height=500)
frame.pack()
self.canvas=tk.Canvas(frame,width=500, height=500,borderwidth=0,highlightthickness=0,background='white',scrollregion=(0,0,500,800))
self.canvas.pack()
vbar=tk.Scrollbar(self.canvas,orient="vertical")
vbar.pack(side="right",fill="y")
vbar.config(command=self.canvas.yview)
self.canvas.config(yscrollcommand=vbar.set)
self.canvas.bind("<Configure>",lambda e:self.canvas.configure(scrollregion=self.canvas.bbox('all')))
root.minsize(500,500)
self.button = tk.Button(self.canvas,
text="QUIT", fg="red",
command=frame.quit)
self.button.pack()
self.button2 = tk.Button(self.canvas,
text="Display image",
command=self.Display_image)
self.button2.pack()
def Display_image(self):
f = tkinter.filedialog.askopenfilename(
parent=root, initialdir='D:/Test',
title='Choose file',
filetypes=[('bmp images', '.bmp')]
)
image = ImageTk.PhotoImage(Image.open(f))
l1 = tkinter.Label(self.canvas, image=image)
l1.image = image
l1.pack()
root = tk.Tk()
app = App(root)
root.mainloop()
The code does create a scrollbar but is not functional. However when I include this line of code self.canvas.create_rectangle((0,0,500,800)) in the code the rectangle scrolls.
Have a scenario where in I am trying to place two button inside a Frame and place that frame in another Frame in a particular row. But the buttons placed inside the sub-frame is not expanding to the full length as shown in the snapshot below.
I tried with grid, place etc. but still didnt work. I haven't tried much on padding or filling etc. or setting some default size of the buttons.
Tried checking for some solution they kept saying you need to rowconfigure and columnconfigure the root widget etc. but even that didnt work. Any suggestion how to make sure the widgets expand to full length ?
Below is the code I tried: For frame and the buttons.
#!/usr/intel/bin/python2.7
import Tkinter
import Tkinter as tk
from Tkinter import *
import ttk
import Tkinter
from Tkinter import *
import subprocess
import shlex
import os
#from PIL import Image, ImageTk
#import Image, ImageTk
import time
import string
import tkFont
import ttk
class MyApp:
def __init__(self, parent):
self.rel3 = None
self.ib_frame = None
self.rb = None
self.eb = None
if not (self.rel3):
self.rel3 = Label(root, font=MyFontH2, text="What Type Of Widget You Wanted To Create: ")
self.rel3.grid(row=6, column=0, sticky='W', padx=38)
self.rel3.rowconfigure(6,weight=1)
else:
self.rel3.grid()
# Frame Code
if not (self.ib_frame):
self.ib_frame = Frame(root)
self.ib_frame.grid(row=7, column=0, columnspan=1, sticky='WE')
self.ib_frame.rowconfigure(7,weight=1)
#self.ib_frame.columnconfigure(0,weight=1)
# Button1 Code
if not self.rb:
self.rb = Button(self.ib_frame, background="royalblue1", activebackground="blue2", text="RTMM")
self.rb.grid(row=0, column=0, sticky='WE')
self.rb.rowconfigure(0, weight=1)
# self.rb.pack(side=LEFT, fill=BOTH)
# Button2 Code
if not (self.eb):
self.eb = Button(self.ib_frame, background="orangered", activebackground="orangered3", text="ECG")
self.eb.grid(row=0, column=1, sticky='WE')
self.eb.rowconfigure(0, weight=1)
#self.eb.pack(side=RIGHT, fill=BOTH)
root = Tk()
root.title("Test UI")
MyFontH2 = tkFont.Font(family='courier', size=20, weight=tkFont.BOLD)
myapp = MyApp(root)
root.mainloop()
Example output: Wondering by the two buttons added sits in the right corner when I added them in a separate frame and then placed it in row in the root frame.
NEW UPDATE: I tried the below code but still the problem is same. Am i doing something wrong ?
#!/usr/intel/bin/python2.7
import Tkinter
import Tkinter as tk
from Tkinter import *
import ttk
import Tkinter
from Tkinter import *
import subprocess
import shlex
import os
#from PIL import Image, ImageTk
#import Image, ImageTk
import time
import string
import tkFont
import ttk
class MyApp:
def __init__(self, parent):
self.rel3 = None
self.ib_frame = None
self.rb = None
self.eb = None
self.fb = None
self.l_1 = None
self.e_1 = None
if not (self.l_1):
self.l_1 = Label(text="Choose the Config: ")
self.l_1.grid(row=1, column=0, sticky='W')
self.l_1.rowconfigure(1,weight=1)
self.l_1.columnconfigure(0,weight=1)
else:
self.l_1.grid_forget(); self.l_1 = None
self.l_1 = Label(text="Choose the Config: ")
self.l_1.grid(row=1, column=0, sticky='W')
self.l_1.rowconfigure(1,weight=1)
self.l_1.columnconfigure(0,weight=1)
if not (self.e_1):
self.e_1 = Entry(bg="goldenrod")
self.e_1.grid(row=1, column=1, sticky='WE')
self.e_1.rowconfigure(1,weight=1)
self.e_1.columnconfigure(1,weight=1)
else:
self.e_1.grid_forget(); self.e_1 = None
self.e_1 = Entry()
self.e_1.grid(row=1, column=1, sticky='WE')
self.e_1.rowconfigure(1,weight=1)
self.e_1.columnconfigure(1,weight=1)
# Frame Code
if not (self.ib_frame):
self.ib_frame = Frame(root)
self.ib_frame.grid(row=7, column=0, columnspan=**2**, sticky='WE')
#self.ib_frame.rowconfigure(7,weight=1)
self.ib_frame.columnconfigure((0,1,2),weight=1)
# Button1 Code
if not self.rb:
self.rb = Button(self.ib_frame, background="royalblue1", activebackground="blue2", text="VEGI")
self.rb.grid(row=0, column=0, sticky='WE')
#self.rb.rowconfigure(0, weight=1)
self.rb.columnconfigure(0,weight=1)
# self.rb.pack(side=LEFT, fill=BOTH)
# Button2 Code
if not (self.eb):
self.eb = Button(self.ib_frame, background="orangered", activebackground="orangered3", text="DESERT")
self.eb.grid(row=0, column=1, sticky='WE')
#self.eb.rowconfigure(0, weight=1)
self.eb.columnconfigure(1,weight=1)
#self.eb.pack(side=RIGHT, fill=BOTH)
# Button2 Code
if not (self.fb):
self.fb = Button(self.ib_frame, background="tan1", activebackground="tan4", text="FRUIT")
self.fb.grid(row=0, column=2, sticky='WE')
#self.fb.rowconfigure(0, weight=1)
self.fb.columnconfigure(2,weight=1)
#self.fb.pack(side=RIGHT, fill=BOTH)
root = Tk()
root.title("Test UI")
MyFontH2 = tkFont.Font(family='courier', size=20, weight=tkFont.BOLD)
myapp = MyApp(root)
root.mainloop()
UPDATE : Got it fixed. Its the columnspan.
You can expand the columns in the frame ib_frame with columnconfigure:
# Frame Code
if not (self.ib_frame):
self.ib_frame = Frame(root, bg='tan')
self.ib_frame.grid(row=7, column=0, columnspan=1, sticky='WE')
self.ib_frame.rowconfigure(7, weight=1)
self.ib_frame.columnconfigure([0,1], weight=1)
# ^
# expand both columns
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()
I want to make a lot of notebook tabs, and I want to put them in canvas and to add a horizontal scrollbar so that I can scroll trough them.
I set the canvas size, but canvas size keep changing when I add new tab. Also, scrollbar does not work, can you tell me what am I doing wrong?
The program does not show me any error. This is the code:
from tkinter import *
from tkinter import ttk
myApp = Tk()
myApp.title(" Program ")
myApp.geometry("900x500")
CanvasTabs = Canvas(myApp, width=50, height=50)
CanvasTabs.grid(row=0,column=0)
tabs = ttk.Notebook(CanvasTabs, width=100, height=100)
tab1 = ttk.Frame(tabs)
tabs.add(tab1,text=" Tab 1 ")
tab2 = ttk.Frame(tabs)
tabs.add(tab2,text=" Tab 2 ")
tab3 = ttk.Frame(tabs)
tabs.add(tab3,text=" Tab 3 ")
tab4 = ttk.Frame(tabs)
tabs.add(tab4,text=" Tab 4 ")
hbar=Scrollbar(CanvasTabs,orient=HORIZONTAL)
hbar.pack(side=TOP,fill=X)
hbar.config(command=CanvasTabs.xview)
CanvasTabs.config(xscrollcommand=hbar.set)
tabs.pack(expand=1, fill="both")
myApp.mainloop()
I code a widget to fix the problem. Here is a real solution:
https://github.com/muhammeteminturgut/ttkScrollableNotebook
# -*- coding: utf-8 -*-
# Copyright (c) Muhammet Emin TURGUT 2020
# For license see LICENSE
from tkinter import *
from tkinter import ttk
class ScrollableNotebook(ttk.Frame):
def __init__(self,parent,*args,**kwargs):
ttk.Frame.__init__(self, parent, *args)
self.xLocation = 0
self.notebookContent = ttk.Notebook(self,**kwargs)
self.notebookContent.pack(fill="both", expand=True)
self.notebookTab = ttk.Notebook(self,**kwargs)
self.notebookTab.bind("<<NotebookTabChanged>>",self._tabChanger)
slideFrame = ttk.Frame(self)
slideFrame.place(relx=1.0, x=0, y=1, anchor=NE)
leftArrow = ttk.Label(slideFrame, text="\u25c0")
leftArrow.bind("<1>",self._leftSlide)
leftArrow.pack(side=LEFT)
rightArrow = ttk.Label(slideFrame, text=" \u25b6")
rightArrow.bind("<1>",self._rightSlide)
rightArrow.pack(side=RIGHT)
self.notebookContent.bind( "<Configure>", self._resetSlide)
def _tabChanger(self,event):
self.notebookContent.select(self.notebookTab.index("current"))
def _rightSlide(self,event):
if self.notebookTab.winfo_width()>self.notebookContent.winfo_width()-30:
if (self.notebookContent.winfo_width()-(self.notebookTab.winfo_width()+self.notebookTab.winfo_x()))<=35:
self.xLocation-=20
self.notebookTab.place(x=self.xLocation,y=0)
def _leftSlide(self,event):
if not self.notebookTab.winfo_x()== 0:
self.xLocation+=20
self.notebookTab.place(x=self.xLocation,y=0)
def _resetSlide(self,event):
self.notebookTab.place(x=0,y=0)
self.xLocation = 0
def add(self,frame,**kwargs):
if len(self.notebookTab.winfo_children())!=0:
self.notebookContent.add(frame, text="",state="hidden")
else:
self.notebookContent.add(frame, text="")
self.notebookTab.add(ttk.Frame(self.notebookTab),**kwargs)
def forget(self,tab_id):
self.notebookContent.forget(tab_id)
self.notebookTab.forget(tab_id)
def hide(self,tab_id):
self.notebookContent.hide(tab_id)
self.notebookTab.hide(tab_id)
def identify(self,x, y):
return self.notebookTab.identify(x,y)
def index(self,tab_id):
return self.notebookTab.index(tab_id)
def insert(self,pos,frame, **kwargs):
self.notebookContent.insert(pos,frame, **kwargs)
self.notebookTab.insert(pos,frame,**kwargs)
def select(self,tab_id):
self.notebookContent.select(tab_id)
self.notebookTab.select(tab_id)
def tab(self,tab_id, option=None, **kwargs):
return self.notebookTab.tab(tab_id, option=None, **kwargs)
def tabs(self):
return self.notebookContent.tabs()
def enable_traversal(self):
self.notebookContent.enable_traversal()
self.notebookTab.enable_traversal()
Taking Bryan's example on this post and modifying it to include your Notebook code we get a functioning scrollbar that will allow you to scroll over your Notebook widget if it exceeds the limit of the window.
Bryan's example uses the pack() geometry manager however I personally find grid() easier to visualize so I replace pack with grid() in my example.
UPDATE:
import tkinter as tk
import tkinter.ttk as ttk
class Example(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.canvas = tk.Canvas(self, borderwidth=0)
self.frame = tk.Frame(self.canvas)
self.vsb = tk.Scrollbar(self, orient="horizontal", command=self.canvas.xview)
self.vsb.grid(row=1, column=0, sticky="nsew")
self.canvas.configure(xscrollcommand=self.vsb.set)
self.canvas.grid(row=0, column=0, sticky="nsew")
self.canvas.create_window((3,2), window=self.frame, anchor="nw", tags="self.frame")
self.frame.bind("<Configure>", self.frame_configure)
self.populate()
def populate(self):
tabs = ttk.Notebook(self.frame, width=100, height=100)
for tab in range(50):
tabs.add(ttk.Frame(tabs), text=" Tab {} ".format(tab))
tabs.grid(row=0, column=0, sticky="ew")
def frame_configure(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
if __name__ == "__main__":
app = Example()
app.mainloop()
Updated results:
Per your request in the comments here is a Non-OOP example:
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
canvas = tk.Canvas(root, borderwidth=0)
frame = tk.Frame(canvas)
vsb = tk.Scrollbar(root, orient="horizontal", command=canvas.xview)
vsb.grid(row=1, column=0, sticky="nsew")
canvas.configure(xscrollcommand=vsb.set)
canvas.grid(row=0, column=0, sticky="nsew")
canvas.create_window((3,2), window=frame, anchor="nw", tags="frame")
tabs = ttk.Notebook(frame, width=100, height=100)
for tab in range(50):
tabs.add(ttk.Frame(tabs), text=" Tab {} ".format(tab))
tabs.grid(row=0, column=0, sticky="ew")
def frame_configure(event):
global canvas
canvas.configure(scrollregion=canvas.bbox("all"))
frame.bind("<Configure>", frame_configure)
root.mainloop()
What I want to be able to do is open a window with two images (one image is an exact copy of the other). Then when I click a button it changes the image on the right. I hope this is making sense. The code I have no is:
from __future__ import division
from Tkinter import *
from PIL import Image, ImageTk, ImageFilter
import random
class MyApp(object):
def __init__(self):
self.root = Tk()
self.root.wm_title("Image examples")
img = Image.open("lineage.jpg").convert("RGB")
(w, h) = (img.size[0], img.size[1])
print (w, h)
tkpi = ImageTk.PhotoImage(img)
label = Label(self.root, image=tkpi)
label.grid(row=0, column=0, padx=5, pady=5, rowspan=10)
img2 = img.copy()
pixels = img2.load()
tkpi2 = ImageTk.PhotoImage(img2)
label = Label(self.root, image=tkpi2)
label.grid(row=0, column=1, padx=5, pady=5, rowspan=10)
Button(self.root, text="Brighten", command=self.brighten).grid(row=0, column= 2)
self.root.mainloop()
def brighten(self):
self.pixels = self.pixels.point(lambda x: x*1.9)
MyApp()
What I am trying to is have img2 update when I click on the brighten button. When I try now I get this error:
File "C:\Users\Admin\Desktop\imageeditor.py", line 36, in brighten
self.pixels = self.pixels.point(lambda x: x*1.9)
AttributeError: 'MyApp' object has no attribute 'pixels'
As you can tell I'm new to programming so any help to send me on the right track would be awesome.
Below is a complete solution that works. These are a few comments on the changes that were made:
Previously the __init__ method never returned because it calls self.root.mainloop() at the end. Which can cause some issues. I restructured it to be more like the hello world example in the python docs.
There is a great Darken/Lighten Example that is what the brighten() method is modeled around.
there was a from Tkinter import *, this replaced by from Tkinter import Frame, Tk, Label, Button. it turns out that both PIL and Tkinter have an attribute called Image which was really confusing to work with. Try and avoid the use of from module import * and instead be explicit in what you are importing this will prevent name space collisions.
code
from Tkinter import Frame, Tk, Label, Button
from PIL import Image, ImageTk, ImageFilter
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
master.wm_title("Image examples")
self.pack()
self.createWidgets()
def createWidgets(self):
self.img = Image.open("lineage.jpg")
self.photo1 = ImageTk.PhotoImage(self.img.convert("RGB"))
self.label1 = Label(self, image=self.photo1)
self.label1.grid(row=0, column=0)
self.photo2 = ImageTk.PhotoImage(self.img.convert("RGB"))
self.label2 = Label(self, image=self.photo2)
self.label2.grid(row=0, column=1)
button = Button(self, text="Brighten", command=self.brighten)
button.grid(row=0, column=2)
def brighten(self):
img2 = self.img.point(lambda p: p * 1.9)
self.photo2 = ImageTk.PhotoImage(img2)
self.label2 = Label(self, image=self.photo2)
self.label2.grid(row=0, column=1)
root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
I got a working one.
from __future__ import division
from Tkinter import *
from PIL import Image, ImageTk, ImageFilter
import random
class MyApp(object):
def __init__(self):
self.root = Tk()
self.root.wm_title("Image examples")
img = Image.open("lineage.jpg").convert("RGB")
(self.w, self.h) = (img.size[0], img.size[1])
self.tkpi = ImageTk.PhotoImage(img)
self.label = Label(self.root, image=self.tkpi)
self.label.grid(row=0, column=0, padx=5, pady=5, rowspan=10)
self.img2 = img.copy()
self.pixels = self.img2.load()
self.width, self.height = self.img2.size
self.tkpi2 = ImageTk.PhotoImage(self.img2)
self.label2 = Label(self.root, image=self.tkpi2)
self.label2.grid(row=0, column=1, padx=5, pady=5, rowspan=10)
self.btn = Button(self.root, text="Brighten")
self.btn.grid(row=0, column= 2)
self.btn.bind('<Button-1>', self.brighten)
self.root.mainloop()
def brighten(self,*args):
# self.pixels = self.pixels.point(lambda x: x*1.9)
for i in range(self.w): # for every pixel:
for j in range(self.h):
# print self.pixels[i,j]
self.pixels[i,j] = (int(self.pixels[i,j][0] * 1.9),
int(self.pixels[i,j][1] * 1.9),
int(self.pixels[i,j][2] * 1.9))
self.tkpi2 = ImageTk.PhotoImage(self.img2)
self.label2.configure(image = self.tkpi2)
self.root.update_idletasks()
MyApp()