Tkinter Scroll Window Does Not Scroll - user-interface

Probably an easy question for a Tkinter veteran but why can't I scroll in my window?
If you run this code and add multiple data ports with the button, you will see what I mean.
Can anyone modify my code to make the scroll window work please?
I am not very well versed in Tkinter yet as I am with other similar tools in other languages so I'm sure there's going to be a lot to edit here.
from tkinter import *
fields = 'Buffer Depth \n(# of max-sized packets)', 'Payload Size \n(Max=1500bytes) ', 'Duplicate Quantity'
entries =[]
root = Tk()
root.title(string= 'Buffer Testing Tool')#create window title
root.geometry('500x750')#main window dimensions
root.configure(bg= 'crimson')
canvas = Canvas(root, height = 1000)
scroll_y = Scrollbar(root, orient="vertical", command=canvas.yview)
frame = Frame()
options = ["Transmit", "Receive"]
def makeform(root, fields):#this will organize and align the labels of the entries plus the entry fields
numberCheck =0
for field in fields:
row = Frame(canvas)
if (numberCheck==0):
firstES = Label(row, text= "Data Port 1", anchor = 'center', fg = "blue")#first ES label
firstES.pack()
DPtype = Label(row, text = 'Type', width=19, anchor = 'nw')
DPtype.pack(side= LEFT)
clicked= StringVar()
clicked.set(options[0])
drop = OptionMenu(row, clicked, *options)
drop.pack(side = LEFT, padx=5, pady= 5)
numberCheck=1
row.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, clicked))
rowNew= Frame(canvas)
lab = Label(rowNew, width=20, text=field, anchor = 'w')
lab.pack(side=LEFT)
ent = Entry(rowNew)
ent.pack(side=RIGHT, expand = YES, fill=X)
rowNew.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, ent))
else:
lab = Label(row, width=20, text=field, anchor = 'w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady= 5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand = YES, fill=X)
entries.append((field, ent))
#return entries
def addEntryField():
next_row = int(len(entries)/4)+1
numberCheck =0
for field in fields:
row = Frame(canvas)
if (numberCheck==0):
nextES = Label(row, text= ('Data Port ' +str(next_row)), anchor = 'center', fg = "blue")
nextES.pack()
DPtype = Label(row, text = 'Type', width=19, anchor = 'nw')
DPtype.pack(side= LEFT)
clicked= StringVar()
clicked.set(options[0])
drop = OptionMenu(row, clicked, *options)
drop.pack(side = LEFT, padx=5, pady= 5)
numberCheck=1
row.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, clicked))
rowNew= Frame(canvas)
lab = Label(rowNew, width=20, text=field, anchor = 'w')
lab.pack(side=LEFT)
ent = Entry(rowNew)
ent.pack(side=RIGHT, expand = YES, fill=X)
rowNew.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, ent))
else:
lab = Label(row, width=20, text=field, anchor = 'w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady= 5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand = YES, fill=X)
entries.append((field, ent))
#return entries
if __name__=='__main__':
b1 = Button(root, text = 'Generate XML File', command=root.quit, anchor = 'center')
b1.pack(side= BOTTOM, padx=5, pady=5)
b2 = Button(root, text = 'Run TTE-Build', command=root.quit, anchor = 'center')
b2.pack(side= BOTTOM, padx=5, pady=5)
b3 = Button(root, text = 'Run TTE-Plan', command=root.quit, anchor = 'center')
b3.pack(side= BOTTOM, padx=5, pady=5)
addEntryButton = Button(root, text= 'Add Data Port', fg = "Blue", command = addEntryField)
addEntryButton.pack(side= BOTTOM, anchor = 'n', padx=5, pady= 5)
ents = makeform(root, fields)#the creation of the window happens here
root.bind('<Return>', (lambda event, e=ents: fetch(e)))#after hitting 'Enter' this will collect the entered data from the user
canvas.create_window(0, 0, anchor= 'nw', window=frame)
canvas.update_idletasks()
canvas.configure(scrollregion=canvas.bbox("all"), yscrollcommand=scroll_y.set)
canvas.pack(fill='both', expand=True, side='left')
scroll_y.pack(fill='y', side='right')
root.mainloop()
def fetch(entries):#this will print what what the entry fields are named plus what is written down in the entry fields (regardless of the # of fields)
for entry in entries:
field = entry[0]
text = entry[1].get()#collect the entry for the fields
print('%s: "%s"' % (field, text))
def Message1():
XMLdone = Label(root, text= "XML File Generated!!")
XMLdone.pack()
def Message2():
XMLdone = Label(root, text= "TTE-Plan has been completed!!")
XMLdone.pack()
def Message3():
XMLdone = Label(root, text= "TTE-Build has been completed!!")
XMLdone.pack()
#Note: The Payload Size must always be greater than or equal to 18 bytes less than the corresponding VL.

There are several problems with the code. The first is that the frame you're adding to the canvas isn't a child of the canvas, but it needs to be. You should also give this window a more descriptive name than just frame.
So, create the frame like this:
canvas = Canvas(root, height = 1000)
scroll_y = Scrollbar(root, orient="vertical", command=canvas.yview)
inner_frame = Frame(canvas)
canvas.create_window(0, 0, anchor= 'nw', window=inner_frame)
The second problem is that you're not updating the scrollregion of the canvas with the inner frame changes. This is typically done by adding a binding to the <Configure> event of the inner frame:
inner_frame.bind("<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all")))
The third problem is that you're adding rows to the canvas rather than to the frame. You need to make your rows children of this inner frame.
for field in fields:
row = Frame(inner_frame)
...
rowNew= Frame(inner_frame)
...

