未正确读取复选框值

Checkbox values not being read properly

我有一个 Python 程序可以从数据库中获取信息;在这种情况下,我们正在预订酒店。我的问题是,如果我使用复选框和 select 多个房间——只有列表中的第一个出现。我认为该错误是存在于我的 checkDetails 方法中的各种计数错误。

它会出现,然后在尝试获取复选框的值时,它仅适用于列表中的第一个复选框。老实说,我不是 100% 确定如何描述这个问题。为了代替文字,我上传了四个显示问题的 gif。

好: Selecting the first two works fine. Selecting the first item alone works as well. No matter what, the first item always works.

BAD_1:Selecting the first item and another item (any item except the second) only displays the first item regardless.

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 关系。很难判断这是否是一个有效的假设。