未正确读取复选框值
Checkbox values not being read properly
我有一个 Python 程序可以从数据库中获取信息;在这种情况下,我们正在预订酒店。我的问题是,如果我使用复选框和 select 多个房间——只有列表中的第一个出现。我认为该错误是存在于我的 checkDetails
方法中的各种计数错误。
它会出现,然后在尝试获取复选框的值时,它仅适用于列表中的第一个复选框。老实说,我不是 100% 确定如何描述这个问题。为了代替文字,我上传了四个显示问题的 gif。
BAD_2:Selecting any two items that don't involve the first item, results in neither item being displayed.
BAD_3:Selecting any single item that isn't the first item results in it not being displayed.
##(USER)MAKE NEW RESERVATION##
def searchReservation(self):
self.root = tk.Tk()
self.root.title("Search Rooms")
# city option button
self.cityvariable = StringVar(self.root)
self.cityvariable.set("Select City")
w = OptionMenu(self.root, self.cityvariable, "Atlanta", "Charlotte",
"Savannah", "Orlando", "Miami").grid(row=0, column=0)
# start and end labels
self.startDate = tk.Label(
self.root, text="Start Date (YYYY-MM-DD)") .grid(row=1, column=0)
self.endDate = tk.Label(
self.root, text="End Date (YYYY-MM-DD)").grid(row=1, column=1)
# start and end entries
self.startStringEntry = tk.Entry(self.root, state=NORMAL, width=10)
self.startStringEntry.grid(row=2, column=0)
self.startStringEntry.insert(0, '2015-11-23') #TODO debugging--remove
self.endStringEntry = tk.Entry(self.root, state=NORMAL, width=10)
self.endStringEntry.grid(row=2, column=1)
self.endStringEntry.insert(0, '2015-11-25') #TODO debugging--remove
# search button
self.search_button = tk.Button(
self.root, text="Search Availabilities", command=self.makeReservation)
self.search_button.grid()
self.root.mainloop()
def validDate(self, date):
correctdate = None
try:
startdate = datetime.datetime.strptime(date, "%Y-%m-%d")
correctdate = True
except ValueError:
correctdate = False
if correctdate is False:
messagebox.showerror(
title="Warning", message="A valid date format is required.")
return correctdate
def makeReservation(self):
if self.startStringEntry.get() == self.endStringEntry.get():
messagebox.showerror(
title="Warning", message="Reservation must be at least a day")
elif not self.validDate(self.startStringEntry.get()) or not self.validDate(self.endStringEntry.get()):
return
elif datetime.datetime.strptime(self.startStringEntry.get(), '%Y-%m-%d') > datetime.datetime.strptime(self.endStringEntry.get(), '%Y-%m-%d'):
messagebox.showerror(
title="Warning", message="End date must be after start date")
else:
self.search_button.config(state='disabled')
self.root.withdraw()
self.makeRes = tk.Tk()
self.makeRes.title("Make a Reservation")
# date labels
Label(self.makeRes, text="Start Date") .grid(row=0, column=0)
Label(self.makeRes, text="End Date").grid(row=0, column=1)
Label(self.makeRes, text=self.startStringEntry.get()).grid(
row=1, column=0)
Label(self.makeRes, text=self.endStringEntry.get()).grid(
row=1, column=1)
Label(self.makeRes, text='City').grid(row=0, column=2)
Label(self.makeRes, text=self.cityvariable.get()).grid(
row=1, column=2)
# column headers
roomnumber = tk.Label(
self.makeRes, text="Room Number").grid(row=2, column=0)
roomcat = tk.Label(self.makeRes, text="Room Category").grid(
row=2, column=1)
capacity = tk.Label(
self.makeRes, text="Room Capacity").grid(row=2, column=2)
costperday = tk.Label(
self.makeRes, text="Cost Per Day").grid(row=2, column=3)
costextra = tk.Label(
self.makeRes, text="Extra Bed Cost").grid(row=2, column=4)
availability = tk.Label(
self.makeRes, text="Select Room").grid(row=2, column=5)
# insert available rooms
sql = """SELECT a.RoomNum, a.Category, b.RoomCapacity, a.CostPerDay, a.ExtraBedCost
FROM ROOM a, ROOM_CAPACITY b
WHERE a.Category = b.Category
AND a.RoomLocation = '""" + self.cityvariable.get() + """'
AND (
a.RoomNum, a.RoomLocation
) NOT
IN (
SELECT DISTINCT c.RoomNum, c.Location
FROM ROOM_RESERVATION c, RESERVATION d
WHERE c.ReservationID = d.ReservationID
AND c.Location = a.RoomLocation
AND d.RefundAmount IS NULL
AND """ + self.endStringEntry.get() + """ <= d.EndDate
AND """ + self.startStringEntry.get() + """ >= d.StartDate
)"""
cursor.execute(sql)
self.count = 3
self.data = []
for data in cursor:
self.data.append(data)
for i in range(5):
Label(self.makeRes, text=data[i]).grid(
row=self.count, column=i)
self.count = self.count + 1
if self.count == 3:
messagebox.showerror(
title="Warning", message="No rooms available for city and dates")
self.makeRes.destroy()
self.searchReservation()
else:
# making checkboxes to select room
self.vars = []
for rowNum in range(3, self.count):
self.var = IntVar(self.makeRes)
Checkbutton(self.makeRes, variable=self.var).grid(
row=rowNum, column=5)
self.vars.append(self.var)
self.check_detail_button = Button(
self.makeRes, text='Check Details', command=self.checkDetails)
self.check_detail_button.grid(row=self.count + 1, column=5)
def checkDetails(self):
noneselected = True
for i in self.vars:
if i.get() == 1:
noneselected = False
break
if noneselected is True:
messagebox.showerror(title="Warning", message="No rooms selected")
else:
self.check_detail_button.config(state='disabled')
ttk.Separator(self.makeRes, orient=HORIZONTAL).grid(
column=0, row=self.count+2, columnspan=10, sticky=(W, E))
# column headers
Label(self.makeRes, text="Room Number").grid(
row=self.count + 3, column=0)
Label(self.makeRes, text="Room Category").grid(
row=self.count + 3, column=1)
Label(self.makeRes, text="Room Capacity").grid(
row=self.count + 3, column=2)
Label(self.makeRes, text="Cost Per Day").grid(
row=self.count + 3, column=3)
Label(self.makeRes, text="Extra Bed Cost").grid(
row=self.count + 3, column=4)
Label(self.makeRes, text="Select Extra Bed").grid(
row=self.count + 3, column=5)
self.count += 4
new_count = 0
for data in self.data:
print(data, self.vars[new_count].get()) #TODO remove
if self.vars[new_count].get() == 1:
for i in range(5):
Label(self.makeRes, text=data[i]).grid(
row=self.count + new_count, column=i)
new_count += 1
# making checkboxes to select beds
self.beds = []
count = 0
for rowNum in range(self.count, self.count + new_count):
if self.vars[count].get() == 1:
var = IntVar(self.makeRes)
checkBox = tk.Checkbutton(
self.makeRes, variable=var).grid(row=rowNum, column=5)
self.beds.append(var)
count += 1
self.count += new_count
Label(self.makeRes, text='Total Cost').grid(
row=self.count + 1, column=2)
# CALCULATE TOTAL COSTS
total_cost = 0
count = 0
self.new_data = []
for i in self.data:
if self.vars[count].get() == 1:
total_cost += i[3]
self.new_data.append(i)
count += 1
val = str(total_cost)
self.total_costs_entry = Entry(self.makeRes)
self.total_costs_entry.grid(row=self.count + 1, column=3)
self.total_costs_entry.insert(0, val)
self.total_costs_entry.config(state='readonly')
Button(self.makeRes, text='Update total', command=self.updateTotalCosts).grid(
row=self.count + 1, column=4)
Label(self.makeRes, text='Use Card').grid(
row=self.count + 2, column=2)
cursor.execute(
'SELECT CardNum FROM PAYMENT_INFO WHERE Username="' + self.user + '"')
cards = ['-']
for i in cursor:
cards.append(i)
self.card = StringVar(self.makeRes)
self.opts = OptionMenu(self.makeRes, self.card, *cards)
self.opts.grid(row=self.count + 2, column=3)
Button(self.makeRes, text="Add Card", command=self.addCreditCard).grid(
row=self.count + 2, column=4)
Button(self.makeRes, text="Delete Card", command=self.deleteCard).grid(
row=self.count + 2, column=5)
Button(self.makeRes, text='Submit', command=self.submitReservation).grid(
row=self.count + 3, column=5)
def updateTotalCosts(self):
total_cost = 0
count = 0
self.new_data = []
for i in self.data:
if self.vars[count].get() == 1:
total_cost += i[3]
self.new_data.append(i)
count += 1
count = 0
for i in self.new_data:
if self.beds[count].get() == 1:
total_cost += i[4]
count += 1
cursor.execute("SELECT DATEDIFF(%s, %s)",
(self.endStringEntry.get(), self.startStringEntry.get()))
diff = cursor.fetchone()
diff = diff[0]
total_cost = diff * total_cost
self.total_costs_entry.destroy()
self.total_costs_entry = Entry(self.makeRes)
self.total_costs_entry.grid(row=self.count + 1, column=3)
self.total_costs_entry.insert(0, str(total_cost))
self.total_costs_entry.config(state='readonly')
编辑:为什么不这样做呢?
for data in self.data:
print(data, self.vars[new_count].get()) #TODO debugging--remove
if self.vars[new_count].get() == 1:
for i in range(5):
Label(self.makeRes, text=data[i]).grid(
row=self.count + new_count, column=i)
new_count += 1
绝对有一个问题是您正在创建 tk.Tk()
的多个实例。 Tkinter 并非设计为以这种方式工作,它会产生与您所看到的类似的问题。
如果您需要额外的 windows,您必须创建 tk.Toplevel
的实例。
另一个问题是这个循环:
for data in self.data:
if self.vars[new_count].get() == 1:
for i in range(5):
Label(self.makeRes, text=data[i]).grid(
row=self.count + new_count, column=i)
new_count += 1
逻辑上存在根本性缺陷。即使您循环遍历数据,您也会继续检查 self.vars[new_count]
。因此,即使您最终找到了数据项 3、4、5 等,您也会一遍又一遍地检查 self.vars[0]
。一旦找到一个选中的项目,您现在会继续查看 self.vars[1]
,即使您现在可能在第 3、4、5 等数据项上。
一个简单的解决方法是确保像迭代数据值一样迭代变量:
for var, data in zip(self.vars, self.data):
if var.get() == 1:
for i in range(5):
Label(self.makeRes, text=str(data[i]) + "?").grid(
row=self.count + new_count, column=i)
new_count += 1
以上假定 self.vars
中的项目与 self.data
中的项目之间存在 1:1 关系。很难判断这是否是一个有效的假设。
我有一个 Python 程序可以从数据库中获取信息;在这种情况下,我们正在预订酒店。我的问题是,如果我使用复选框和 select 多个房间——只有列表中的第一个出现。我认为该错误是存在于我的 checkDetails
方法中的各种计数错误。
它会出现,然后在尝试获取复选框的值时,它仅适用于列表中的第一个复选框。老实说,我不是 100% 确定如何描述这个问题。为了代替文字,我上传了四个显示问题的 gif。
BAD_2:Selecting any two items that don't involve the first item, results in neither item being displayed.
BAD_3:Selecting any single item that isn't the first item results in it not being displayed.
##(USER)MAKE NEW RESERVATION##
def searchReservation(self):
self.root = tk.Tk()
self.root.title("Search Rooms")
# city option button
self.cityvariable = StringVar(self.root)
self.cityvariable.set("Select City")
w = OptionMenu(self.root, self.cityvariable, "Atlanta", "Charlotte",
"Savannah", "Orlando", "Miami").grid(row=0, column=0)
# start and end labels
self.startDate = tk.Label(
self.root, text="Start Date (YYYY-MM-DD)") .grid(row=1, column=0)
self.endDate = tk.Label(
self.root, text="End Date (YYYY-MM-DD)").grid(row=1, column=1)
# start and end entries
self.startStringEntry = tk.Entry(self.root, state=NORMAL, width=10)
self.startStringEntry.grid(row=2, column=0)
self.startStringEntry.insert(0, '2015-11-23') #TODO debugging--remove
self.endStringEntry = tk.Entry(self.root, state=NORMAL, width=10)
self.endStringEntry.grid(row=2, column=1)
self.endStringEntry.insert(0, '2015-11-25') #TODO debugging--remove
# search button
self.search_button = tk.Button(
self.root, text="Search Availabilities", command=self.makeReservation)
self.search_button.grid()
self.root.mainloop()
def validDate(self, date):
correctdate = None
try:
startdate = datetime.datetime.strptime(date, "%Y-%m-%d")
correctdate = True
except ValueError:
correctdate = False
if correctdate is False:
messagebox.showerror(
title="Warning", message="A valid date format is required.")
return correctdate
def makeReservation(self):
if self.startStringEntry.get() == self.endStringEntry.get():
messagebox.showerror(
title="Warning", message="Reservation must be at least a day")
elif not self.validDate(self.startStringEntry.get()) or not self.validDate(self.endStringEntry.get()):
return
elif datetime.datetime.strptime(self.startStringEntry.get(), '%Y-%m-%d') > datetime.datetime.strptime(self.endStringEntry.get(), '%Y-%m-%d'):
messagebox.showerror(
title="Warning", message="End date must be after start date")
else:
self.search_button.config(state='disabled')
self.root.withdraw()
self.makeRes = tk.Tk()
self.makeRes.title("Make a Reservation")
# date labels
Label(self.makeRes, text="Start Date") .grid(row=0, column=0)
Label(self.makeRes, text="End Date").grid(row=0, column=1)
Label(self.makeRes, text=self.startStringEntry.get()).grid(
row=1, column=0)
Label(self.makeRes, text=self.endStringEntry.get()).grid(
row=1, column=1)
Label(self.makeRes, text='City').grid(row=0, column=2)
Label(self.makeRes, text=self.cityvariable.get()).grid(
row=1, column=2)
# column headers
roomnumber = tk.Label(
self.makeRes, text="Room Number").grid(row=2, column=0)
roomcat = tk.Label(self.makeRes, text="Room Category").grid(
row=2, column=1)
capacity = tk.Label(
self.makeRes, text="Room Capacity").grid(row=2, column=2)
costperday = tk.Label(
self.makeRes, text="Cost Per Day").grid(row=2, column=3)
costextra = tk.Label(
self.makeRes, text="Extra Bed Cost").grid(row=2, column=4)
availability = tk.Label(
self.makeRes, text="Select Room").grid(row=2, column=5)
# insert available rooms
sql = """SELECT a.RoomNum, a.Category, b.RoomCapacity, a.CostPerDay, a.ExtraBedCost
FROM ROOM a, ROOM_CAPACITY b
WHERE a.Category = b.Category
AND a.RoomLocation = '""" + self.cityvariable.get() + """'
AND (
a.RoomNum, a.RoomLocation
) NOT
IN (
SELECT DISTINCT c.RoomNum, c.Location
FROM ROOM_RESERVATION c, RESERVATION d
WHERE c.ReservationID = d.ReservationID
AND c.Location = a.RoomLocation
AND d.RefundAmount IS NULL
AND """ + self.endStringEntry.get() + """ <= d.EndDate
AND """ + self.startStringEntry.get() + """ >= d.StartDate
)"""
cursor.execute(sql)
self.count = 3
self.data = []
for data in cursor:
self.data.append(data)
for i in range(5):
Label(self.makeRes, text=data[i]).grid(
row=self.count, column=i)
self.count = self.count + 1
if self.count == 3:
messagebox.showerror(
title="Warning", message="No rooms available for city and dates")
self.makeRes.destroy()
self.searchReservation()
else:
# making checkboxes to select room
self.vars = []
for rowNum in range(3, self.count):
self.var = IntVar(self.makeRes)
Checkbutton(self.makeRes, variable=self.var).grid(
row=rowNum, column=5)
self.vars.append(self.var)
self.check_detail_button = Button(
self.makeRes, text='Check Details', command=self.checkDetails)
self.check_detail_button.grid(row=self.count + 1, column=5)
def checkDetails(self):
noneselected = True
for i in self.vars:
if i.get() == 1:
noneselected = False
break
if noneselected is True:
messagebox.showerror(title="Warning", message="No rooms selected")
else:
self.check_detail_button.config(state='disabled')
ttk.Separator(self.makeRes, orient=HORIZONTAL).grid(
column=0, row=self.count+2, columnspan=10, sticky=(W, E))
# column headers
Label(self.makeRes, text="Room Number").grid(
row=self.count + 3, column=0)
Label(self.makeRes, text="Room Category").grid(
row=self.count + 3, column=1)
Label(self.makeRes, text="Room Capacity").grid(
row=self.count + 3, column=2)
Label(self.makeRes, text="Cost Per Day").grid(
row=self.count + 3, column=3)
Label(self.makeRes, text="Extra Bed Cost").grid(
row=self.count + 3, column=4)
Label(self.makeRes, text="Select Extra Bed").grid(
row=self.count + 3, column=5)
self.count += 4
new_count = 0
for data in self.data:
print(data, self.vars[new_count].get()) #TODO remove
if self.vars[new_count].get() == 1:
for i in range(5):
Label(self.makeRes, text=data[i]).grid(
row=self.count + new_count, column=i)
new_count += 1
# making checkboxes to select beds
self.beds = []
count = 0
for rowNum in range(self.count, self.count + new_count):
if self.vars[count].get() == 1:
var = IntVar(self.makeRes)
checkBox = tk.Checkbutton(
self.makeRes, variable=var).grid(row=rowNum, column=5)
self.beds.append(var)
count += 1
self.count += new_count
Label(self.makeRes, text='Total Cost').grid(
row=self.count + 1, column=2)
# CALCULATE TOTAL COSTS
total_cost = 0
count = 0
self.new_data = []
for i in self.data:
if self.vars[count].get() == 1:
total_cost += i[3]
self.new_data.append(i)
count += 1
val = str(total_cost)
self.total_costs_entry = Entry(self.makeRes)
self.total_costs_entry.grid(row=self.count + 1, column=3)
self.total_costs_entry.insert(0, val)
self.total_costs_entry.config(state='readonly')
Button(self.makeRes, text='Update total', command=self.updateTotalCosts).grid(
row=self.count + 1, column=4)
Label(self.makeRes, text='Use Card').grid(
row=self.count + 2, column=2)
cursor.execute(
'SELECT CardNum FROM PAYMENT_INFO WHERE Username="' + self.user + '"')
cards = ['-']
for i in cursor:
cards.append(i)
self.card = StringVar(self.makeRes)
self.opts = OptionMenu(self.makeRes, self.card, *cards)
self.opts.grid(row=self.count + 2, column=3)
Button(self.makeRes, text="Add Card", command=self.addCreditCard).grid(
row=self.count + 2, column=4)
Button(self.makeRes, text="Delete Card", command=self.deleteCard).grid(
row=self.count + 2, column=5)
Button(self.makeRes, text='Submit', command=self.submitReservation).grid(
row=self.count + 3, column=5)
def updateTotalCosts(self):
total_cost = 0
count = 0
self.new_data = []
for i in self.data:
if self.vars[count].get() == 1:
total_cost += i[3]
self.new_data.append(i)
count += 1
count = 0
for i in self.new_data:
if self.beds[count].get() == 1:
total_cost += i[4]
count += 1
cursor.execute("SELECT DATEDIFF(%s, %s)",
(self.endStringEntry.get(), self.startStringEntry.get()))
diff = cursor.fetchone()
diff = diff[0]
total_cost = diff * total_cost
self.total_costs_entry.destroy()
self.total_costs_entry = Entry(self.makeRes)
self.total_costs_entry.grid(row=self.count + 1, column=3)
self.total_costs_entry.insert(0, str(total_cost))
self.total_costs_entry.config(state='readonly')
编辑:为什么不这样做呢?
for data in self.data:
print(data, self.vars[new_count].get()) #TODO debugging--remove
if self.vars[new_count].get() == 1:
for i in range(5):
Label(self.makeRes, text=data[i]).grid(
row=self.count + new_count, column=i)
new_count += 1
绝对有一个问题是您正在创建 tk.Tk()
的多个实例。 Tkinter 并非设计为以这种方式工作,它会产生与您所看到的类似的问题。
如果您需要额外的 windows,您必须创建 tk.Toplevel
的实例。
另一个问题是这个循环:
for data in self.data:
if self.vars[new_count].get() == 1:
for i in range(5):
Label(self.makeRes, text=data[i]).grid(
row=self.count + new_count, column=i)
new_count += 1
逻辑上存在根本性缺陷。即使您循环遍历数据,您也会继续检查 self.vars[new_count]
。因此,即使您最终找到了数据项 3、4、5 等,您也会一遍又一遍地检查 self.vars[0]
。一旦找到一个选中的项目,您现在会继续查看 self.vars[1]
,即使您现在可能在第 3、4、5 等数据项上。
一个简单的解决方法是确保像迭代数据值一样迭代变量:
for var, data in zip(self.vars, self.data):
if var.get() == 1:
for i in range(5):
Label(self.makeRes, text=str(data[i]) + "?").grid(
row=self.count + new_count, column=i)
new_count += 1
以上假定 self.vars
中的项目与 self.data
中的项目之间存在 1:1 关系。很难判断这是否是一个有效的假设。