Related

Tkinter: Widget not being applied to the top right hand corner of the screen(grid)

I want to make a GUI for a voice assistant and for that when I try to use the grid option the label's get aligned at the centre of the screen when specified as column 2/3/4/5.
import tkinter
from tkinter import Canvas, Frame, Image, Label, StringVar, Tk, font
from tkinter.constants import ANCHOR, BOTTOM, E, END, GROOVE, RAISED, RIDGE, RIGHT, SUNKEN, TOP, Y
from typing import Text
window = tkinter.Tk()
window.title("App name")
window.geometry("320x640")
f = Frame(window)
x = f.grid_size()
# Add image file
bg = tkinter.PhotoImage(file = "Greybg.png")
# Show image using label
label1 = tkinter.Label( window, image = bg)
label1.place(x = 0, y = 0)
userimg = tkinter.PhotoImage(file = 'user1.png')
userlabel = tkinter.Label(window, image = userimg, bg = '#3D4154')
userlabel.place(relx = 1.0, rely = 0.01, anchor = 'ne')
def clicked():
print("Wow no error")
# Creating a photoimage object to use image
photo = tkinter.PhotoImage(file = "mic.png")
# here, image option is used to
# set image on button
micbtn = tkinter.Button(window, text = 'Click Me !', image = photo, bg = '#808588', border = 0, command = clicked).place(x = 142,y=580)
string_variable = tkinter.StringVar()
string_variable.set("User Text Here")
text = tkinter.Label(window, textvariable = string_variable, bg = "#80EAF7", wraplength= 250, pady = 1, padx = 1, fg = '#020402')
text.grid(row = 0, column=1, sticky=E,)
string_variable1 = tkinter.StringVar()
string_variable1.set("Assistant Reply here")
text1 = tkinter.Label(window, textvariable = string_variable1, wraplength= 250, pady = 1, padx = 1, fg = '#020402', font = ('Helvetica',8,'bold'))
text1.grid(row = 1, column=0)
window.resizable(0, 0)
window.mainloop()
In the above code, the icons get aligned like this, whereas I want the "User Text Here" to be at the top right-hand corner of the screen, how do I do that?
You can make columns 0 and 1 to use all the horizontal available space using
window.columnconfigure((0,1), weight=1)
Credit to https://stackoverflow.com/users/5317403/acw1668

I am having problems with getting my window formatted. I have tried all of the pack combinations I can think of but no success

