Related
I have this table in tkinter. However, I want to have only one button in each row with four text fields. (I currently have four buttons in each row.)
Basically, I want to connect these four buttons to one button in a row. How can I do this?
from tkinter import *
class Table:
def __init__(self,root):
# code for creating table
for i in range(total_rows):
for j in range(total_columns):
self.e = Button(root, width=20,text = lst[i][j])
self.e.grid(row=i, column=j)
# take the data
lst = [(1,'Raj','Mumbai',19),
(2,'Aaryan','Pune',18),
(3,'Vaishnavi','Mumbai',20),
(4,'Rachna','Mumbai',21),
(5,'Shubham','Delhi',21)]
# find total number of rows and
# columns in list
total_rows = len(lst)
total_columns = len(lst[0])
# create root window
root = Tk()
t = Table(root)
root.mainloop()
I've modified your code to include a Toplevel window called 'work' that gives access to the super buttons. The quantity of buttons is determined by the number of rows in table.
Each button is connected to another Toplevel window called 'edit'.
'Edit' contains Label, Entry and Button objects. The quantity is determined by the number of columns in table.
All windows are resizable with 'work' and 'edit' windows accessible via F1 key.
Escape key will close 'top' table via messagebox.
Ok this is the latest version.
I've divided the project into two python files, a data file called 'Datafile.py' and code called "Records.py'.
'Datafile.py' must be saved separately from 'Records.py.
Records code is completely configurable by changing table data in Datafile.py
Changing table data by adding or modifying columns and/or rows will configure the main program. The table, work and edit windows are determined by the row and columns in Datafile.py
SAVE THIS AS 'Datafile.py'
import time
timedate = time.localtime()
year = timedate.tm_year
indice = [ "gender", "name", "location", "age", "birth"]
table = [
["Male", "Raj", "Mumbai", 19, year-19],
["Male", "Aaryan", "Pune", 18, year-18],
["Female", "Vaishnavi","Mumbai", 20, year-20],
["Female", "Rachna", "Mumbai", 21, year-21],
["Male", "Shubham", "Delhi", 21, year-21],
["Male", "Roger", "New York", 17, year-17],
["Male", "David", "Sydney", 53, year-53],
["Female", "Jennifer", "London", 42, year-42]]
Here is the main program 'Records.py'.
SAVE AS 'Records.py'
import tkinter as tk
from tkinter import messagebox
from Datafile import timedate, indice, table
class Table:
def __init__(self, master):
self.master = root
self.master.title("Table")
# create table of buttons in self.store
self.rows = len(table)
self.columns = len(table[0])
# number of rows and columns
self.store = []
for r in range(self.rows):
self.store.append([])
for c in range(self.columns):
e = tk.Label(
self.master, width = 20, bd = 1,
relief = "raised", text = table[r][c])
e.grid(row = r, column = c, sticky = tk.NSEW)
self.flexx(self.master, r = r, c = c)
self.store[r].append(e) # all table buttons stored in list
self.master.geometry(f"{self.columns*100}x{self.rows*26}")
self.master.update()
# create toplevel widget for buttons
self.work = tk.Toplevel(self.master)
self.work.transient(self.master)
self.work.withdraw()
self.work.title("Individual Selector")
# populate toplevel widget with the Super buttons
# make buttons resizable
for r in range(self.rows):
e = tk.Button(
self.work, text = f"{table[r][1]}", bd = 1,
command = self.redirect(self.access, r))
e.grid(row=r, column=0, sticky = tk.NSEW)
self.flexx(self.work, r = r)
# Table edit window
self.edit = tk.Toplevel(self.master)
self.edit.transient(self.master)
self.edit.withdraw()
self.edit.title("Table Editor")
self.labelframe = tk.LabelFrame(self.edit, labelanchor = tk.N, text = "Name")
self.labelframe.grid(row = 0, column = 0, sticky = tk.NSEW)
self.flexx(self.edit)
# place entry tools here
self.data = []
for c in range(self.columns):
l = tk.Label(self.labelframe, text = f"{indice[c]}")
l.grid(row = c, column = 0, sticky = tk.NSEW)
e = tk.Entry(self.labelframe)
e.grid(row = c, column = 1, sticky = tk.NSEW)
self.data.append(e)
b = tk.Button(
self.labelframe, text = "Enter", bd = 1,
command = self.redirect(self.change, c))
b.grid(row = c, column = 2, sticky = tk.NSEW)
self.flexx(self.labelframe, r = c, c = 1)
# wire up master and work widgets
for a, b in [(self.master, self.closer),
(self.work, self.opener),
(self.edit, self.editor)]:
a.protocol('WM_DELETE_WINDOW', b)
a.bind("<KeyRelease-Escape>", b)
# Keys to work widget
self.master.bind("<F1>", self.opener)
self.work.bind("<F1>", self.opener)
self.edit.bind("<F1>", self.editor)
def redirect(self, f, *args):
return lambda: f(*args)
def flexx(self, m, r = 0, c = 0, rw = 1, cw = 1):
m.rowconfigure( r, weight = rw )
m.columnconfigure( c, weight = cw )
def change(self, c):
e = self.data[c]
self.store[self.currentRow][c]["text"] = e.get()
table[self.currentRow][c] = e.get()
def closer(self, ev = None):
if messagebox.askquestion(title = "Quit", message = "Confirm",
detail = "Close program?") == "yes":
self.master.destroy()
def opens( self, o, m ):
"""Toggle switch for toplevel"""
if o.winfo_viewable( ):
o.withdraw( )
m.focus_set( )
else:
o.focus_set( )
o.deiconify()
def position(self, o):
x = int(o.winfo_x() + o.winfo_width() + 5)
y = int(o.winfo_y() + o.winfo_height() / 2)
return x, y
def opener(self, ev = None):
x, y = self.position( self.master)
self.work.geometry(f"190x{26*self.rows}+{x}+{y}")
self.opens(self.work, self.master)
def editor(self, ev = None):
x, y = self.position( self.work)
self.edit.geometry(f"213x{26*self.columns}+{x}+{y}")
self.opens(self.edit, self.work)
def access(self, *args):
self.currentRow = r = args[0]
self.labelframe["text"] = f"{table[r][1]}"
for i,e in enumerate(self.data):
e.delete(0, "end")
e.insert(0, table[r][i])
self.editor()
if __name__ == "__main__":
root = tk.Tk()
top = Table(root)
root.mainloop()
I am trying to create a login page, when the user clicks the login button it is supposed to display a new page (not Toplevel, and create a new window), but it doesn't seem to work.
root = Tk()
root.geometry('670x466')
accounts = []
class Goode_brothers:
def __init__(self, parent):
self.myFrame = Frame(parent)
self.myFrame.pack()
self.load = Image.open('new-dip-project\\food.jpg')
self.render = ImageTk.PhotoImage(self.load)
self.img = Label(parent, image = self.render)
self.img.place(x = -26, y =0)
self.img_login = PhotoImage(file = 'new-dip-project\\button (3).png')
self.b1 = Button(parent,image = self.img_login, command = self.read_info, bd = 0, bg = '#3b353b', activebackground = '#3b353b')
self.b1.place(x = 275, y = 340)
self.img_register = PhotoImage(file = 'new-dip-project\\register.png')
self.b2 = Button(parent,image = self.img_register, command = self.openNewWindow, bd = 0, bg = '#3b353b', activebackground = '#3b353b')
self.b2.place(x = 265, y = 400)
self.canvas = Canvas(parent, width = 400, height = 120)
self.canvas.pack()
self.img4 = ImageTk.PhotoImage(Image.open('new-dip-project\\goode.png'))
self.canvas.create_image(20, 20, anchor=NW, image=self.img4)
self.email = Entry(parent)
self.email.place(x = 340, y = 180)
self.password = Entry(parent)
self.password.place(x = 354, y = 250)
self.img_label = PhotoImage(file = 'new-dip-project\\label-image.png')
self.name = Label(parent, image = self.img_label, text = "Email:", bg = '#3c3a3b').place(x = 197,y = 178)
self.img_label_pass = PhotoImage(file = 'new-dip-project\\label_pass.png')
self.name = Label(parent, image = self.img_label_pass, text = "Password:", bg = '#3c3a3b').place(x = 177,y = 245)
def openMenu(self):
self.myFrame.destroy
self.myFrame2 = Frame()
self.myFrame2.pack()
def read_info(self):
with open("emails.txt") as read_ep:
for line in read_ep:
accounts.append(line.strip().split(", "))
credential = [self.email.get(), self.password.get()]
if credential in accounts:
self.openMenu()
else:
self.ep_notexist = Label(root, text = "Your Email or Password is incorrect, Please try again", font=("open sans", "8"))
self.ep_notexist.place(x = 210, y = 300)
self.ep_notexist.after(4000, self.ep_notexist.destroy)
First destroy all the widgets placed of login page by using
for wid in root.winfo_children():
wid.destroy()
and then pack your new frame. It will work.
(if you don't want to destroy widgets you can also use wid.pack_forget() if you have used pack to place widgets)
You actually do not destroy the frame in the below line:
def openMenu(self):
self.myFrame.destroy # <--- frame is not destroyed actually
It should be:
def openMenu(self):
self.myFrame.destroy()
I want to display the values in the text boxes, but i'm getting this error:
blue.set(B_mean1)
AttributeError: 'numpy.ndarray' object has no attribute 'set'
and my code is:
from Tkinter import Tk, Frame, BOTH
from Tkinter import *
import cv2
from collections import *
from CBIR import *
from experiment import *
from scipy.spatial import distance
import Tkinter,tkFileDialog
from PIL import Image, ImageTk
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent,background="light grey")
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("PISE")
self.pack(fill=BOTH, expand=1)
def open():
path=tkFileDialog.askopenfilename(filetypes=[("Image File",'.jpg')])
custName.set(path)
im = Image.open(path)
tkimage = ImageTk.PhotoImage(im)
myvar=Label(root,image = tkimage)
myvar.image = tkimage
myvar.pack()
myvar.place(x = 100, y = 100)
graylist1 = list()
resizelist1 = list()
eq_graylist1 = list()
cont_list1 = list()
ene_list1 = list()
homo_list1 = list()
cor_list1 = list()
B_mean1 = list()
G_mean1 = list()
R_mean1 = list()
dis_list1 = list()
imge = cv2.imread(path)
arr = array(imge)
g_img = cv2.imread(path,0)
gray_re_img = cv2.resize(g_img,(256,256))
graylist1.append(gray_re_img)
equ = cv2.equalizeHist(gray_re_img)
eq_graylist1.append(equ)
re_img = cv2.resize(imge,(256,256))
resizelist1.append(re_img)
blue, green, red = cv2.split(re_img)
total = re_img.size
B = sum(blue) / total
G = sum(green) / total
R = sum(red) / total
B_mean1.append(B)
G_mean1.append(G)
R_mean1.append(R)
im = skimage.io.imread(path, as_grey=True)
im = skimage.img_as_ubyte(im)
im /= 32
g = skimage.feature.greycomatrix(im, [1], [0], levels=8, symmetric=False, normed=True)
cont = skimage.feature.greycoprops(g, 'contrast')[0][0]
cont_list1.append(cont)
ene = skimage.feature.greycoprops(g, 'energy')[0][0]
ene_list1.append(ene)
homo = skimage.feature.greycoprops(g, 'homogeneity')[0][0]
homo_list1.append(homo)
cor = skimage.feature.greycoprops(g, 'correlation')[0][0]
cor_list1.append(cor)
dis = skimage.feature.greycoprops(g, 'dissimilarity')[0][0]
dis_list1.append(dis)
feature_matrix_ip = zip( B_mean1 , G_mean1 , R_mean1, cont_list1 , ene_list1 , homo_list1 , cor_list1 , dis_list1)
blue.set(B_mean1)
root = Tk()
root.geometry("1105x605+300+300")
app = Example(root)
label = Label(app, text='Python Image Search', fg = 'black',font = 'PoorRichard 24')
label.pack()
label.place(y = 5, x = 0)
img = Image.open('logo.png')
bg_img = ImageTk.PhotoImage(img)
label1 = Label(app, image = bg_img)
label1.place(y = 5, x = 1225)
custName = StringVar(None)
yourName = Entry(app, textvariable=custName)
yourName.grid(column=0,row=0,sticky='EW')
yourName.update()
yourName.focus_set()
yourName.pack(padx = 20, pady = 20,anchor='n')
yourName.place(y = 60, x = 100, width = 525, height = 25)
blue_label = Label(app,text = 'Blue Mean')
blue_label.place(x = 850,y = 140)
blue = IntVar()
blue_text = Entry(app,textvariable = blue)
blue_text.place(x = 1000,y = 140)
button = Button(app, text='Select an Image',command = open)
button.pack(padx = 1, pady = 1,anchor='ne')
button.place( x = 650, y = 60)
root.mainloop()
All I want to know is how to display the values into the textbox. Any suggestions are welcome.
Thanks in advance!
Your problem is that you are using the variable name blue for two different things. At one point it's a numpy array and at another it is an IntVar. When you call blue.set(...), you are doing that at the point where blue references a numpy array, hence the error message 'numpy.ndarray' object has no attribute 'set'
Try changing the name of your IntVar to something else, such as blue_var, and make sure you change it everywhere.
The following things I want is to add multiple different tasks, and there is a task start button which is used to trig a timer.
class Pomodoro_app(Tk):
def add_task(self):
global time
time = StringVar()
time.set("Start")
task_content = askstring(title = 'Add a Task', prompt = "Input a task")
task_label = Label(self, text = task_content, font = ("Arial, 12")).grid(column = 0, row = 3)
task_start_button = Button(self, textvariable = time, command = self.start_working).grid(column = 1, row = 3)
def createWidgets(self):
self.welcome_label = Label(self, text = "Welcome to the Challenge!", font = ("Arial, 12")).grid(column = 0, row = 0, columnspan = 2)
self.add_task_button = Button(self, text = "Add Task", width = 20, command = self.add_task).grid(column = 0 , columnspan = 2)
def __init__(self):
"""GUI Initiation"""
Tk.__init__(self)
self.createWidgets()
"""window Initiation"""
self.resizable(False, False)
x = (self.winfo_screenwidth() - self.winfo_reqwidth()) / 2
y = (self.winfo_screenheight() - self.winfo_reqheight()) / 2
self.geometry('250x400+%d+%d' % (x, y))
Using lambda (or inner function), you can pass additional argument to callback.
For example:
class Pomodoro_app(Tk):
def add_task(self):
global time
time = StringVar()
time.set("Start")
task_content = askstring(title = 'Add a Task', prompt = "Input a task")
task_label = Label(self, text = task_content, font = ("Arial, 12")).grid(column = 0, row = self.next_row)
task_start_button = Button(self, textvariable = time, command = lambda: self.start_working(task_content)).grid(column = 1, row = self.next_row)
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
self.next_row += 1
def start_working(self, task_name):
print('start working', task_name)
def createWidgets(self):
self.welcome_label = Label(self, text = "Welcome to the Challenge!", font = ("Arial, 12")).grid(column = 0, row = 0, columnspan = 2)
self.add_task_button = Button(self, text = "Add Task", width = 20, command = self.add_task).grid(column = 0 , columnspan = 2)
def __init__(self):
"""GUI Initiation"""
Tk.__init__(self)
self.createWidgets()
"""window Initiation"""
self.resizable(False, False)
x = (self.winfo_screenwidth() - self.winfo_reqwidth()) / 2
y = (self.winfo_screenheight() - self.winfo_reqheight()) / 2
self.geometry('250x400+%d+%d' % (x, y))
self.next_row = 3
what i have is a window that opens up and it has a list box. this is created using one class. when i click the search button and results are found using a different class, i want the list box to update without having to open up another window. below is my code so far\n
from Tkinter import *
class addTask:
def __init__(self):
self.addWindow = Tk()
self.addWindow.configure(background = "black")
self.addWindow.geometry("450x450")
self.addWindow.resizable(width = False, height = False)
self.addWindow.title("Add Task")
self.addNameLabel = Label(self.addWindow,text="Add the name of the task",font = ("Helvetica",10,"italic"),bg = "black",fg = "white")
self.addNameLabel.place(relx=0.01, rely=0.05)
self.nameWiget = Text (self.addWindow, width = 63, height = 1)
self.nameWiget.place(relx=0.0, rely=0.1)
self.addDateLabel = Label(self.addWindow,text="Add the date of the task",font = ("Helvetica",10,"italic"),bg = "black",fg = "white")
self.addDateLabel.place(relx=0.01, rely=0.2)
self.dateWiget = Text (self.addWindow, width = 63, height = 1)
self.dateWiget.place(relx=0.0, rely=0.25)
self.addTaskLabel = Label(self.addWindow,text="Add the details of the task",font = ("Helvetica",10,"italic"),bg = "black",fg = "white")
self.addTaskLabel.place(relx=0.01, rely=0.35)
self.taskWiget = Text (self.addWindow, width = 63, height = 1)
self.taskWiget.place(relx=0.0, rely=0.4)
addButton = Button(self.addWindow,height = 5, width = 20, text="Add Task",highlightbackground="black",font=("Helvetica",10,"bold"),command=lambda:self.saveFuntion())
addButton.place(relx=0.25, rely=0.55)
def saveFuntion(self):
nameInfo = (self.nameWiget.get(1.0, END))
dateInfo = self.dateWiget.get(1.0, END)
taskInfo = self.taskWiget.get(1.0, END)
print nameInfo
task1 = Task(nameInfo,dateInfo,taskInfo)
task1.save()
self.nameWiget.delete(1.0,END)
class Task:
def __init__(self,name,date,task):
self.__name = name
self.__date = date
self.__task = task
def save(self):
fileName = open("dataFile.txt","a")
fileName.write(self.__name)
fileName.write(self.__date)
fileName.write(self.__task)
class editTask:
def __init__(self):
self.editWindow = Tk()
self.newWindow = Tk()
self.newWindow.geometry("450x750")
self.editWindow.configure(background = "black")
self.editWindow.geometry("450x750")
self.editWindow.resizable(width = False, height = False)
self.editWindow.title("Edit Task")
self.listBox = Listbox(self.editWindow,heigh = 15, width = 30)
self.listBox.place(relx = 0.2, rely = 0.6)
#drop down menu
self.var = StringVar(self.editWindow)
self.var.set("Select search critria")
self.choices = ["Name","Date"]
self.option = OptionMenu(self.editWindow,self.var,*self.choices)
self.option.configure(bg = "black")
self.option.place(relx = 0.5, rely = 0.2)
#edit label and text box
self.editLabel = Label(self.editWindow,text="Add the name of the task",font = ("Helvetica",10,"italic"),bg = "black",fg = "white")
self.editLabel.place(relx=0.01, rely=0.05)
self.editInfoWiget = Text (self.editWindow, width = 63, height = 1)
self.editInfoWiget.place(relx=0.0, rely=0.1)
# search button
searchButton = Button(self.editWindow,height = 5, width = 20, text="Search for Task",highlightbackground="black",font=("Helvetica",10,"bold"),command=lambda:self.searchFuntion())
searchButton.place(relx=0.3, rely=0.4)
def searchFuntion(self):
critria = self.var.get()
info = self.editInfoWiget.get(1.0,END)
thing = info.split("\n")
thing2 = thing[0]
search = searchCritria(critria,thing2)
search.search()
# def openListBox(self):
class searchCritria():
def __init__(self,critria,info):
self.__critria = critria
self.__info = info
def search(self):
self.file = open("dataFile.txt", "r+")
fileData = self.file.readlines()
self.file.close()
lengthOfFile = len(fileData)
counter = 1
self.name = []
self.date = []
self.details = []
for i in range (lengthOfFile):
split = fileData[i].split("\n")
while counter == 1:
self.name.append(split)
break
while counter == 2:
self.date.append(split)
break
while counter == 3:
self.details.append(split)
break
counter = counter +1
if counter > 3:
counter = 1
if self.__critria == "Name":
for x in range (len(self.name)):
self.taskName = self.name[x]
self.taskName2 = self.taskName[0]
if self.__info == self.taskName2:
openWindow = True
else :
openWindow = False
if openWindow == True:
editTask().listBox.insert(END,self.taskName2)
if self.__critria == "Date":
for x in range (len(self.date)):
self.taskDate = self.date[x]
self.taskDate2 = self.taskDate[0]
if self.__info == self.taskDate2:
print "found"
else :
print"not found"
class editTask2():
def __init__(self):
self.edit2Window = Tk()
self.edit2Window.configure(background = "black")
self.edit2Window.geometry("450x350")
self.edit2Window.resizable(width = False, height = False)
self.edit2Window.title("Edit Task")
any help would be great
thanks
The biggest problem in your code is that you're creating multiple instances of Tk. Tkinter simply isn't designed to work that way. You should only ever create a single instance of Tk. If you need additional windows, create instances of Toplevel.
Also, you need to call the mainloop function of this instance of Tk exactly once. Without it, your GUI will not work.
If you want to update a listbox in another class than where it was created, the concept is pretty simple: if A needs to update B, A needs a reference to B. So, either pass in a reference to the listbox when you create the other class, or give the other class a method you can call where you pass in the reference to the listbox after it was created.