Python classes with tkinter unable to parse object items - python

I am wanting to use a class as normal and parse through data use the self instance. My aim is to be able to create many displays/screens that show graph data using matplotlib. I want a user to be able to select a csv file and a view of the data is listed.
I am having trouble returning the data from another file. I have a csv upload class that gets the data from a csv. The data is then put into a text variable and is called by a class. I am wanting to return this data to the DES class so that the data can be viewed but I am finding that I need to know the instance in order to access the class. Any help is appreciated. Please feel free to ask questions.
DES Class
i = 0
class DES(Frame):
def __init__(self, master, summary):
global i
self.master = master
self.frame = tk.Frame(self.master, width=750, height=968,bg='white')
self.summary = summary
self.upload_button = tk.Button(
self.frame,
text="Options",
fg="DodgerBlue4",
font=("Graph Type", 15),
height=1, width=12,
borderwidth=2,
relief="groove",
command=self.menu)
self.des_button = tk.Button(
self.frame,
text="New DES",
fg="DodgerBlue4",
font=("Graph Type", 15),
height=1, width=12,
borderwidth=2,
relief="groove",
command=self.new_des)
self.logout_buttotn = tk.Button(
self.frame,
text="Logout",
font=("Arial", 15),
height=1, width=12,
borderwidth=2,
relief="groove",
fg="red",
command = self.close)
self.chat_submit_button = tk.Button(
self.frame,
text="Submit",
font=("Arial", 9),
height=1, width=12,
# command=self.set_chat_text,
borderwidth=2,
relief="groove")
self.chat_input = tk.Entry(
self.frame,
width=55,
font=("Arial", 14), highlightthickness=0,
bg="white", borderwidth=1, relief="solid")
self.summary_output = tk.Text(
self.frame,
height=8,
width=78,
bg="gray95",
borderwidth=2,
relief="groove",
font=("Arial", 12))
self.summary_output.configure(state='disabled')
self.chat_output = tk.Text(
self.frame,
height=8,
width=78,
bg="gray95",
borderwidth=2,
relief="groove",
font=("Arial", 12))
self.chat_output.insert(INSERT, "Chat: \n")
self.chat_output.configure(state='disabled')
self.combo_box_graph = ttk.Combobox(
self.frame,
width=12,
justify='center',
font=("Arial", 22),
state="readonly")
self.combo_box_graph['values'] = (
'Select',
'Line Graph',
'Bar Graph',
'Histogram',
'Scatter Graph')
# s = tk.StringVar()
self.combo_box_graph.current(0)
# self.combo_box_graph.bind("<<ComboboxSelected>>", view_graph)
font = Font(family = "Helvetica", size = 12)
self.frame.option_add("*TCombobox*Listbox*Font", font)
# IMPLEMENTING GRAPH ------------------------------------------------------
fig = Figure(figsize=(5, 4), dpi=130) # Create graph figure
plt.ax = fig.add_subplot(111) # Add plots
self.canvas = FigureCanvasTkAgg(fig, self.master) # tk implementation
self.canvas.draw() # Create the graph canvas
# # IMPLEMENTING TOOLBAR ----------------------------------------------------
toolbarFrame = Frame(self.master)
toolbarFrame.pack(side=TOP, fill=BOTH) # Place toolbar at top of screen
toolbar = NavigationToolbar2Tk(self.canvas, toolbarFrame)
self.upload_button.place(x=20, y=560)
self.combo_box_graph.place(x=170, y=560)
self.summary_output.place(x=20, y=610)
self.chat_output.place(x=20, y=770)
self.chat_input.place(x=20, y=920)
self.chat_submit_button.place(x=633, y=920)
self.logout_buttotn.place(x=585, y=560)
self.canvas.get_tk_widget().place(x=50, y=30)
if i == 0:
self.des_button.place(x=395, y=560)
i += 1
self.frame.pack()
def new_des(self):
self.newWindow = tk.Toplevel(self.master)
self.app = DES(self.newWindow)
def menu(self):
self.newWindow = tk.Toplevel(self.master)
self.app = upload_csv(self.newWindow)
def close(self):
self.master.destroy()
def set_chat_text(self):
self.chat_output.configure(state='normal')
self.chat_output.insert('end', self.chat_input.get() + '\n')
self.chat_output.configure(state='disabled')
self.chat_input.delete(0, END)
def set_summary_text(self):
self.summary_output.configure(state='normal')
self.summary_output.delete('1.0', END) # Remote all text
self.summary_output.insert('end', self.summary)
self.summary_output.configure(state='disabled') #Make text widget read only
def main():
root = tk.Tk()
app = DES(root, "")
root.mainloop()
if __name__ == '__main__':
main()
Upload CSV file:
text = ""
class upload_csv(Frame):
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master, width=250, height=160, bg='white')
self.upload_csv_btn = Button(
self.frame,
text="Add Data Source",
fg="DodgerBlue4",
font=("Graph Type", 15),
height=1, width=20,
borderwidth=2,
relief="groove",
command=self.upload)
self.merge_btn = Button(
self.frame,
text="Combine CSV Files",
command=merge_csv,
font=("Arial", 15),
height=1, width=20,
borderwidth=2,
relief="groove",
fg="DodgerBlue4")
self.close_btn = Button(
self.frame,
text="Close",
font=("Arial", 15),
height=1, width=20,
borderwidth=2,
relief="groove",
fg="red",
command=self.close_windows)
self.upload_csv_btn.place(x=10, y=10)
self.merge_btn.place(x=10, y=60)
self.close_btn.place(x=10, y=110)
self.frame.pack()
def close_windows(self):
self.master.destroy()
def upload(self):
global text
self.xvalues = []
self.yvalues = []
self.xyvalues = []
self.header = []
self.xvalues.clear()
self.yvalues.clear()
self.xyvalues.clear()
self.header.clear()
# csv_quit()
filename = filedialog.askopenfilename()
if len(filename) != 0:
print('Selected:', filename)
with open(filename) as file:
csvreader = csv.reader(file)
self.header.append(next(csvreader))
for row in csvreader:
if len(row) == 3:
self.xvalues.append(int(row[0]))
self.yvalues.append(int(row[1]))
self.xyvalues.append(int(row[2]))
text = (
self.header[0][0]+ ": " + str(self.xvalues).replace('[','').replace(']','') +
"\n\n" + self.header[0][1] + ": " + str(self.yvalues).replace('[','').replace(']','') +
"\n\n" + self.header[0][2] + ": " + str(self.xyvalues).replace('[','').replace(']',''))
elif len(row) == 2:
self.xvalues.append(row[0])
self.yvalues.append(row[1])
text = (
self.header[0][0] + ": " + str(self.xvalues).replace('[','').replace(']','') +
"\n\n" + self.header[0][1] + ": " + str(self.yvalues).replace('[','').replace(']',''))
s = Set(text)
s.set_summary()
My set class:
class Set:
def __init__ (self, summary):
self.summary = summary
def set_summary(self):
print(self.summary)
s = DES(self.summary)
DES.set_summary_text()
When I get the text variable I am calling a function in the set class, I am then wanting to use that to call the set_summary function in the DES class but I cant due to not proving an instance. Please help.