Here is the code I currently am using but it produces a mess.
the space between the left treeview and the scollbar is to wide
the buttons should be aligned in the center of the window to the right of the left scroll bar.
the right treeview is too low.
Here is my current code:
nbWindow.add(frmLink, text="Link")
treLink1 = ttk.Treeview(frmLink)
treLink1["show"] = "headings"
treLink1["columns"] = ("one", "two")
treLink1.column("one", width=200)
treLink1.column("two", width=20)
treLink1.heading("one", text="Field Name")
treLink1.heading("two", text="Field Key")
# attach scrollbar
scrollbarLink = Scrollbar(frmLink)
scrollbarLink.config(command=treLink1.yview)
treLink1.configure(yscrollcommand=scrollbarLink.set)
treLink1.pack(side=LEFT, padx=30, pady=30, fill="both")
scrollbarLink.pack(side=RIGHT, padx=0, pady=30, fill=Y)
#add movement buttons
#button to add new field
btAddFieldLink = Button(frmLink, text="Add Field")
btAddFieldLink.config(height=2, width=10)
btAddFieldLink.pack(pady=30, fill=Y)
# button move down,
btMoveDownLink = Button(frmLink, text="Move Down")
btMoveDownLink.config(height=2, width=10)
btMoveDownLink.pack(pady=0)
# button move up
btMoveUpLink = Button(frmLink, text=" Move Up ")
btMoveUpLink.config(height=2, width=10)
btMoveUpLink.pack()
# button delete field
btDeleteFieldLink = Button(frmLink, text="Delete Field")
btDeleteFieldLink.config(height=2, width=10)
btDeleteFieldLink.pack()
#format link view
treLink3 = ttk.Treeview(frmLink)
treLink3["show"] = "headings"
treLink3["columns"] = ("one", "two")
treLink3.column("one", width=5)
treLink3.column("two", width=200)
treLink3.heading("one", text="TName")
treLink3.heading("two", text="Field Name")
# attach scrollbar
scrollbarLink1 = Scrollbar(frmLink)
scrollbarLink1.config(command=treLink3.yview)
treLink3.configure(yscrollcommand=scrollbarLink1.set)
treLink3.pack(side=RIGHT)
scrollbarLink.pack(side=LEFT)
Have you tried adding all the groups of elements in their own frame?
Something like this:
import tkinter as tk
root = tk.Tk()
def createlabels(root, stack):
for i in stack:
tk.Label(root,text=i).pack()
stack1 = ['one','two','three','four']
stack2 = ['five','six','seven','eight']
stack3 = ['nine','ten','eleven','twelve']
f1 = tk.Frame(root, bg="#ff0000")
f2 = tk.Frame(root, bg="#00ff00")
f3 = tk.Frame(root, bg="#0000ff")
createlabels(f1,stack1)
createlabels(f2,stack2)
createlabels(f3,stack3)
f1.pack(fill=tk.BOTH, side=tk.LEFT)
f2.pack(fill=tk.BOTH, expand=1)
f3.pack(fill=tk.BOTH, expand=1)
tk.mainloop()

Problem about transfer value and combobox at wxPython

