python进阶-用Tkinter/mysqldb写一个简单的酒店预定GUI界面

版权声明:苍生苦难,不知伊于胡底 https://blog.csdn.net/qq_40527086/article/details/84672554

学了python的部分库和基本语法后,结合数据库操作,做一个简单的用户友好界面实现一个简单的酒店预订小系统。

准备姿势

tkinter的组件转换
tkinter按钮组件详解
Python连接数据库操作
数据库准备
在本地数据库新建一个hotel_data的数据库,建立四张表。
建表的查询语句如下:

/*
 Navicat Premium Data Transfer

 Source Server         : mysql
 Source Server Type    : MySQL
 Source Server Version : 80012
 Source Host           : localhost:3306
 Source Schema         : hotel_data

 Target Server Type    : MySQL
 Target Server Version : 80012
 File Encoding         : 65001

 Date: 22/11/2018 16:05:09
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for hotel
-- ----------------------------
DROP TABLE IF EXISTS `hotel`;
CREATE TABLE `hotel`  (
  `hotel_id` int(11) NOT NULL,
  `hotel_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `stars` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`hotel_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of hotel
-- ----------------------------
INSERT INTO `hotel` VALUES (1, '惠民旅馆', 5);
INSERT INTO `hotel` VALUES (2, '风景旅馆', 4);
INSERT INTO `hotel` VALUES (3, '商务旅馆', 4);

-- ----------------------------
-- Table structure for order
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order`  (
  `order_id` int(11) NOT NULL COMMENT 'joer',
  `room_id` int(11) NULL DEFAULT NULL,
  `start_date` date NULL DEFAULT NULL,
  `leave_date` date NULL DEFAULT NULL,
  `amount` int(11) NULL DEFAULT NULL,
  `payment` int(11) NULL DEFAULT NULL,
  `create_date` date NULL DEFAULT NULL,
  PRIMARY KEY (`order_id`) USING BTREE,
  INDEX `room_order_id`(`room_id`) USING BTREE,
  CONSTRAINT `room_order_id` FOREIGN KEY (`room_id`) REFERENCES `room_type` (`room_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of order
-- ----------------------------
INSERT INTO `order` VALUES (0, 6, '2018-11-14', '2018-11-15', 4, 2000, '2018-11-01');
INSERT INTO `order` VALUES (1, 5, '2018-11-14', '2018-11-16', 2, 2100, '2018-11-01');
INSERT INTO `order` VALUES (2, 1, '2018-11-14', '2018-11-14', 5, 2500, '2018-11-01');
INSERT INTO `order` VALUES (3, 8, '2018-11-14', '2018-11-16', 2, 1296, '2018-11-01');
INSERT INTO `order` VALUES (4, 4, '2018-11-14', '2018-11-16', 2, 2400, '2018-11-01');

-- ----------------------------
-- Table structure for room_info
-- ----------------------------
DROP TABLE IF EXISTS `room_info`;
CREATE TABLE `room_info`  (
  `info_id` int(11) NOT NULL,
  `date` date NULL DEFAULT NULL,
  `price` decimal(10, 2) NULL DEFAULT NULL,
  `remain` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `room_id` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`info_id`) USING BTREE,
  INDEX `room_info_key`(`room_id`) USING BTREE,
  CONSTRAINT `room_info_key` FOREIGN KEY (`room_id`) REFERENCES `room_type` (`room_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of room_info
-- ----------------------------
INSERT INTO `room_info` VALUES (1, '2018-11-14', 500.00, '5', 1);
INSERT INTO `room_info` VALUES (2, '2018-11-15', 500.00, '4', 1);
INSERT INTO `room_info` VALUES (3, '2018-11-16', 600.00, '6', 1);
INSERT INTO `room_info` VALUES (4, '2018-11-14', 300.00, '6', 2);
INSERT INTO `room_info` VALUES (5, '2018-11-15', 300.00, '5', 2);
INSERT INTO `room_info` VALUES (6, '2018-11-16', 400.00, '5', 2);
INSERT INTO `room_info` VALUES (7, '2018-11-14', 200.00, '4', 3);
INSERT INTO `room_info` VALUES (8, '2018-11-15', 200.00, '3', 3);
INSERT INTO `room_info` VALUES (9, '2018-11-16', 300.00, '4', 3);
INSERT INTO `room_info` VALUES (10, '2018-11-14', 450.00, '5', 4);
INSERT INTO `room_info` VALUES (11, '2018-11-15', 300.00, '5', 4);
INSERT INTO `room_info` VALUES (12, '2018-11-16', 450.00, '5', 4);
INSERT INTO `room_info` VALUES (13, '2018-11-14', 400.00, '2', 5);
INSERT INTO `room_info` VALUES (14, '2018-11-15', 250.00, '2', 5);
INSERT INTO `room_info` VALUES (15, '2018-11-16', 400.00, '2', 5);
INSERT INTO `room_info` VALUES (16, '2018-11-14', 300.00, '1', 6);
INSERT INTO `room_info` VALUES (17, '2018-11-15', 200.00, '1', 6);
INSERT INTO `room_info` VALUES (18, '2018-11-16', 300.00, '5', 6);
INSERT INTO `room_info` VALUES (19, '2018-11-14', 300.00, '2', 7);
INSERT INTO `room_info` VALUES (20, '2018-11-15', 250.00, '3', 7);
INSERT INTO `room_info` VALUES (21, '2018-11-16', 300.00, '8', 7);
INSERT INTO `room_info` VALUES (22, '2018-11-14', 250.00, '1', 8);
INSERT INTO `room_info` VALUES (23, '2018-11-15', 200.00, '1', 8);
INSERT INTO `room_info` VALUES (24, '2018-11-16', 200.00, '5', 8);
INSERT INTO `room_info` VALUES (25, '2018-11-14', 200.00, '2', 9);
INSERT INTO `room_info` VALUES (26, '2018-11-15', 150.00, '4', 9);
INSERT INTO `room_info` VALUES (27, '2018-11-16', 150.00, '4', 9);

-- ----------------------------
-- Table structure for room_type
-- ----------------------------
DROP TABLE IF EXISTS `room_type`;
CREATE TABLE `room_type`  (
  `room_id` int(11) NOT NULL,
  `room_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `hotel_id` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`room_id`) USING BTREE,
  INDEX `hotel_room_key`(`hotel_id`) USING BTREE,
  CONSTRAINT `hotel_room_key` FOREIGN KEY (`hotel_id`) REFERENCES `hotel` (`hotel_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of room_type
-- ----------------------------
INSERT INTO `room_type` VALUES (1, '大床房', 1);
INSERT INTO `room_type` VALUES (2, '双人房', 1);
INSERT INTO `room_type` VALUES (3, '三人房', 1);
INSERT INTO `room_type` VALUES (4, '海景房', 2);
INSERT INTO `room_type` VALUES (5, '园景房', 2);
INSERT INTO `room_type` VALUES (6, '山景房', 2);
INSERT INTO `room_type` VALUES (7, '总统套房', 3);
INSERT INTO `room_type` VALUES (8, '豪华套房', 3);
INSERT INTO `room_type` VALUES (9, '33号房', 3);

SET FOREIGN_KEY_CHECKS = 1;

drop table if EXISTS `user_order`;
CREATE TABLE `user_order`  (
  `user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci,
  `hotel` varchar(255) NULL DEFAULT NULL,
  `room_name`  varchar(255) NULL DEFAULT NULL,
  `nums` int(10) NULL DEFAULT NULL,
  `start_date` varchar(255) NULL DEFAULT NULL,
  `end_date` varchar(255) NULL DEFAULT NULL,
  `price` INT(10) NULL DEFAULT NULL,
  PRIMARY KEY (`user`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
drop table if EXISTS `user_inf`;
CREATE TABLE `user_inf`  (
  `user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci,
  `passwd` varchar(255) NULL DEFAULT NULL,
  `ID`  varchar(255) NULL DEFAULT NULL,
  `Tel` varchar(255) NULL DEFAULT NULL,
  PRIMARY KEY (`user`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

建好后四张表如下:

  • hotel 酒店信息
  • 在这里插入图片描述
  • room_info 房间信息
    在这里插入图片描述
  • room_type 房型
    在这里插入图片描述
  • user_inf 记录用户的注册信息
    在这里插入图片描述
  • user order表 记录订单信息
    在这里插入图片描述

实验环境

系统:WIN10
语言:Python 2.7
IDLE: PyCharm
调用包:
*tkinter(自带GUI包)
*pandas(存取csv文件)
*MySQLDb(数据库操作)
*PIL库(图像处理)
*time (用于延时处理)

流程图

小系统的流程图如下:
在这里插入图片描述

具体页面展示和测试

测试由命令行窗口显示,若测试与系统中显示信息一致,则通过验证。
用于测试的账号(预存在数据库user_inf表中,你也可以自己设置):
做好的GUI界面如下:

  • 登陆界面
    在这里插入图片描述在这里插入图片描述

  • 点击注册进入注册页面
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 预订界面
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 测试窗口展示

测试窗口结果:
用户输入是:
2018-11-14 2018-11-16 0 1000 1
满足条件的有
   hotel_name  stars room_name  remain  price
0        惠民旅馆      5       大床房       5  500.0
1        惠民旅馆      5       大床房       4  500.0
2        惠民旅馆      5       大床房       6  600.0
3        惠民旅馆      5       双人房       6  300.0
4        惠民旅馆      5       双人房       5  300.0
5        惠民旅馆      5       双人房       5  400.0
6        惠民旅馆      5       三人房       4  200.0
7        惠民旅馆      5       三人房       3  200.0
8        惠民旅馆      5       三人房       4  300.0
9        风景旅馆      4       海景房       5  450.0
10       风景旅馆      4       海景房       2  300.0
11       风景旅馆      4       海景房       2  450.0
12       风景旅馆      4       园景房       2  400.0
13       风景旅馆      4       园景房       2  250.0
14       风景旅馆      4       园景房       2  400.0
15       风景旅馆      4       山景房       1  300.0
16       风景旅馆      4       山景房       1  200.0
17       风景旅馆      4       山景房       5  300.0
18       商务旅馆      4      总统套房       2  300.0
19       商务旅馆      4      总统套房       3  250.0
20       商务旅馆      4      总统套房       8  300.0
21       商务旅馆      4      豪华套房       1  250.0
22       商务旅馆      4      豪华套房       1  200.0
23       商务旅馆      4      豪华套房       5  200.0
24       商务旅馆      4      33号房       2  200.0
25       商务旅馆      4      33号房       4  150.0
26       商务旅馆      4      33号房       4  150.0

['lk', 'lk', '2018-11-14', '2018-11-16', 1]
[u'\u603b\u7edf\u5957\u623f', 8, 300.0]
select * from `user_order` where user='lk' 
查询成功
用户的最终选择为:
(u'lk', u'UNSHOWED', u'UNSHOWED', 1L, u'2018-11-14', u'2018-11-16', 200L)

之前的用户测试的时候预定过该房间,所以预定失败。现在切换用户进行新一轮的测试。
点击退出切换到下一个用户。
在这里插入图片描述
测试窗口:

用户输入是:
2018-11-14 2018-11-16 0 1000 1
满足条件的有
   hotel_name  stars room_name  remain  price
21       商务旅馆      4      豪华套房       1  250.0
22       商务旅馆      4      豪华套房       1  200.0
23       商务旅馆      4      豪华套房       5  200.0
['psr', 'psr', '2018-11-14', '2018-11-16', 1]
[u'\u8c6a\u534e\u5957\u623f', 1, 250.0]
插入数据库的信息是:
INSERT INTO  `user_order`(`user`,`hotel`,`room_name`,`nums`,`start_date`,`end_date`,`price`)VALUES('psr','UNSHOWED','UNSHOWED','1','2018-11-14','2018-11-16','250')
预定成功
select * from `user_order` where user='psr' 
查询成功
用户的最终选择为:
(u'psr', u'UNSHOWED', u'UNSHOWED', 1L, u'2018-11-14', u'2018-11-16', 250L)

最终生成新订单表
在这里插入图片描述

全部代码包含详细注释:

# -author:LK12 time:2018/11/26
# -*- coding:utf-8 -*-

import tkinter as tk
from PIL import ImageTk,Image
import time
import tkinter.font as tkFont
import MySQLdb
import pandas as pd
from tkinter import ttk

import sys
reload(sys)
sys.setdefaultencoding('utf-8')
### 设置框架大小等性质,这样就不用每次都重新设置
## 主界面,登陆界面
class MainFrame(tk.Tk):
    def __init__(self,title):
        tk.Tk.__init__(self)
        self.title(title)
        self.iconbitmap('hotel1.ico')
        self.geometry('280x470+500+100')
        self.attributes('-alpha', 0.92)
## 其他界面
class OtherFrame(tk.Toplevel):
    def __init__(self, title):
        tk.Toplevel.__init__(self)
        self.title(title)
        self.iconbitmap('hotel1.ico')
        self.geometry('280x470+500+100')
        self.attributes('-alpha', 0.92)

class user_login(object):

    def __init__(self, root):
        self.root = root
        # 登陆提示信息设置为可变,用于提醒用户是否登陆成功
        self.var1 = tk.StringVar()
        self.var1.set('Hotel Order System')
        # 连接数据库
        self.conn = MySQLdb.Connection(
            host='localhost',
            port=3306,
            user='root',
            passwd='root',
            db='hotel_data',
            charset='utf8'
        )
        # 获取管理员权限可见的账户信息,提取出账户和密码存入字典便于验证
        self.cursor = self.conn.cursor()
        self.cursor.execute('select user,passwd from user_inf')
        login_inf = self.cursor.fetchall()
        user_inf = [str(ii[0]) for ii in login_inf]
        passwd_inf = [str(ii[1]) for ii in login_inf]
        self.dict_inf = dict(zip(user_inf, passwd_inf))
        # 获取三个表自然连接即所有信息,为了转换格式将其存入csv文件再提取出来,编码变为gb2312
        sql1 = 'select * from (room_type NATURAL JOIN hotel)NATURAL JOIN room_info'
        self.cursor.execute(sql1)
        hotel_inf = self.cursor.fetchall()
        hotel_inf = pd.DataFrame(list(hotel_inf), columns=['room_id', 'hotel_id', 'room_name',
                                                           'hotel_name', 'stars', 'info_id',
                                                           'date', 'price', 'remain'])
        hotel_inf = hotel_inf.drop(['info_id'], axis=1)
        hotel_inf.to_csv('12.csv', encoding='gb2312')
        self.hotel_inf = pd.read_csv('12.csv', encoding='gb2312')
        frame1 = tk.Frame() #框架一 标志图标
        frame2 = tk.Frame() #框架二 用户密码
        frame3 = tk.Frame() #框架三 忘记密码
        frame4 = tk.Frame() #框架四 注释
        # 读取图片添加到登陆验证页,增加美感
        pic = Image.open('hotel.jpg')
        # 设置读取的图片为全局变量,在class外部才能正确显示
        global img
        img = ImageTk.PhotoImage(pic)

        # 登陆验证页面的框架组织
        tk.Label(frame1,
                 textvariable=self.var1,
                 compound=tk.CENTER,
                 fg='green',
                 bg='red',
                 font=('Fixdsys', 10),
                 width=140,
                 justify=tk.CENTER,
                 height=10,
                 bd=80,
                 image=img
                 ).grid(row=5, padx=10, pady=5)
        tk.Label(frame2, text='用户名',bd=4).grid(row=0)
        tk.Label(frame2, text='密码',bd=4).grid(row=1)
        self.e1 = tk.Entry(frame2)
        self.e1.grid(row=0, column=1, padx=10, pady=5)
        self.e2 = tk.Entry(frame2,show='*')
        self.e2.grid(row=1, column=1, padx=10, pady=5)
        self.e1.insert(0, 'lk')
        self.e2.insert(0, 'lk')
        b1 = tk.Button(frame2,text='登陆', command=self.login, width=10,fg='white',bg='blue')
        b1.grid(row=3, column=0, sticky=tk.W, padx=10, pady=5)
        b2 = tk.Button(frame2,text='免费注册', command=self._register, width=10,fg='blue',highlightcolor='blue')
        b2.grid(row=3, column=1, sticky=tk.E, padx=10, pady=5)
        tk.Button(frame3, text='忘记密码',bd=5, command=self.forget_pwd).pack()
        l4 = tk.Label(frame4,
                      text='*这是一个简单的酒店预定小系统\n\n'
                           '*用于测试的账号和密码:lk/lk\n\n'
                           '*可以自己注册,信息将写入数据库\n\n'
                           '*该小系统由python自带tkinter包构建\n\n'
                           '*开发环境:windows10 Python 2.7\n'
                           '                --All rights reserved by LK',
                      justify=tk.LEFT,
                      bg='gray',
                      fg='purple',
                      width=130,
                      highlightcolor='purple',
                      font=tkFont.Font(family='楷体',size=9, underline=0))
        l4.pack()

        frame1.pack(side=tk.TOP)
        frame2.pack()
        frame3.pack()
        frame4.pack(side=tk.BOTTOM)

    ### 登陆成功后普通查询界面
    def login(self):
        global top_login
        if self.e1.get() in self.dict_inf.keys():
            if self.e2.get() == self.dict_inf[self.e1.get()]:
                self.root.withdraw()
                top_login = OtherFrame('登陆成功,欢迎您:%s' % (self.e1.get()))
                f0 = tk.Frame(top_login)
                f1 = tk.Frame(top_login, bg='gray')
                f2 = tk.Frame(top_login)
                f0.grid(row=0)
                f1.grid(row=1)
                f2.grid(row=2)
                ## 跳转至查询界面
                def search_hotel():
                    top_login.withdraw()
                    self.login()
                ## 跳转至订单界面
                def watch_order():
                    top_login.withdraw()
                    self.order()
                select_b1 = tk.Button(f0,text='酒店查询',fg='white',bg='blue',width=17,command=search_hotel)
                select_b1.pack(side=tk.LEFT)
                select_b2 = tk.Button(f0,text='订单查询',fg='white',bg='blue',width=17,command=watch_order)
                select_b2.pack(side=tk.RIGHT)
                ## 日期选择
                l1 = tk.Label(f1,text='日期选择')
                l1.grid(row=0)
                # 入住日期滑动选择
                start_date_var = tk.StringVar()
                ttk1 = ttk.Combobox(f1,width=12,textvariable=start_date_var,
                                    values=['2018-11-14','2018-11-15','2018-11-16'],state='readonly')
                ttk1.current(0)
                ttk1.set('入住日期')
                ttk1.grid(row=1, column=0)
                # 过渡标签
                l12 = tk.Label(f1, text='>>>')
                l12.grid(row=1, column=2)
                # 离开日期滑动选择
                end_day_var = tk.StringVar()
                ttk2 = ttk.Combobox(f1, width=12, textvariable=end_day_var,
                                    values=['2018-11-14', '2018-11-15', '2018-11-16'], state='readonly')
                ttk2.current(0)
                ttk2.set('离开日期')
                ttk2.grid(row=1, column=3)
                ## 价格区间选择
                l2 = tk.Label(f1, text='价格选择')
                l2.grid(row=2)
                # 最低价格
                low_price_var = tk.StringVar()
                ttk3 = ttk.Combobox(f1,width=12,textvariable=low_price_var,
                                    values=['0','200','400','500'],state='readonly')
                ttk3.current(0)
                ttk3.set('最低价格')
                ttk3.grid(row=3, column=0)
                # >>>标签
                tk.Label(f1, text='>>>').grid(row=3, column=2)
                # 最高价格
                high_price_var = tk.StringVar()
                ttk4 = ttk.Combobox(f1, width=12, textvariable=high_price_var,
                                    values=['500', '600', '700', '1000'], state='readonly')
                ttk4.current(0)
                ttk4.set('最高价格')
                ttk4.grid(row=3, column=3)
                ## 房型选择
                tk.Label(f1, text='房型选择').grid(row=4, column=0)
                tk.Label(f1, text='预定房数').grid(row=4, column=3)
                room_name_var = tk.StringVar()
                ttk5 = ttk.Combobox(f1,width=12,textvariable=room_name_var,values=['大床房','双人房','三人房','海景房','园景房'
                    ,'山景房','总统套房','豪华套房','33号房'])
                ttk5.current(0)
                ttk5.set('默认都行')
                ttk5.grid(row=5,column=0)

                ## 预定数选择
                remain_var = tk.StringVar()
                ttk6 = ttk.Combobox(f1, width=12, textvariable=remain_var, values=['1', '2', '3', '4', '5'
                    , '6', '7', '8', '9'])
                ttk6.current(0)
                ttk6.grid(row=5, column=3)

                ## 获取用户输入并进行选择
                def get_hotel_inf():
                    global start_date,end_date,remain,selected
                    start_date = ttk1.get()
                    end_date = ttk2.get()
                    low_price = int(ttk3.get())
                    high_price = int(ttk4.get())
                    room_name = ttk5.get()
                    remain = int(ttk6.get())

                    print '用户输入是:'
                    print start_date,end_date,low_price,high_price,remain
                    try:
                        if room_name == u'默认都行':
                            selected =  self.hotel_inf[(self.hotel_inf['date']>=start_date)
                                                           &(self.hotel_inf['date']<=end_date)
                                                           &(self.hotel_inf['price']>=low_price)
                                                           &(self.hotel_inf['price']<=high_price)
                                                           &(self.hotel_inf['remain']>=remain)]

                        else:
                            selected = self.hotel_inf[(self.hotel_inf['date'] >= start_date)
                                                      & (self.hotel_inf['date'] <= end_date)
                                                      & (self.hotel_inf['price'] >= low_price)
                                                      & (self.hotel_inf['price'] <= high_price)
                                                      & (self.hotel_inf['remain'] >= remain)
                                                      & (self.hotel_inf['room_name'] == room_name)]

                        selected = selected[['hotel_name','stars','room_name','remain','price']]
                        print '满足条件的有'
                        print selected
                    except MySQLdb.Error:
                        self.conn.rollback()
                        selected = [-1,-1]
                    hotel = selected.drop_duplicates(subset='hotel_name',keep='first')
                    hotel = hotel.reset_index(drop=True)
                    hotel_name = hotel['hotel_name']
                    tk.Label(f2,
                             text='>>共搜到%d个酒店%d间房型满足您的条件\n点击酒店查看具体信息'%(len(hotel_name),len(selected)),
                             justify=tk.LEFT).grid(column=0)
                    ## 查询结果显示
                    def callback(hotel_index):
                        Inf = selected[selected['hotel_name'] == hotel_name[hotel_index]]
                        v3 = tk.IntVar()
                        v3.set(1)
                        Inf = Inf.reset_index(drop=True)
                        Inf = Inf[['room_name', 'remain', 'price']]
                        Inf.columns = ['房型', '剩余', '单价']
                        bg_colors = ['green', 'yellow', 'blue']
                        fg_colors = ['white', 'red', 'white']
                        ## 当用户选择了具体的房间后,进入确认预定界面,显示该用户信息和酒店信息
                        def get_room():
                             ensure_inf = OtherFrame('确认预定?')
                             global home_price
                             home_price = Inf.ix[v3.get()].tolist()
                             print [self.e1.get(), self.e2.get(), start_date, end_date, remain]
                             print home_price
                             def write_to_sql():
                                 try:
                                     # 插入user/hotel/room_name/nums/sday/eday/price
                                     sql_insert_order = "INSERT INTO  " \
                                                        "`user_order`(`user`,`hotel`,`room_name`,`nums`,`start_date`,`end_date`,`price`)" \
                                                        "VALUES('%s','%s','%s','%d','%s','%s','%d')"\
                                                        %(self.e1.get(),'UNSHOWED','UNSHOWED',int(remain),start_date,end_date,int(home_price[2]))
                                     self.cursor.execute(sql_insert_order)
                                     self.conn.commit()
                                     tk.Label(ensure_inf,text='预定成功').pack()
                                     tk.Button(ensure_inf,text='查看订单',command=watch_order).pack(side=tk.LEFT)
                                     tk.Button(ensure_inf,text='退出',command=self.leave).pack(side=tk.RIGHT)
                                     print '插入数据库的信息是:'
                                     print sql_insert_order
                                     print '预定成功'
                                 except MySQLdb.Error as e:
                                     tk.Label(ensure_inf, justify=tk.LEFT,text='预定失败\n'
                                                               '原因:\n'+'用户已经订过了').pack()
                                     tk.Button(ensure_inf, text='退出', command=self.leave).pack(side=tk.LEFT)
                                     tk.Button(ensure_inf, text='查看订单', command=watch_order).pack(side=tk.RIGHT)
                                     self.conn.rollback()
                             tk.Label(ensure_inf,text= '请确认你的预定操作\n用户:%s\n起始日期:%s\n'
                                       '结束日期:%s\n'
                                       '预定房数:%d\n'
                                      '单价:%d\n' %(self.e1.get(),start_date,end_date,remain,home_price[2]),
                                      bd=20,
                                      font=10).pack()
                             tk.Button(ensure_inf,text='确认',command=write_to_sql).pack()
                             ensure_inf.mainloop()

                        detail_inf = OtherFrame('❤请选择❤')
                        group = tk.LabelFrame(detail_inf,
                                              text='》》点击预定《《',
                                              padx=10,
                                              pady=10,
                                              width=140,
                                              height=10,

                        )
                        group.pack()

                        for jj in range(len(Inf)):
                            tk.Radiobutton(group,
                                           text=Inf.ix[jj],
                                           variable=v3,
                                           value=jj,
                                           indicatoron=0,
                                           bg=bg_colors[jj],
                                           fg=fg_colors[jj],
                                           activebackground='red',
                                           justify=tk.LEFT,
                                           command=get_room).pack()
                        tk.Label(detail_inf,textvariable=v3).pack()
                        detail_inf.mainloop()

                    for ii in range(len(hotel_name)):
                        callback0 = lambda:callback(ii)
                        tk.Label(f2, text='⭐' * hotel.stars[ii], fg='red',font=5).grid()
                        tk.Button(f2,
                                  text=hotel_name[ii],
                                  compound=tk.CENTER,
                                  image=img,
                                  bd=10,
                                  height=30,width=150,
                                  font=('幼圆',20),
                                  command=callback0).grid()
                    self.conn.rollback()
                tk.Button(f1, text='搜索', command=get_hotel_inf).grid(row=7, columns=2)
                tk.Button(f1,text='重新搜索',command=self.login).grid(row=7,column=3)
                tk.Button(f1,text='高级筛选',command=self.customed_select).grid(row=7,columns=4)
                top_login.mainloop()

            else:
                self.var1.set('密码错误')
        else:
            self.var1.set('用户名不存在,欢迎注册')
    ### 用户自定义高级筛选,这些查询就比较变态

    def customed_select(self):
        # 点击第一种变态查询的响应

        def select1():
            def select1_inf():
                if select1_ttk.get() == '不限':
                    sql_select1 = "select DISTINCT hotel_name,room_name FROM (room_type NATURAL JOIN hotel)"
                else:
                    sql_select1 = "select DISTINCT hotel_name,room_name FROM (room_type NATURAL JOIN hotel)" \
                              " where hotel_name='{}'".format(select1_ttk.get())

                self.cursor.execute(sql_select1)
                cs2_inf = self.cursor.fetchall()
                cs2_l1 = tk.Listbox(select1_lf2,width=30)
                for ii in cs2_inf:
                    cs2_l1.insert(tk.END,ii)
                cs2_l1.pack()

            cs2 = OtherFrame('酒店:房型')
            tk.Label(cs2, text='查询酒店房型列表,返回酒店名,房型名').pack()
            select1_lf1 = tk.LabelFrame(cs2, text='选择酒店')
            select1_lf1.pack()
            select1_var = tk.StringVar()
            select1_ttk = ttk.Combobox(select1_lf1, textvariable=select1_var, state='readonly',
                                       values=['惠民旅馆', '风景旅馆', '商务旅馆'])
            select1_ttk.current(0)
            select1_ttk.set('不限')
            select1_ttk.pack(side=tk.LEFT)
            tk.Button(select1_lf1, text='查询', command=select1_inf).pack(side=tk.LEFT)
            tk.Button(select1_lf1, text='重置', command=select1).pack(side=tk.RIGHT)
            tk.Button(cs2, text='返回', command=self.customed_select).pack(side=tk.LEFT)
            tk.Button(cs2, text='退出', command=self.leave).pack(side=tk.RIGHT)
            select1_lf2 = tk.LabelFrame(cs2, text='查询结果')
            select1_lf2.pack()
            cs2.mainloop()

        # 点击第二种变态查询的响应
        def select2():
            # 用户选择日期后的信息显示响应
            def select2_inf():
                sql_select2 = "SELECT hotel_name,avg(price) as avg_price,date " \
                              "from (room_type NATURAL JOIN hotel)NATURAL JOIN room_info " \
                              "where date='{}' " \
                              "GROUP BY hotel_id " \
                              "ORDER BY avg_price".format(select2_ttk.get())
                self.cursor.execute(sql_select2)
                cs3_inf = self.cursor.fetchall()
                cs3_l1 = tk.Listbox(select2_lf2,width=30)
                for ii in cs3_inf:
                    cs3_l1.insert(tk.END, ii)
                cs3_l1.insert(0,['Hotel','Date','Avg_Price'])
                cs3_l1.pack()

            cs3 = OtherFrame('酒店-日期-均价')
            tk.Label(cs3,text='查询酒店某天所有房型的平均价格并从低\n到高排序,返回酒店名,日期,平均价格').pack()
            select2_lf1 = tk.LabelFrame(cs3,text='选择日期')
            select2_lf1.pack()
            select2_ttk = ttk.Combobox(select2_lf1, values=['2018-11-14','2018-11-15','2018-11-16'],state='readonly')
            select2_ttk.current(0)
            select2_ttk.pack(side=tk.LEFT)
            tk.Button(select2_lf1, text='查询', command=select2_inf).pack(side=tk.LEFT)
            tk.Button(select2_lf1, text='重置', command=select2).pack(side=tk.RIGHT)
            tk.Button(cs3, text='返回', command=self.customed_select).pack(side=tk.LEFT)
            tk.Button(cs3, text='退出', command=self.leave).pack(side=tk.RIGHT)
            select2_lf2 = tk.LabelFrame(cs3, text='查询结果')
            select2_lf2.pack()
            cs3.mainloop()
        # 点击第三种变态查询的响应
        def select3():
            def select3_inf():
                sql_select3 = "SELECT hotel_name,room_name,avg(price) as avg_price " \
                              "from((SELECT *,count(room_name) from (room_type NATURAL JOIN hotel)NATURAL JOIN room_info " \
                              "where date>='{0}' AND date<='{1}' AND remain>=4  " \
                              "GROUP BY room_name " \
                              "HAVING count(room_name)={2})as M) " \
                              "GROUP BY room_name " \
                              "ORDER BY avg_price".format(select3_ttk1.get(),select3_ttk2.get(),int(select3_ttk3.get()))
                print sql_select3
                self.cursor.execute(sql_select3)
                cs4_inf = self.cursor.fetchall()
                cs4_l1 = tk.Listbox(select3_lf2, width=30)
                for ii in cs4_inf:
                    cs4_l1.insert(tk.END,ii)
                cs4_l1.pack()

            cs4 = OtherFrame('酒店—房型-剩余数')
            tk.Label(cs4, text='指定时间范围和要型预定房的\n房间数量,查询满足条件(时间,剩余\n房间数量)的房型及其平均价格,\n'
                            '并按房型平均价格从低到高进行排序。\n查询结果应包含酒店,房型及平均价格信息',
                  justify=tk.LEFT).pack()
            select3_lf1 = tk.LabelFrame(cs4, text='请选择')
            select3_lf1.pack()
            tk.Label(select3_lf1,text='起始日期').pack()
            select3_ttk1 = ttk.Combobox(select3_lf1, values=['2018-11-14', '2018-11-15', '2018-11-16'],
                                        state='readonly')
            select3_ttk1.current(0)
            select3_ttk1.pack()
            tk.Label(select3_lf1,text='结束日期').pack()
            select3_ttk2 = ttk.Combobox(select3_lf1, values=['2018-11-14', '2018-11-15', '2018-11-16'],state='readonly')
            select3_ttk2.current(0)
            select3_ttk2.pack()
            tk.Label(select3_lf1, text='预定数').pack()
            select3_ttk3 = ttk.Combobox(select3_lf1, values=['1', '2', '3','4','5'],
                                        state='readonly')
            select3_ttk3.current(0)
            select3_ttk3.pack()
            tk.Button(cs4,text='查询',command=select3_inf).pack()
            tk.Button(cs4, text='重置', command=select3).pack()
            tk.Button(cs4,text='退出',command=self.leave).pack(side=tk.RIGHT)
            tk.Button(cs4,text='返回',command=self.customed_select).pack(side=tk.LEFT)
            select3_lf2 = tk.LabelFrame(cs4, text='查询结果')
            select3_lf2.pack()
            cs4.mainloop()
        # 点击第四种变态查询的响应
        def select4():
            def select4_inf():
                sql_select4 = "SELECT hotel_name,'{0}' as date,room_name,sum(amount) as sum_amount " \
                              "FROM (`order` NATURAL join room_type)NATURAL JOIN hotel " \
                              "WHERE start_date<='{1}' and leave_date>='{2}'" \
                              "GROUP BY room_name".format(select4_ttk.get(),select4_ttk.get(),select4_ttk.get())
                self.cursor.execute(sql_select4)
                cs5_inf = self.cursor.fetchall()
                cs5_l1 = tk.Listbox(select4_lf2,width=30)
                for ii in cs5_inf:
                    cs5_l1.insert(0, ii)
                cs5_l1.pack()

            cs5 = OtherFrame('酒店—房型-剩余数')
            tk.Label(cs5, text='查询指定日期,各酒店,各房型的预定数量',
                  justify=tk.LEFT).pack()
            select4_lf1 = tk.LabelFrame(cs5, text='日期选择')
            select4_lf1.pack()
            select4_ttk = ttk.Combobox(select4_lf1,values=['2018-11-14','2018-11-15','2018-11-16'],state='readonly')
            select4_ttk.current(0)
            select4_ttk.pack()
            tk.Button(select4_lf1,text='查询', command=select4_inf).pack(side=tk.LEFT)
            tk.Button(select4_lf1,text='重置',command=select4).pack(side=tk.RIGHT)
            tk.Button(cs5,text='退出',command=self.leave).pack(side=tk.RIGHT)
            tk.Button(cs5,text='返回',command=self.customed_select).pack(side=tk.LEFT)
            select4_lf2 = tk.LabelFrame(cs5, text='查询结果')
            select4_lf2.pack()
            cs5.mainloop()

        def select5():
            def select5_inf():
                pass
            pass

        ## 集中变态查询的选择界面框架组织
        cs1 = OtherFrame('高级查询')
        lf1 = tk.LabelFrame(cs1,text='>>请选择你想进行的具体查询,点击进入<<')
        lf1.pack()
        tk.Button(lf1,text = '查询酒店房型列表,返回酒店名,房型名',
                  command=select1,bd=4,width=35,bg='blue',fg='white',activebackground='red').pack()
        tk.Label(lf1,text='').pack()
        tk.Button(lf1, text='查询酒店某天所有房型的平均价格并从低\n到高排序,返回酒店名,日期,平均价格',
                  justify=tk.LEFT,
                  command=select2,bd=4,width=35,bg='blue',fg='white',activebackground='red').pack()
        tk.Label(lf1, text='').pack()
        tk.Button(lf1, text='指定时间范围和要型预定房的\n房间数量,查询满足条件(时间,剩余\n房间数量)的房型及其平均价格,\n'
                            '并按房型平均价格从低到高进行排序。\n查询结果应包含酒店,房型及平均价格信息',
                  justify=tk.LEFT,
                  command=select3,bd=4,width=35,bg='blue',fg='white',activebackground='red').pack()
        tk.Label(lf1, text='').pack()
        tk.Button(lf1, text='查询指定日期,各酒店,各房型的预定数量',
                  command=select4,bd=4,width=35,bg='blue',fg='white',activebackground='red').pack()
        tk.Label(lf1, text='').pack()
        tk.Button(lf1, text='Q6那种变态筛选',
                  command=select4, bd=4, width=35, bg='blue', fg='white', activebackground='red').pack()
        tk.Label(lf1, text='').pack()
        tk.Button(lf1,text='返回普通筛选',command=self.login,bg='pink').pack(side=tk.LEFT)
        tk.Button(lf1, text='退出', command=self.leave,bg='red').pack(side=tk.RIGHT)
        cs1.mainloop()
    ## 根据用户选择的变态查询,访问数据库查询函数
    def select_operation(self,select_sql):
        try:
            self.cursor.execute(select_sql)
            Inf = self.cursor.fetchall()
            print '查询成功,信息如下:'
            for each_line in Inf:
                print each_line
        except MySQLdb.Error as e:
            print 'select wrong'+str(e)
            self.conn.rollback()
            Inf = 0
        return Inf

    def other_operation(self,sql_insert):
        try:
            self.cursor.execute(sql_insert)
            n = self.cursor.rowcount
            self.conn.commit()
            print '成功,共更新%d条记录'%int(n)
        except MySQLdb.Error as e:
            print 'insert wrong'+str(e)
            self.conn.rollback()

    ## 登陆验证界面和主查询界面的转换
    def close_open(self,close_window,open_window):
        close_window.withdraw()
        open_window.update()
        open_window.deiconify()

   ## 定义用户订单的界面
    def order(self):
        def search_hotel():
            top_order.withdraw()
            self.login()
        def watch_order():
            top_login.withdraw()
            top_login.destroy()
            self.order()
        top_order = tk.Toplevel()
        top_order.iconbitmap('hotel1.ico')
        top_order.geometry('300x450+500+100')
        top_order.title('登陆成功,欢迎您:%s' % (self.e1.get()))
        f0 = tk.Frame(top_order)
        f1 = tk.Frame(top_order, bg='gray')
        select_b1 = tk.Button(f0, text='酒店查询', fg='white', bg='blue', width=17,command=search_hotel)
        select_b1.pack(side=tk.LEFT)
        select_b2 = tk.Button(f0, text='订单查询', fg='white', bg='blue', width=17,command=watch_order)
        select_b2.pack(side=tk.RIGHT)
        try:
            self.conn.rollback()
            sql_sel = "select * from `user_order` where user='%s' "%self.e1.get()
            self.cursor.execute(sql_sel)
            search_inf = self.cursor.fetchone()
            print '查询成功'
        except MySQLdb.Error as e:
            search_inf = []
            print '查询失败'
            print e

        print '用户的最终选择为:'
        print search_inf
        try:
            tk.Label(f1,text='用户名',fg='red').grid(row=0,column=0)
            tk.Label(f1,text=self.e1.get(),fg='blue').grid(row=0,column=3)
            tk.Label(f1, text='酒店',fg='red').grid(row=1,column=0)
            hotel_sel = selected['hotel_name'].tolist()
            tk.Label(f1, text=hotel_sel[0],fg='blue').grid(row=1,column=3)
            tk.Label(f1, text='房型',fg='red').grid(row=2,column=0)
            tk.Label(f1, text=home_price[0],fg='blue').grid(row=2,column=3)
            tk.Label(f1, text='预定数量',fg='red').grid(row=3,column=0)
            tk.Label(f1, text=remain,fg='blue').grid(row=3,column=3)
            tk.Label(f1, text='入住时间',fg='red').grid(row=4,column=0)
            tk.Label(f1, text=start_date,fg='blue').grid(row=4,column=3)
            tk.Label(f1, text='退房时间',fg='red').grid(row=5,column=0)
            tk.Label(f1, text=end_date,fg='blue').grid(row=5,column=3)
            tk.Label(f1, text='单价',fg='red').grid(row=6,column=0)
            tk.Label(f1, text=home_price[2],fg='blue').grid(row=6,column=3)
            tk.Button(f1, text='退出', command=self.leave).grid(row=9,column=0)
            tk.Button(f1, text='修改订单', command=self.forget_pwd).grid(row=9,column=3)
        except:
            tk.Label(f1, text='暂时没有订单信息', fg='blue').grid(row=6, column=0)
            tk.Button(f1, text='退出', command=self.leave).grid(row=9, column=0)
            tk.Button(f1, text='修改订单', command=self.forget_pwd).grid(row=9, column=3)
        f0.pack()
        f1.pack()
        top_order.mainloop()

    ## 用户选择退出程序,关闭数据库连接,关闭界面
    def leave(self):

        print '正在关闭数据库连接'
        self.cursor.close()
        self.conn.close()
        print '数据库连接已经关闭'
        print '正在关闭窗口'
        self.root.withdraw()
        self.root.destroy()
        print '窗口关闭完成'

    ## 注册界面
    def _register(self):
        self.root.withdraw()
        self.top_register = OtherFrame('你好')
        self.top_register.title('账号注册')
        top_pic = tk.Frame(self.top_register)
        top = tk.Frame(self.top_register)
        tk.Label(top_pic,image=img,bd=80,height=10,width=140).pack()
        tk.Label(top, text='用户名').grid(row=1)
        tk.Label(top, text='密码').grid(row=3)
        tk.Label(top, text='确认密码').grid(row=5)
        tk.Label(top, text='身份证号').grid(row=7)
        tk.Label(top, text='电话').grid(row=9)
        self.v1 = tk.StringVar()
        self.v2 = tk.StringVar()
        self.v3 = tk.StringVar()
        self.v4 = tk.StringVar()
        self.v5 = tk.StringVar()
        e1 = tk.Entry(top, width=20,textvariable=self.v1) # 设置你的用户名
        e2 = tk.Entry(top,  width=20,show='*',textvariable=self.v2) # 设置你的密码
        e3 = tk.Entry(top,  width=20, show='*',textvariable=self.v3) # 确认你的密码
        e4 = tk.Entry(top, width=20,textvariable=self.v4) # 设置你的身份号
        e5 = tk.Entry(top, width=20,textvariable=self.v5) # 设置你的电话
        e1.grid(row=1, column=1, padx=1, pady=1)
        e2.grid(row=3, column=1, padx=1, pady=1)
        e3.grid(row=5, column=1, padx=1, pady=1)
        e4.grid(row=7, column=1, padx=1, pady=1)
        e5.grid(row=9, column=1, padx=1, pady=1)
        handle = lambda: self.close_open(self.top_register,self.root)
        tk.Button(top, text='<<返回登陆界面',fg='white',bg='blue',
                  command=handle).grid(row=11, column=0, padx=10, pady=1)
        tk.Button(top, text='>>注册你的账号',bg='blue',fg='white',
                  command=self.save_inf).grid(row=11, column=1, padx=10, pady=1)
        self.register_var = tk.StringVar()
        self.register_var.set('')
        tk.Label(top,textvariable=self.register_var,fg='red').grid(row=13,column=1)
        top_pic.pack()
        top.pack()
        self.top_register.mainloop()

    ## 存储用户的注册信息
    def save_inf(self):
         if self.v2.get() != self.v3.get():
             self.register_var.set('两次密码输入不一致')
         elif self.v1.get() in self.dict_inf.keys():
             self.register_var.set('用户名已经存在')
         elif self.v1.get()=='' or self.v2.get()=='' or self.v3.get()=='' or self.v4.get()==''or self.v5.get()=='':
             self.register_var.set('信息输入不完整')
         else:
             try:
                sql_insert = "insert into user_inf values('%s','%s','%s','%s')"%(self.v1.get(),self.v2.get(),self.v4.get(),self.v5.get())
                self.cursor.execute(sql_insert)
                self.conn.commit()
                self.register_var.set('注册成功,点击跳转')
                time.sleep(1)
                register_to_login = lambda: self.close_open(self.top_register, top_login)
                tk.Button(self.top_register,
                          text='注册成功,点击跳转',
                          command=register_to_login).grid(row=16)

             except MySQLdb.Error as e:
                self.conn.rollback()
                print '写入错误'+str(e)

    ## 用户选忘记密码的响应,这里为了简便不提供支持,其实很简单
    def forget_pwd(self):
        print '这只是个按钮,暂不提供支持'
        self.var1.set('~忘了吧,不提供支持了~')

if __name__ == "__main__":
    root0 = MainFrame('酒店预定系统')
    user_login(root0)
    root0.mainloop()

猜你喜欢

转载自blog.csdn.net/qq_40527086/article/details/84672554