Related

Tkinter: Cannot edit entry widget after 2nd selection

I've made a simple GUI for placing objects in RoboDK via a Python script using Tkinter.
Essentailly, the user selects an object using the btnSelect button, which then updates the entry widgets with its coordinates (x, y, z, then Euler rotation). The user can then edit the entry widgets then select the "Move object" button (or btnMove in the code) to move the object to the new position. However, when selecting an object for the second time, the entry fields cannot be edited without selecting a new object.
from tkinter.constants import DISABLED, NORMAL, CENTER, END
from typing import *
import tkinter as tk
import threading
from robolink import * # RoboDK API
from robodk import * # Robot toolbox
X_MAX = 500
X_MIN = 0
Y_MAX = 300
Y_MIN = -360
ROTZ_MAX = 180
ROTZ_MIN = -180
# Keep track of selected item
obj = None
def main():
rdk = Robolink()
window = buildGUI(rdk)
window.mainloop()
def buildGUI(rdk: Robolink) -> tk.Tk:
window = tk.Tk()
canvas = tk.Canvas(window, width=200)
canvas.grid(columnspan=3, rowspan=14)
# Set the window title (must be unique for the docking to work, try to be creative)
window_title = 'Move object window'
window.title(window_title)
title = tk.Label(window, text="Move Object", font="none 14 bold")
title.grid(columnspan=3, column=0, row=0)
# Delete the window when we close it
window.protocol("WM_DELETE_WINDOW", lambda: onClose(window))
deadspace1 = tk.Label(text="")
deadspace1.grid(columnspan=3, column=0, row=1)
selectText = tk.StringVar()
btnSelect = tk.Button(window, textvariable=selectText, height=2, width=0,
bg="#bbbbbb", fg='white', justify=CENTER)
selectText.set("Select object")
btnSelect.grid(column=1, row=2)
deadspace2 = tk.Label("")
deadspace2.grid(columnspan=3, column=0, row=3)
objName = tk.StringVar()
objLabel = tk.Label(window, textvariable=objName, font="none 12 bold")
objName.set("None Selected")
objLabel.grid(columnspan=3, column=0, row=4)
deadspace2 = tk.Label("")
deadspace2.grid(columnspan=3, column=0, row=5)
# Position options
xLabel = tk.Label(window, text="x: ", font='none 12')
xLabel.grid(column=0, row=6)
xEntry = tk.Entry(window, width=10)
xEntry.grid(columnspan=2, column=1, row=6)
yLabel = tk.Label(window, text="y: ", font='none 12')
yLabel.grid(column=0, row=7)
yEntry = tk.Entry(window, width=10)
yEntry.grid(columnspan=2, column=1, row=7)
zLabel = tk.Label(window, text="z: ", font='none 12')
zLabel.grid(column=0, row=8)
zEntry = tk.Entry(window, width=10)
zEntry.grid(columnspan=2, column=1, row=8)
# Rotation options
rxLabel = tk.Label(window, text="rx: ", font='none 12')
rxLabel.grid(column=0, row=9)
rxEntry = tk.Entry(window, width=10)
rxEntry.grid(columnspan=2, column=1, row=9)
ryLabel = tk.Label(window, text="ry: ", font='none 12')
ryLabel.grid(column=0, row=10)
ryEntry = tk.Entry(window, width=10)
ryEntry.grid(columnspan=2, column=1, row=10)
rzLabel = tk.Label(window, text="rz: ", font='none 12')
rzLabel.grid(column=0, row=11)
rzEntry = tk.Entry(window, width=10)
rzEntry.grid(columnspan=2, column=1, row=11)
entries = [xEntry, yEntry, zEntry, rzEntry, ryEntry, rxEntry]
deadspace3 = tk.Label(text="")
deadspace3.grid(columnspan=3, column=0, row=12)
btnMove = tk.Button(window, text="Move object", height=2, width=0,
bg="#bbbbbb", fg='white', justify=CENTER,
command=lambda: moveObject(entries))
btnMove.grid(column=1, row=13)
selectCallback = lambda: select_item(rdk, selectText, objName, entries)
btnSelect['command'] = selectCallback
EmbedWindow(window_title)
return window
# Close the window
def onClose(window: tk.Tk):
window.destroy()
quit(0)
def select_item(rdk: Robolink, selectText: tk.StringVar, objName: tk.Label,
entries: List[tk.Entry]):
def thread_btnSelect():
selectText.set("Waiting...")
item = rdk.ItemUserPick('Select an item', ITEM_TYPE_OBJECT)
if item.Valid():
global obj
obj = item
objName.set(item.Name())
updateObjectPosition(item, entries)
selectText.set("Select object")
# Prevent RoboDK from freezing
threading.Thread(target=thread_btnSelect).start()
def updateObjectPosition(item: Item, entries: List[tk.Entry]):
pose = item.Pose()
coords = Pose_2_KUKA(pose)
for entry, coord in zip(entries, coords):
entry.delete(0, END)
entry.insert(0, str(coord))
def moveObject(entries: tk.Entry):
global obj
if obj is None:
ShowMessage("No object selected")
return
try:
coords = getCoords(entries)
obj.setPose(KUKA_2_Pose(coords))
except Exception as err:
ShowMessage(str(err))
def getCoords(entries: List[tk.Entry]) -> list:
coords = [0] * 6
for i, entry in enumerate(entries):
coords[i] = float(entry.get())
return coords
if __name__ == "__main__":
main()
Using a tkinter.Variable such as tkinter.DoubleVar with your entries should fix this issue. You can also use tkinter.DoubleSpin for convenience.
x, y, z, rx, ry, rz = Pose_2_TxyzRxyz(item.Pose())
xVar = tk.DoubleVar(value=x)
xEntry = tk.Spinbox(window, textvariable=xVar, format="%.2f", from_=-9999999, to=9999999)
xVal = xVal.get()