Hi I'm wxpython newbie.
and an week before I was upload my question and not yet solve.
so Today I need more help about my problem
so here is the code....
# -*- coding:utf-8 -*-
import wx
import sqlite3
from PIL import Image # for image processing
from wx.adv import Animation, AnimationCtrl # for gif Animation
conn = sqlite3.connect('reference_file.rre')
cur = conn.cursor()
class MyApp(wx.App):
def OnInit(self):
self.frame = errorCode_SAC(None, title ="Guide")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
class errorCode_SAC(wx.Frame):
# constructor
def __init__(self, parent, id=wx.ID_ANY, title="Search", pos=wx.DefaultPosition, size=(1500,650), style=wx.DEFAULT_FRAME_STYLE, name=""):
super(errorCode_SAC, self).__init__(parent, id, title, pos, size, style, name="")
self.Panel_err_sac = wx.Panel(self,wx.ID_ANY, pos=(0,0), size=(774, 608))
self.Panel_dd = wx.Panel(self, wx.ID_ANY, pos=(777,0), size=(1,608))
self.Panel_err_sac_result = wx.Panel(self,wx.ID_ANY, pos=(778,0), size=(706, 308))
self.Panel_err_image = wx.Panel(self,wx.ID_ANY, pos=(778,309), size=(706,300))
self.explBox_err_sac = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ Instruction ]", pos = (8,10), size=(756, 200))
self.lbname1 = wx.StaticText(self.explBox_err_sac, label="1.input name.",pos=(10,20))
self.sa_ra_code_box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ input model ]", pos=(8,230), size=(340,80))
self.sa_err_code_CeNa = wx.TextCtrl(self.sa_ra_code_box, wx.ID_ANY, pos=(8,30), size=(260,22))
self.button = wx.Button(self.sa_ra_code_box, wx.ID_OK, label="search", size=(50,23), pos = (280,30))
self.button.SetDefault()
self.sa_er_Box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ Search by input name ]", pos = (8,320), size = (340,280))
self.sa_er_inputkw = wx.StaticText(self.sa_er_Box, label="",pos=(8,15), size=(10,40), style=wx.ALIGN_LEFT)
self.sa_er_middle = wx.StaticText(self.sa_er_Box, label=" by", pos=(50,15))
self.sa_er_middle = wx.StaticText(self.sa_er_Box, label="", pos=(8,30))
self.sa_er_footer = wx.StaticText(self.sa_er_Box, label=" searched",pos=(50,30))
self.sa_er_svlist = wx.ListCtrl(self.sa_er_Box, -1, pos = (8,60), size = (330,200), style = wx.LC_REPORT | wx.SUNKEN_BORDER)
self.sa_er_svlist.InsertColumn(0,"model")
self.sa_er_svlist.InsertColumn(1,"spec")
self.sa_er_svlist.SetColumnWidth(0,100)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.sa_err_catelist_OnClick, self.sa_er_svlist)
self.button.Bind(wx.EVT_BUTTON, self.sa_err_search_OnButton)
self.sa_er_result_Box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ check list ]", pos=(360,230), size =(405,370))
self.sa_er_question_ti = wx.StaticText(self.sa_er_result_Box, label="", pos=(50,20), size = (130,-1))
self.sa_er_question_text = wx.StaticText(self.sa_er_result_Box, label="point", pos = (10,50), size = (130,-1))
self.sa_er_question_te = wx.StaticText(self.sa_er_result_Box, label="", pos=(50,50), size = (130,-1))
self.P_err_sac_case1 = wx.StaticBox(self.Panel_err_sac_result, wx.ID_ANY, "[ check list below ]", pos = (8,10), size=(690,60))
self.P_err_sac_case2 = wx.StaticBox(self.Panel_err_sac_result, wx.ID_ANY, "[ symptom ]", pos=(8,90), size =(690,200))
self.cas2_symp = wx.StaticText(self.P_err_sac_case2, label="selected symptom is..", pos=(10,20))
self.cas2_symp_text = wx.StaticText(self.P_err_sac_case2, label="", pos=(10,40))
self.cas2_descrip = wx.StaticText(self.P_err_sac_case2, label="cause....", pos=(10,70))
self.cas2_descrip_text = wx.StaticText(self.P_err_sac_case2, label="", pos=(10,90))
# -- Combo box
items=[] # Dummy list
self.cb = wx.ComboBox(self.P_err_sac_case1, pos=(10,30),size=(500,20), choices=items, style=wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.OnSelectComboBox)
# -- search query
def sa_err_search_OnButton(self, e):
self.sa_er_inputkw.SetLabel(self.sa_err_code_CeNa.GetValue())
searchResult = "%"+self.sa_err_code_CeNa.GetValue()+"%"
self.sa_er_svlist.DeleteAllItems()
sa_err_code_CeNa = cur.execute("Select * from sa_er_cate where cate like '"+searchResult+"'")
count = 0
for i in sa_err_code_CeNa:
self.sa_er_svlist.Append(i[1:3])
count = count +1
self.sa_er_middle.SetLabel(str(count))
self.Bind(wx.EVT_CLOSE, self.on_close)
def on_close(self,e):
self.Destroy()
def sa_err_catelist_OnClick(self, event):
sa_idx = event.GetIndex()
sa_err_check = self.sa_er_svlist.GetItem(sa_idx, 0).GetText()
sa_err_check_Comment = cur.execute("select cate,chek_comment from sa_er_cate where cate ='%s'" %sa_err_check)
for row in sa_err_check_Comment:
self.sa_er_question_ti.SetLabel(row[0])
self.sa_er_question_te.SetLabel(row[1])
model_name_string = row[0]
result_query_1 = cur.execute("Select symp from sac_er_ramp where cate='%s'" % model_name_string)
list=[]
for row_test in result_query_1:
list.append(row_test[0])
self.cb.SetItems(list)
def OnSelectComboBox(self,event):
item = event.GetString()
result_query_2 = cur.execute("Select symp, descrip, judgement,image from sac_er_ramp where symp='%s'" % item)
for row in result_query_2:
self.cas2_symp_text.SetLabel(row[0])
self.cas2_descrip_text.SetLabel(row[1])
imageno = row[3]
# -- IMAGE
erim = Image.open('./image/image_error_ramp/%s.webp' % imageno)
erim.info.pop('background',None)
erim.save('./image/image_error_ramp/%s.gif' % imageno,save_all=True, loop=0)
anim = Animation('./image/image_error_ramp/%s.gif' % imageno)
ctrl = AnimationCtrl(self.Panel_err_image, -1,anim, pos=(35,40))
ctrl.Play()
os.remove('./image/image_error_ramp/%s.gif' % imageno)
if __name__=="__main__":
app = MyApp(False)
app.MainLoop()
and progress of this code is below
input "model name" at textctrl
search "relate model" and button bind to event (to get a specific model name)
select a "model" from listctrl bind to event (to get a combobox's elements)
and combobox's list fill with relate list (list's element bring from sqlie)
select a combobox element and relate image is shown (image is animated GIF)
and below is my problem
when I select combobox list and Animated GIF is played at panel.
and select combobox's another element, Animated GIF play another and image is overlap
below code...image convert and play code... i call this code "IMAGE"
(I saved all Animated GIF to webp and convert to gif that time)
erim = Image.open('./image/image_error_ramp/%s.webp' % imageno)
erim.info.pop('background',None)
erim.save('./image/image_error_ramp/%s.gif' % imageno,save_all=True, loop=0)
anim = Animation('./image/image_error_ramp/%s.gif' % imageno)
ctrl = AnimationCtrl(self.Panel_err_image, -1,anim, pos=(35,40))
ctrl.Play()
os.remove('./image/image_error_ramp/%s.gif' % imageno)
So I think maybe Solve the problem to move "IMAGE" code locate below the constructor code(because init constructor is there.)
# constructor
def __init__(self, parent, id=wx.ID_ANY, title="Search", pos=wx.DefaultPosition, size=(1500,650), style=wx.DEFAULT_FRAME_STYLE, name=""):
IMAGE CODE
and here(below the constructor code) I can't get imageno (imageno is image's name. and this name bring from sqlite, so I select a element from a combobox but I can't get any response from combobox)
and my problem is this
Can I get the image's name from the sqlite at the below of constructor code with combobox?
or otherwise at original location(below the annotation "IMAGE") any code for "Animated GIF not overlapping" ?
ps. week a go robin dunn and rolf of saxony teach me about this problem
But I can't Understand and very depressed.....
Have a Niceday
It's quite difficult to know where to start with this answer, because there are coding errors, logical errors and I do not know what the data looks like.
However, several things stand out.
sqlite queries need a fetch to return the row/rows
use fetchone(), fetchmany(n) or fetchall()
When testing print() is your friend, if not using an IDE
print the result/s to check you have what you expect
Always assume that an error could have happened, test with if or try for example
Initialise variables, especially if you are setting them in an if statement
Assume the test could fail.
That said, I applaud your go for it attitude but you could have done this in smaller steps. Master each step before attempting to put them all together.
Here is a version of your code, that comes with many caveats.
I don't know your data or data structure.
I have started by creating some dummy records in my database.
I don't know your objectives or the logic.
Only those issues I needed to address to get a basically functioning program have been addressed and I've removed some code around the image processing to help me not you.
Hopefully, you can find some benefit in the code below.
I recommend using "diff" on my code versus yours, to see what has changed.
import wx
import sqlite3
from PIL import Image # for image processing
from wx.adv import Animation, AnimationCtrl # for gif Animation
conn = sqlite3.connect('reference_file.rre', isolation_level=None)
conn.row_factory = sqlite3.Row
cur = conn.cursor()
result = cur.execute("create table if not exists sa_er_cate (cate TEXT PRIMARY KEY NOT NULL,chek_comment TEXT)");
result = cur.execute("create table if not exists sa_er_ramp (cate TEXT PRIMARY KEY NOT NULL, symp TEXT, descrip TEXT, judgement TEXT,image TEXT)");
# Define a default data
cur.execute("select * from sa_er_cate where (cate=?)",["no1"]);
MyCate = cur.fetchone()
if not MyCate:
try:
conn.execute("insert into sa_er_cate (cate, chek_comment) values (?,?)"\
,("no1","comment 1"));
except sqlite3.Error as e:
print('Default Cate Insert Error '+str(e), 'Error')
try:
conn.execute("insert into sa_er_cate (cate, chek_comment) values (?,?)"\
,("no2","comment 2"));
except sqlite3.Error as e:
print('Default Cate Insert Error '+str(e), 'Error')
cur.execute("select * from sa_er_ramp where (cate=?)",["no1"]);
MySymp = cur.fetchone()
if not MySymp:
try:
conn.execute("insert into sa_er_ramp (cate, symp, descrip, judgement, image) values (?,?,?,?,?)"\
,("no1","no1","description 1","judgement 1","Image1"));
except sqlite3.Error as e:
print('Default Symp Insert Error '+str(e), 'Error')
try:
conn.execute("insert into sa_er_ramp (cate,symp, descrip, judgement, image) values (?,?,?,?,?)"\
,("no2","no2","description 2","judgement 2","Image2"));
except sqlite3.Error as e:
print('Default Symp Insert Error '+str(e), 'Error')
class MyApp(wx.App):
def OnInit(self):
self.frame = errorCode_SAC(None, title ="Guide")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
class errorCode_SAC(wx.Frame):
# constructor
def __init__(self, parent, id=wx.ID_ANY, title="Search", pos=wx.DefaultPosition, size=(1500,650), style=wx.DEFAULT_FRAME_STYLE, name=""):
super(errorCode_SAC, self).__init__(parent, id, title, pos, size, style, name="")
self.Panel_err_sac = wx.Panel(self,wx.ID_ANY, pos=(0,0), size=(774, 608))
self.Panel_dd = wx.Panel(self, wx.ID_ANY, pos=(777,0), size=(1,608))
self.Panel_err_sac_result = wx.Panel(self,wx.ID_ANY, pos=(778,0), size=(706, 308))
self.Panel_err_image = wx.Panel(self,wx.ID_ANY, pos=(778,309), size=(706,300))
self.explBox_err_sac = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ Instruction ]", pos = (8,10), size=(756, 200))
self.lbname1 = wx.StaticText(self.explBox_err_sac, label="1.input name.",pos=(10,20))
self.sa_ra_code_box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ input model ]", pos=(8,230), size=(340,80))
self.sa_err_code_CeNa = wx.TextCtrl(self.sa_ra_code_box, wx.ID_ANY, pos=(8,30), size=(260,22))
self.button = wx.Button(self.sa_ra_code_box, wx.ID_OK, label="search", size=(50,23), pos = (280,30))
self.button.SetDefault()
self.sa_er_Box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ Search by input name ]", pos = (8,320), size = (340,280))
self.sa_er_inputkw = wx.StaticText(self.sa_er_Box, label="",pos=(8,15), size=(10,40), style=wx.ALIGN_LEFT)
self.sa_er_middle = wx.StaticText(self.sa_er_Box, label=" by", pos=(50,15))
self.sa_er_middle = wx.StaticText(self.sa_er_Box, label="", pos=(8,30))
self.sa_er_footer = wx.StaticText(self.sa_er_Box, label=" searched",pos=(50,30))
self.sa_er_svlist = wx.ListCtrl(self.sa_er_Box, -1, pos = (8,60), size = (330,200), style = wx.LC_REPORT | wx.SUNKEN_BORDER)
self.sa_er_svlist.InsertColumn(0,"model")
self.sa_er_svlist.InsertColumn(1,"spec")
self.sa_er_svlist.SetColumnWidth(0,100)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.sa_err_catelist_OnClick, self.sa_er_svlist)
self.button.Bind(wx.EVT_BUTTON, self.sa_err_search_OnButton)
self.sa_er_result_Box = wx.StaticBox(self.Panel_err_sac, wx.ID_ANY, "[ check list ]", pos=(360,230), size =(405,370))
self.sa_er_question_ti = wx.StaticText(self.sa_er_result_Box, label="", pos=(50,20), size = (130,-1))
self.sa_er_question_text = wx.StaticText(self.sa_er_result_Box, label="point", pos = (10,50), size = (130,-1))
self.sa_er_question_te = wx.StaticText(self.sa_er_result_Box, label="", pos=(50,50), size = (130,-1))
self.P_err_sac_case1 = wx.StaticBox(self.Panel_err_sac_result, wx.ID_ANY, "[ check list below ]", pos = (8,10), size=(690,80))
self.P_err_sac_case2 = wx.StaticBox(self.Panel_err_sac_result, wx.ID_ANY, "[ symptom ]", pos=(8,110), size =(690,200))
self.cas2_symp = wx.StaticText(self.P_err_sac_case2, label="selected symptom is..", pos=(10,20))
self.cas2_symp_text = wx.StaticText(self.P_err_sac_case2, label="", pos=(10,40))
self.cas2_descrip = wx.StaticText(self.P_err_sac_case2, label="cause....", pos=(10,70))
self.cas2_descrip_text = wx.StaticText(self.P_err_sac_case2, label="", pos=(10,90))
# -- Combo box
items=[] # Dummy list
self.cb = wx.ComboBox(self.P_err_sac_case1, pos=(10,30),size=(500,30), choices=items, style=wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.OnSelectComboBox)
self.Bind(wx.EVT_CLOSE, self.on_close)
# -- search query
def sa_err_search_OnButton(self, e):
self.sa_er_inputkw.SetLabel(self.sa_err_code_CeNa.GetValue())
searchResult = "%"+self.sa_err_code_CeNa.GetValue()+"%"
self.sa_er_svlist.DeleteAllItems()
sa_err_code_CeNa = cur.execute("Select * from sa_er_cate where cate like '"+searchResult+"'")
rows = cur.fetchall()
count = 0
for i in rows:
self.sa_er_svlist.Append(i[0:3])
count += 1
self.sa_er_middle.SetLabel(str(count))
def on_close(self,e):
self.Destroy()
def sa_err_catelist_OnClick(self, event):
sa_idx = event.GetIndex()
sa_err_check = self.sa_er_svlist.GetItem(sa_idx, 0).GetText()
print("1",sa_err_check)
sa_err_check_Comment = cur.execute("select cate,chek_comment from sa_er_cate where cate ='%s'" %sa_err_check)
row = cur.fetchone()
print("2",row)
if row:
self.sa_er_question_ti.SetLabel(row[0])
self.sa_er_question_te.SetLabel(row[1])
print (row)
model_name_string = row[0]
result_query_1 = cur.execute("Select symp from sa_er_ramp where cate='%s'" % model_name_string)
rows = cur.fetchall()
res_list=["Select an option"]
for row_test in rows:
res_list.append(row_test[0])
self.cb.SetItems(res_list)
self.cb.SetSelection(0)
print(res_list)
self.Refresh()
def OnSelectComboBox(self,event):
item = event.GetString()
result_query_2 = cur.execute("Select symp, descrip, judgement,image from sa_er_ramp where symp='%s'" % item)
rows = cur.fetchall()
imageno = ""
for row in rows:
self.cas2_symp_text.SetLabel(row[0])
self.cas2_descrip_text.SetLabel(row[1])
imageno = row[3]
# -- IMAGE
print("Image selected:",imageno)
#erim = Image.open('./image/image_error_ramp/%s.webp' % imageno)
#erim.info.pop('background',None)
#erim.save('./image/image_error_ramp/%s.gif' % imageno,save_all=True, loop=0)
anim = Animation('./%s.gif' % imageno)
ctrl = AnimationCtrl(self.Panel_err_image, -1,anim, pos=(35,40))
ctrl.Play()
#os.remove('./image/image_error_ramp/%s.gif' % imageno)
if __name__=="__main__":
app = MyApp(False)
app.MainLoop()

Tkinter - Same event for multiple buttons

Using Tkinter, I have many buttons. I would like the same callback function to be triggered every time any of the buttons pressed. How can I find out which button was pressed ?
def call(p1):
# Which Button was pressed?
pass
for i in range (50):
B1 = Button(master, text = '...', width = 2)
B1.grid(row = i*20, column = 60)
B1.bind('<Button-1>',call)
B2 = Button(master, text = '...', width = 2)
B2.grid(row = i*20, column = 60)
B2.bind('<Button-1>',call)
Using a list to reference the dynamically created buttons and lambda to store a reference to the index of the button object. You can determine which button was clicked. In the below examples I use .cget("text") on the button object to demonstrate accessing the button widget.
import tkinter as tk
root = tk.Tk()
root.minsize(200, 200)
btn_list = [] # List to hold the button objects
def onClick(idx):
print(idx) # Print the index value
print(btn_list[idx].cget("text")) #Print the text for the selected button
for i in range(10):
# Lambda command to hold reference to the index matched with range value
b = tk.Button(root, text = 'Button #%s' % i, command = lambda idx = i: onClick(idx))
b.grid(row = i, column = 0)
btn_list.append(b) # Append the button to a list
root.mainloop()
Alternatively you can use bind and then access the widget from the event object generated.
import tkinter as tk
root = tk.Tk()
root.minsize(200, 200)
def onClick(event):
btn = event.widget # event.widget is the widget that called the event
print(btn.cget("text")) #Print the text for the selected button
for i in range(10):
b = tk.Button(root, text = 'Button #%s' % i)
b.grid(row = i, column = 0)
# Bind to left click which generates an event object
b.bind("<Button-1>", onClick)
root.mainloop()
#Steven Summers' first example seems most clear to me, but I think doing it without the list is even clearer.
The way I understood the question, you not only want to know which button was clicked but you also want each button to call one other, undescribed function (universal in my example below). In that case, you can use the very handy
combine_funcs (see: Have multiple commands when button is pressed) to call two functions from one widget.
Here is my code. Instead of a list, I simply have a string that is changed and printed with each click.
import tkinter as tk
root = tk.Tk()
root.minsize(200, 200)
buttonVal = ''
def combine_funcs(*funcs):
def combined_func(*args, **kwargs):
for f in funcs:
f(*args, **kwargs)
return combined_func
def universal():
print 'Universal function is called'
def button_check(buttonName):
buttonVal = buttonName
print buttonVal # Or whatever you want to do with the button info
for i in range(10):
B1 = tk.Button(root, text = 'Button #%s' % i, command = combine_funcs(universal, lambda buttonName = 'Button #%s' % i:button_check(buttonName)))
B1.grid(row = i, column = 0)
root.mainloop()
Use lambda:
B1 = Button(master, text = '...', width = 2, command = lambda: call('B1') )
And so on...
This might not be the simplest solution, but it is the only one I could come up with.
from Tkinter import *
master = Tk()
L = []
def call(p1):
for i in range(len(L)):
if str(L[i]) == str(p1.widget):
print 'Button' + str(i)
break
for i in range (50):
exec("Button" + str(i) + " = Button(master, text = '...', width = 2)")
exec("Button" + str(i) + ".grid(row = i*20, column = 60)")
exec("Button" + str(i) + ".bind('<Button-1>',call)")
s = 'L.append(str(Button' + str(i) + '))'
exec(s)