Parameters passed to a function does not works as intended

When the "view" button is pressed, it should trigger the function solution(i) such that label should be displayed in the new window. The problem is that the window opens and the previous label is packed but the label which gets it's text from "i" does not gets packed, Is there any issue in passing the parameter.
Any help is appreciated.
root = Tk()
root.config(background = "#303939")
root.state('zoomed')
def pre():
with open("DoubtSolution.txt","r+") as f:
dousol = f.read()
dousol_lst = dousol.split("`")
k = 0
window = Tk()
window.config(background = "#303939")
window.state('zoomed')
predoubt = Label(window,
text="Previous Doubts",
fg="Cyan",
bg="#303939",
font="Helvetica 50 bold"
).grid(row=0, column=1)
def solution(text):
print(text)
window1 = Tk()
window1.config(background="#303939")
window1.state('zoomed')
sol = Label(window1,
text=text[:text.find("~")],
font=font.Font(size=20),
bg="#303939",
fg="Cyan")
sol.pack()
window1.mainloop()
for i in dousol_lst:
if i[-5:] == admno:
doubt = Label(window, text=i[i.find("]]")+2:i.find("}}}}")], font=font.Font(size=20), bg="#303939",
fg="Cyan")
doubt.grid(row=2+k, column=1, pady=10)
view = Button(
master=window,
text="View", font=font.Font(size=15, family="Helvetica"),
activebackground="White",
bg="Teal",
bd=0.8,
fg="White",
command = lambda k = k:solution(i)
)
view.grid(row=2+k, column=2, padx=20)
k=k+1
window.mainloop()
previous = Button(
master=root,
text="Previous Doubts", font="Helvetica 22 bold",
activebackground="White",
bg="Teal",
bd=0.8,
fg="White",
command = pre
).grid(row=4, column=3, padx=20)
root.mainloop()

Display the location name of the open file in the tkinter window

Very simple, don't be impressed by the size of the code.
I want to do something very simple (well, not for me, since I'm asking for help here) put the location of the open file in the red square on the screen:
Screen
import tkinter as tk
from tkinter.filedialog import askopenfilename
from tkinter import messagebox
def OpenFile_AntiDuplicate():
global antiduplicate_file
mainframe = tk.Frame(bg='#1c2028')
antiduplicate_file = askopenfilename(initialdir="/",
filetypes =(("Text file", "*.txt"),("All files","*.*")),
title = "Open text file"
)
fichier_dir = tk.Label(mainframe, text=antiduplicate_file).pack()
try:
with open(antiduplicate_file,'r') as UseFile:
print(antiduplicate_file)
except:
print("Non-existent file")
def RUN_AntiDuplicate():
try:
with open(antiduplicate_file,'r') as UseFile:
print(antiduplicate_file)
except:
error1 = tk.messagebox.showerror("ERROR", "No files exist!")
#----------------------------------------------------------
class HoverButton(tk.Button):
def __init__(self, master, **kw):
tk.Button.__init__(self,master=master,**kw)
self.defaultBackground = self["background"]
self.bind("<Enter>", self.on_enter)
self.bind("<Leave>", self.on_leave)
def on_enter(self, e):
self['background'] = self['activebackground']
def on_leave(self, e):
self['background'] = self.defaultBackground
#----------------------------------------------------------
def Anti_Duplicate():
mainframe = tk.Frame(bg='#1c2028')
mainframe.grid(row=0, column=0, sticky='nsew')
bouton_1 = HoverButton(mainframe, font=("Arial", 10), text="Back",
background='#000000', fg='white', borderwidth=2,
activebackground='#202124', activeforeground='#CF3411',
relief='ridge', command=mainframe.destroy)
bouton_1.place(x=520, y=300)
open_button = HoverButton(mainframe, font=("Arial", 10), text="Open File..",
background='#000000', fg='white', borderwidth=2,
activebackground='#202124', activeforeground='#1195cf',
relief='ridge', command = OpenFile_AntiDuplicate)
open_button.place(x=284.3, y=200, anchor='n')
run_button = HoverButton(mainframe, font=("Arial", 20), text="RUN",
background='#000000', fg='white', borderwidth=2,
activebackground='#202124', activeforeground='#11CF6D',
relief='ridge', command = RUN_AntiDuplicate)
run_button.place(x=50, y=330, anchor='s')
bouton_2 = tk.Button(mainframe, font=("Arial", 10),
text="The purpose of this tool is to remove duplicate lines from a text file.",
background='#202124', fg='#1195cf', borderwidth=2,
activebackground= '#202124', activeforeground='#1195cf', relief='sunken')
bouton_2.place(relx=.5, y=50, anchor='n')
bouton_1 = tk.Button(mainframe, font=("Arial", 15), text="Anti-Duplicate",
background='#202124', fg='#1195cf', borderwidth=2,
activebackground='#202124', activeforeground='#1195cf', relief='sunken')
bouton_1.pack(side= "top", padx= 5, pady=5, ipadx= 30, anchor="n")
#----------------------------------------------------------
def main_menu():
root = tk.Tk()
screenn_x = int(root.winfo_screenwidth())
root.config(background='#1c2028')
screenn_y = int(root.winfo_screenheight())
root.title("ComboKit v0.0.1")
root.minsize(570, 340)
root.resizable(0,0)
windowss_x = 570
windowss_y = 340
possX = (screenn_x // 2) - (windowss_x // 2)
possY = (screenn_y // 2) - (windowss_y // 2)
geoo = "{}x{}+{}+{}".format(windowss_x, windowss_y, possX, possY)
root.geometry(geoo)
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
mainframe = tk.Frame(root, bg='#1c2028')
mainframe.grid(row=0, column=0, sticky='n')
main_fusion_bouton = HoverButton(mainframe, font=("Arial", 15), text="Fusion",
background='#000000', fg='white', borderwidth=2,
activebackground='#202124', activeforeground='#1195cf',
relief='ridge', command=None)
main_fusion_bouton.pack(side= "left", padx= 5, pady=5, ipadx= 10, anchor="n")
main_antiduplicate_bouton = HoverButton(mainframe, font=("Arial", 15), text="Anti-Duplicate",
background='#000000', fg='white', borderwidth=2,
activebackground='#202124', activeforeground='#1195cf',
relief='ridge', command=Anti_Duplicate)
main_antiduplicate_bouton.pack(side= "left", padx= 5, pady=5, ipadx= 30)
main_split_button = HoverButton(mainframe, font=("Arial", 15), text="Split",
background='#000000', fg='white', borderwidth=2,
activebackground='#202124', activeforeground='#1195cf',
relief='ridge', command=None)
main_split_button.pack(side= "left", padx= 5, pady=5, ipadx= 19, anchor="n")
root.mainloop()
main_menu()
So here's my code allows you to use 3 tools:
"Split" / "Anti-Duplicate" / "Merge"
At the moment I'm working on the "Anti-Duplicate" so it's on this Frame() where the text should be displayed.
I've already done everything, even the button to open the file explorer, but for the moment the location of the file is only displayed in the cmd.
Thank you very much!
The location of the file does not show up because you created a new frame to hold the label fichier_dir inside OpenFile_AntiDuplicate() and you did not call any layout function on the frame, so the frame will not be shown.
Better create the label fichier_dir inside Anti_Duplicate() and pass it to OpenFile_AntiDuplicate() function:
def Anti_Duplicate():
...
fichier_dir = tk.Label(mainframe, bg='#1c2028', fg='white')
fichier_dir.place(relx=0.5, y=170, anchor='n')
open_button = HoverButton(mainframe, font=("Arial", 10), text="Open File..",
background='#000000', fg='white', borderwidth=2,
activebackground='#202124', activeforeground='#1195cf',
relief='ridge', command = lambda: OpenFile_AntiDuplicate(fichier_dir))
...
And update OpenFile_AntiDuplicate(...):
def OpenFile_AntiDuplicate(fichier_dir):
global antiduplicate_file
antiduplicate_file = askopenfilename(initialdir="/",
filetypes =(("Text file", "*.txt"),("All files","*.*")),
title = "Open text file"
)
fichier_dir['text'] = antiduplicate_file
...

Scrollable frame will not render all items in it Python Tkinter

I am working on a program where there is a scrollable frame that will be containing a large quantity of items. But with my app it does not render all of them. Can someone possibly tell me why? And how I can fix it?
Code:
#700x650
from Tkinter import *
import ttk
class itemLoad:
def __init__(self):
pass
def item(self):
items = "Video File,Image File,None,King King"
return items
class App(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.pack(fill=BOTH)
self.loadItem = itemLoad()
self.one = None
self.create_widgets()
self.loadItems()
def create_widgets(self):
self.mainFrame = Frame(self, width=700, height=650)
self.mainFrame.pack_propagate(False)
self.mainFrame.pack()
self.menu = Frame(self.mainFrame, width=150, height=650, bg="Gray92")
self.menu.pack_propagate(False)
self.menu.pack(side=LEFT)
self.itemMenu = Frame(self.mainFrame, width=550, height=650)
self.itemMenu.pack_propagate(False)
self.itemMenu.pack(side=LEFT)
self.vScroller = ttk.Scrollbar(self.itemMenu, orient=VERTICAL)
self.vScroller.pack(side=RIGHT, fill=Y)
self.canvas = Canvas(self.itemMenu, bd=0, width=534, highlightthickness=0, yscrollcommand=self.vScroller.set)
self.canvas.pack_propagate(False)
self.canvas.pack(side=LEFT, fill=BOTH)
self.vScroller.config(command=self.canvas.yview)
self.innerFrame = Frame(self.canvas, width=550, height=650, bg="Pink")
self.canvas.create_window(0, 0, window=self.innerFrame, anchor=NW)
def update(event):
self.canvas.config(scrollregion=self.canvas.bbox("all"))
self.innerFrame.bind("<Configure>", update)
self.spacer = Frame(self.mainFrame, bg="Gray")
self.spacer.pack(side=LEFT, fill=Y)
frame = Frame(self.menu, bg="Gray92")
frame.pack(side=TOP, fill=X)
high = Frame(frame, bg="Gray92", width=10)
high.pack(side=LEFT, fill=Y)
self.bu1 = Label(frame, font=("Calibri", 14), text=" Main Folder", width=12, anchor=W, bg="Gray92")
self.bu1.pack(side=LEFT, fill=X, ipadx=10, ipady=10)
frame2 = Frame(self.menu, bg="Gray92")
frame2.pack(side=TOP, fill=X)
high2 = Frame(frame2, bg="Gray92", width=10)
high2.pack(side=LEFT, fill=Y)
self.bu2 = Label(frame2, font=("Calibri", 14), text=" Favorited", width=12, anchor=W, bg="Gray92")
self.bu2.pack(side=LEFT, fill=X, ipadx=10, ipady=10)
frame3 = Frame(self.menu, bg="Gray92")
frame3.pack(side=TOP, fill=X)
high3 = Frame(frame3, bg="Gray92", width=10)
high3.pack(side=LEFT, fill=Y)
self.bu3 = Label(frame3, font=("Calibri", 14), text=" Trash Can", width=12, anchor=W, bg="Gray92")
self.bu3.pack(side=LEFT, fill=X, ipadx=10, ipady=10)
frame4 = Frame(self.menu, bg="Gray92")
frame4.pack(side=BOTTOM, fill=X)
high4 = Frame(frame4, bg="Gray92", width=10)
high4.pack(side=LEFT, fill=Y)
self.bu4 = Label(frame4, font=("Calibri", 14), text=" Log Out", width=12, anchor=W, bg="Gray92")
self.bu4.pack(side=LEFT, fill=X, ipadx=10, ipady=10)
def hover(event):
widg = event.widget
items = widg.winfo_children()
if items[1].cget("text") == self.one:
pass
else:
items[0].config(bg="Gray85")
items[1].config(bg="Gray85")
def unHover(event):
widg = event.widget
text = None
items = widg.winfo_children()
if items[1].cget("text") == self.one:
pass
else:
items[0].config(bg="Gray92")
items[1].config(bg="Gray92")
def clicked(event):
widg = event.widget
par = widg.winfo_parent()
par = self.menu._nametowidget(par)
for item in self.menu.winfo_children():
items = item.winfo_children()
items[0].config(bg="Gray92")
for item in par.winfo_children():
try:
self.one = item.cget("text")
except:
item.config(bg="lightBlue")
frame.bind("<Enter>", hover)
frame2.bind("<Enter>", hover)
frame3.bind("<Enter>", hover)
frame4.bind("<Enter>", hover)
frame.bind("<Leave>", unHover)
frame2.bind("<Leave>", unHover)
frame3.bind("<Leave>", unHover)
frame4.bind("<Leave>", unHover)
high.bind("<Button-1>", clicked)
self.bu1.bind("<Button-1>", clicked)
high2.bind("<Button-1>", clicked)
self.bu2.bind("<Button-1>", clicked)
high3.bind("<Button-1>", clicked)
self.bu3.bind("<Button-1>", clicked)
high4.bind("<Button-1>", clicked)
self.bu4.bind("<Button-1>", clicked)
def loadItems(self):
theItems = self.loadItem.item()
for i in range(0, 500):
none = Frame(self.innerFrame, width=200, height=500, bg="red")
none.pack_propagate(False)
none.pack(side=TOP, padx=10, pady=10)
let = Label(none, text=i)
let.pack(side=TOP)
root = Tk()
root.geometry("700x650")
root.resizable(0,0)
app = App(root)
root.mainloop()
I think you're exceeding the limits of the tkinter canvas. The frame you're trying to scroll is 250,000 pixels tall. I doubt the canvas can handle that.
When I make all of your inner widgets considerably smaller your code works fine.

Adding a scrollbar to a frame using Tkinter (Python)

I've a simple GUI thats shows the users some options, after putting the number of the initial options to be shown. In this case, 4:
By clicking on Add row you can add a row to the GUI. The thing is that if the user wants 100 options, the GUI becomes extra big and all the options are not shown.
So I would like to have a scrollbar only on the options space, not the rest parts. Sorry for the bad Photoshop, but I would like to have something like this:
The options space is the FrameTwo, so I would like to have the entire FrameTwo inside of scrollbar like the image above.
# -*- coding: utf-8 -*-
from Tkinter import *
import Image
import ImageTk
import tkFileDialog
import datetime
class Planificador(Frame):
def __init__(self,master):
Frame.__init__(self, master)
self.master = master
self.initUI()
def initUI(self):
self.master.title("Plan")
self.frameOne = Frame(self.master)
self.frameOne.grid(row=0,column=0)
self.frameTwo = Frame(self.master)
self.frameTwo.grid(row=1, column=0)
self.frameThree = Frame(self.master)
self.frameThree.grid(row=2, column=0)
# Borrar esto?
self.txt = Text(self)
self.txt.pack(fill=BOTH, expand=1)
self.piezastext = Label(self.frameOne, text = " Amount of pieces ", justify="center")
self.piezastext.grid(row=1, column=0)
self.entrypiezas = Entry(self.frameOne,width=3)
self.entrypiezas.grid(row=2, column=0, pady=(5,5))
self.aceptarnumpiezas = Button(self.frameOne,text="Click me", command=self.aceptar_piezas,width=8)
self.aceptarnumpiezas.grid(row=6, column=0, pady=(5,5))
def aceptar_piezas(self):
try:
val = int(self.entrypiezas.get())
self.aceptar_piezas_ok()
except ValueError:
showerror('Error', "Introduce un numero")
def aceptar_piezas_ok(self):
self.num_piezas = self.entrypiezas.get()
self.piezastext.grid_remove()
self.entrypiezas.grid_remove()
self.aceptarnumpiezas.grid_remove()
self.optionmenus_piezas = list()
self.numpiezas = []
self.numerolotes = []
self.optionmenus_prioridad = list()
self.lotes = list()
self.mispiezas = ['One', 'Two', 'Three', 'Four', 'Five']
self.n = 1
while self.n <= int(self.num_piezas):
self.textopieza = Label(self.frameTwo, text = "Pieza: ", justify="left")
self.textopieza.grid(row=self.n, column=0)
var = StringVar()
menu = OptionMenu(self.frameTwo, var, *self.mispiezas)
menu.config(width=10)
menu.grid(row=self.n, column=1)
var.set("One")
self.optionmenus_piezas.append((menu, var))
self.numpiezastext = Label(self.frameTwo, text = "Numero de piezas: ", justify="center")
self.numpiezastext.grid(row=self.n, column=2, padx=(10,0))
self.entrynumpiezas = Entry(self.frameTwo,width=6)
self.entrynumpiezas.grid(row=self.n, column=3, padx=(0,10))
self.entrynumpiezas.insert(0, "0")
self.textoprioridad = Label(self.frameTwo, text = "Prioridad: ", justify="center")
self.textoprioridad.grid(row=self.n, column=4)
var2 = StringVar()
menu2 = OptionMenu(self.frameTwo, var2, "Normal", "Baja", "Primera pieza", "Esta semana")
menu2.config(width=10)
menu2.grid(row=self.n, column=5)
var2.set("Normal")
self.optionmenus_prioridad.append((menu2, var2))
self.lotestext = Label(self.frameTwo, text = "Por lotes?", justify="center")
self.lotestext.grid(row=self.n, column=6, padx=(10,0))
self.var1 = IntVar()
self.entrynumlotes = Checkbutton(self.frameTwo, variable=self.var1)
self.entrynumlotes.grid(row=self.n, column=7, padx=(5,10))
self.lotes.append(self.var1)
self.numpiezas.append(self.entrynumpiezas)
self.n += 1
self.anadirpiezas = Button(self.frameThree, text="Add row", command=self.addpieza, width=10)
self.anadirpiezas.grid(row=0, column=2, pady=(10,10))
self.calculotext = Label(self.frameThree, text = "Other stuff ")
self.calculotext.grid(row=1, column=2, padx=(10,0), pady=(10,10))
self.graspbutton = Button(self.frameThree, text="OPT 1", width=10)
self.graspbutton.grid(row=2, column=1)
self.parettobutton = Button(self.frameThree, text="OPT 2",width=10)
self.parettobutton.grid(row=2, column=2, pady=(10,10), padx=(10,0))
self.parettoEvolbutton = Button(self.frameThree, text="OPT 2", width=10)
self.parettoEvolbutton.grid(row=2, column=3, pady=(10,10), padx=(10,0))
def addpieza(self):
self.textopiezanuevo = Label(self.frameTwo, text = "Pieza: ", justify="left")
self.textopiezanuevo.grid(row=int(self.num_piezas)+1, column=0)
var = StringVar()
menu = OptionMenu(self.frameTwo, var, *self.mispiezas)
menu.grid(row=self.n, column=1)
menu.config(width=10)
menu.grid(row=int(self.num_piezas)+1, column=1)
var.set("One")
self.optionmenus_piezas.append((menu, var))
self.numpiezastext = Label(self.frameTwo, text = "Numero de piezas: ", justify="center")
self.numpiezastext.grid(row=int(self.num_piezas)+1, column=2, padx=(10,0))
self.entrynumpiezas = Entry(self.frameTwo,width=6)
self.entrynumpiezas.grid(row=int(self.num_piezas)+1, column=3, padx=(0,10))
self.entrynumpiezas.insert(0, "0")
self.textoprioridad = Label(self.frameTwo, text = "Prioridad: ", justify="center")
self.textoprioridad.grid(row=int(self.num_piezas)+1, column=4)
var2 = StringVar()
menu2 = OptionMenu(self.frameTwo, var2, "Normal", "Baja", "Primera pieza", "Esta semana")
menu2.config(width=10)
menu2.grid(row=int(self.num_piezas)+1, column=5)
var2.set("Normal")
self.optionmenus_prioridad.append((menu2, var2))
self.lotestext = Label(self.frameTwo, text = "Por lotes?", justify="center")
self.lotestext.grid(row=int(self.num_piezas)+1, column=6, padx=(10,0))
self.var1 = IntVar()
self.entrynumlotes = Checkbutton(self.frameTwo, variable=self.var1)
self.entrynumlotes.grid(row=int(self.num_piezas)+1, column=7, padx=(5,10))
self.lotes.append(self.var1)
self.numpiezas.append(self.entrynumpiezas)
self.num_piezas = int(self.num_piezas)+1
if __name__ == "__main__":
root = Tk()
aplicacion = Planificador(root)
root.mainloop()
FrameOne is used to put an image I removed to make this example more simple. And FrameThree are the buttons you can see at the bottom of the GUI.
So it would be very helpful if someone could give me a hand and tell me how to put the entire FrameTwo inside of a scrollbar as you can see on the third image.
Thanks in advance.
One of your problems, is that "frameTwo" has no limits to it's size. If you don't limit it's size, any scrollbar you add, never will act. But limiting the size of you frame have the inconvenient of limit the number of lines you can grid, making the scrollbar useless again.
A solution is creating a frame inside the "frameTwo", to receive the pieces you create. This way, by one hand, allow you to limit the size of "frameTwo" and attach the scrollbar to it, and by other hand, allow you to grid the pieces you add to the frame located inside "frameTwo", named, let's say, "ListFrame". when "ListFrame" size becomes bigger than "frameTwo" size, you can now make the scrollbar work.
I change your code with the changes mentioned above. Check it out.
The changes are commented in the code.
Sorry for the short explanation, but i'm a bit hurry. I may edit this answer when I have more time.
PS: Sorry if my english is not the best
# -*- coding: utf-8 -*-
from Tkinter import *
import Image
import ImageTk
import tkFileDialog
import datetime
class Planificador(Frame):
def __init__(self,master):
Frame.__init__(self, master)
self.master = master
self.initUI()
def initUI(self):
self.master.title("Plan")
self.frameOne = Frame(self.master)
self.frameOne.grid(row=0,column=0)
self.frameTwo = Frame(self.master)
self.frameTwo.grid(row=1, column=0)
#Creating of a new frame, inside of "frameTwo" to the objects to be inserted
#Creating a scrollbar
#The reason for this, is to attach the scrollbar to "FrameTwo", and when the size of frame "ListFrame" exceed the size of frameTwo, the scrollbar acts
self.canvas=Canvas(self.frameTwo)
self.listFrame=Frame(self.canvas)
self.scrollb=Scrollbar(self.master, orient="vertical",command=self.canvas.yview)
self.scrollb.grid(row=1, column=1, sticky='nsew') #grid scrollbar in master, but
self.canvas['yscrollcommand'] = self.scrollb.set #attach scrollbar to frameTwo
self.canvas.create_window((0,0),window=self.listFrame,anchor='nw')
self.listFrame.bind("<Configure>", self.AuxscrollFunction)
self.scrollb.grid_forget() #Forget scrollbar because the number of pieces remains undefined by the user. But this not destroy it. It will be "remembered" later.
self.canvas.pack(side="left")
self.frameThree = Frame(self.master)
self.frameThree.grid(row=2, column=0)
# Borrar esto?
self.txt = Text(self)
self.txt.pack(fill=BOTH, expand=1)
self.piezastext = Label(self.frameOne, text = " Amount of pieces ", justify="center")
self.piezastext.grid(row=1, column=0)
self.entrypiezas = Entry(self.frameOne,width=3)
self.entrypiezas.grid(row=2, column=0, pady=(5,5))
self.aceptarnumpiezas = Button(self.frameOne,text="Click me", command=self.aceptar_piezas,width=8)
self.aceptarnumpiezas.grid(row=6, column=0, pady=(5,5))
def AuxscrollFunction(self,event):
#You need to set a max size for frameTwo. Otherwise, it will grow as needed, and scrollbar do not act
self.canvas.configure(scrollregion=self.canvas.bbox("all"),width=600,height=500)
def aceptar_piezas(self):
#IMPORTANT!!! All the objects are now created in "ListFrame" and not in "frameTwo"
#I perform the alterations. Check it out
try:
val = int(self.entrypiezas.get())
self.aceptar_piezas_ok()
self.scrollb.grid(row=1, column=1, sticky='nsew') #grid scrollbar in master, because user had defined the numer of pieces
except ValueError:
showerror('Error', "Introduce un numero")
def aceptar_piezas_ok(self):
self.num_piezas = self.entrypiezas.get()
self.piezastext.grid_remove()
self.entrypiezas.grid_remove()
self.aceptarnumpiezas.grid_remove()
self.optionmenus_piezas = list()
self.numpiezas = []
self.numerolotes = []
self.optionmenus_prioridad = list()
self.lotes = list()
self.mispiezas = ['One', 'Two', 'Three', 'Four', 'Five']
self.n = 1
while self.n <= int(self.num_piezas):
self.textopieza = Label(self.listFrame, text = "Pieza: ", justify="left")
self.textopieza.grid(row=self.n, column=0)
var = StringVar()
menu = OptionMenu(self.listFrame, var, *self.mispiezas)
menu.config(width=10)
menu.grid(row=self.n, column=1)
var.set("One")
self.optionmenus_piezas.append((menu, var))
self.numpiezastext = Label(self.listFrame, text = "Numero de piezas: ", justify="center")
self.numpiezastext.grid(row=self.n, column=2, padx=(10,0))
self.entrynumpiezas = Entry(self.listFrame,width=6)
self.entrynumpiezas.grid(row=self.n, column=3, padx=(0,10))
self.entrynumpiezas.insert(0, "0")
self.textoprioridad = Label(self.listFrame, text = "Prioridad: ", justify="center")
self.textoprioridad.grid(row=self.n, column=4)
var2 = StringVar()
menu2 = OptionMenu(self.listFrame, var2, "Normal", "Baja", "Primera pieza", "Esta semana")
menu2.config(width=10)
menu2.grid(row=self.n, column=5)
var2.set("Normal")
self.optionmenus_prioridad.append((menu2, var2))
self.lotestext = Label(self.listFrame, text = "Por lotes?", justify="center")
self.lotestext.grid(row=self.n, column=6, padx=(10,0))
self.var1 = IntVar()
self.entrynumlotes = Checkbutton(self.listFrame, variable=self.var1)
self.entrynumlotes.grid(row=self.n, column=7, padx=(5,10))
self.lotes.append(self.var1)
self.numpiezas.append(self.entrynumpiezas)
self.n += 1
self.anadirpiezas = Button(self.frameThree, text="Add row", command=self.addpieza, width=10)
self.anadirpiezas.grid(row=0, column=2, pady=(10,10))
self.calculotext = Label(self.frameThree, text = "Other stuff ")
self.calculotext.grid(row=1, column=2, padx=(10,0), pady=(10,10))
self.graspbutton = Button(self.frameThree, text="OPT 1", width=10)
self.graspbutton.grid(row=2, column=1)
self.parettobutton = Button(self.frameThree, text="OPT 2",width=10)
self.parettobutton.grid(row=2, column=2, pady=(10,10), padx=(10,0))
self.parettoEvolbutton = Button(self.frameThree, text="OPT 2", width=10)
self.parettoEvolbutton.grid(row=2, column=3, pady=(10,10), padx=(10,0))
def addpieza(self):
self.textopiezanuevo = Label(self.listFrame, text = "Pieza: ", justify="left")
self.textopiezanuevo.grid(row=int(self.num_piezas)+1, column=0)
var = StringVar()
menu = OptionMenu(self.listFrame, var, *self.mispiezas)
menu.grid(row=self.n, column=1)
menu.config(width=10)
menu.grid(row=int(self.num_piezas)+1, column=1)
var.set("One")
self.optionmenus_piezas.append((menu, var))
self.numpiezastext = Label(self.listFrame, text = "Numero de piezas: ", justify="center")
self.numpiezastext.grid(row=int(self.num_piezas)+1, column=2, padx=(10,0))
self.entrynumpiezas = Entry(self.listFrame,width=6)
self.entrynumpiezas.grid(row=int(self.num_piezas)+1, column=3, padx=(0,10))
self.entrynumpiezas.insert(0, "0")
self.textoprioridad = Label(self.listFrame, text = "Prioridad: ", justify="center")
self.textoprioridad.grid(row=int(self.num_piezas)+1, column=4)
var2 = StringVar()
menu2 = OptionMenu(self.listFrame, var2, "Normal", "Baja", "Primera pieza", "Esta semana")
menu2.config(width=10)
menu2.grid(row=int(self.num_piezas)+1, column=5)
var2.set("Normal")
self.optionmenus_prioridad.append((menu2, var2))
self.lotestext = Label(self.listFrame, text = "Por lotes?", justify="center")
self.lotestext.grid(row=int(self.num_piezas)+1, column=6, padx=(10,0))
self.var1 = IntVar()
self.entrynumlotes = Checkbutton(self.listFrame, variable=self.var1)
self.entrynumlotes.grid(row=int(self.num_piezas)+1, column=7, padx=(5,10))
self.lotes.append(self.var1)
self.numpiezas.append(self.entrynumpiezas)
self.num_piezas = int(self.num_piezas)+1
if __name__ == "__main__":
root = Tk()
aplicacion = Planificador(root)
root.mainloop()
You have option menus, labels, entry boxes, and checkbuttons in FrameTwo. How would you expect a scrollbar for the entire frame would work? Would it scroll all widgets at the same time? Tkinter scrollbars are generally attached to listboxes, canvases, entry widgets, and text fields. http://effbot.org/zone/tkinter-scrollbar-patterns.htm Come up with a simple example that illustrates the problem for further help.

Categories