Python 2.7 Tkinter Change Label text on button event

Im very new to Python(2.7) im learning GUI design(Tkinter) and keep running into different syntax/no call method/global name not defined errors when trying to implement a simple label text change from a Entry object on button click. Can someone show me the correct syntax for the action
from Tkinter import *
class Part3:
def __init__(self, parent):
GUIFrame =Frame(parent,width= 300, height=200)
GUIFrame.pack(expand = False, anchor = CENTER)
entry = Entry(text="enter your choice")
entry.place(x=65, y = 10)
self.test = StringVar()
self.test.set('''Hi, I'm a Label :)''')
self.Label1 = Label(parent, textvariable = self.test)
self.Label1.place(x = 85, y = 100)
self.Button2 = Button(parent, text='edit',command=self.LabelChange)
self.Button2.place(x= 80, y = 60)
self.Button3 = Button(parent, text='exit', command= parent.quit)
self.Button3.place(x= 160, y = 60)
def LabelChange(self):
test = self.entry.get()
self.Label1(test)
root = Tk()
MainFrame =Part3(root)
root.title('Input Test')
root.mainloop()
The Idea being on the 'edit' (button2) click, the text of Label1 is changed to the text of entry.
Try:
self.entry = Entry(text="enter your choice")
...
test = self.entry.get()
self.test.set(test)
I know most tutorials give examples using textvariables, but in most cases you don't need them. You can get and set the values in the widget without using textvariable. Textvariables are mostly useful for doing traces on variables. Variable traces are a somewhat advanced technique that you will rarely need.
from Tkinter import *
class Part3:
def __init__(self, parent):
GUIFrame =Frame(parent,width= 300, height=200)
GUIFrame.pack(expand = False, anchor = CENTER)
self.entry = Entry(text="enter your choice") # this needs to be in self
self.entry.place(x=65, y = 10)
self.test = StringVar()
self.test.set('''Hi, I'm a Label :)''')
self.Label1 = Label(parent, textvariable = self.test)
self.Label1.place(x = 85, y = 100)
self.Button2 = Button(parent, text='edit',command=self.LabelChange)
self.Button2.place(x= 80, y = 60)
self.Button3 = Button(parent, text='exit', command= parent.quit)
self.Button3.place(x= 160, y = 60)
def LabelChange(self):
self.test.set(self.entry.get())
root = Tk()
MainFrame =Part3(root)
root.title('Input Test')
root.mainloop()
root.destroy()
Use can use a .after command. For example:
Lbl = Label(text='Hi')
def change():
Lbl.after(3000, lambda: Lbl.config(text="hola")
# Or you can use the one below to remove delay.
Lbl.config(text='hola')
return change
Btn = Button(command=change ())
Lbl.pack()
Btn.pack()

Resources