主頁 > 後端開發 > PyQt5 快速開發 - 學生管理系統專案實戰報告

PyQt5 快速開發 - 學生管理系統專案實戰報告

2022-01-03 08:29:48 後端開發

PyQt5 快速開發 - 學生管理系統專案實戰報告

  • 一、登陸界面搭建
  • 二、登陸驗證
  • 三、主界面
    • 1、初始化
    • 2、添加控制元件
    • 3、設定函式與信號
    • 4、樹的函式
    • 5、右鍵選項信號槽
    • 6、資料表顯示函式
    • 7、運行代碼按鈕信號槽
    • 8、代碼輸入框
    • 9、清空按鈕與富文本瀏覽器
  • 四、新建資料表對話框
    • 1、添加控制元件
    • 2、初始化對話框
    • 3、設定控制元件屬性
    • 4、確定按鈕信號槽
    • 5、連接 UI 表單
  • 五、洗掉記錄對話框
  • 六、全部代碼

為了實作我的計劃,我使用 PyQt5 撰寫程式,制作了一個簡易 GUI 的 學生管理系統,作為 2021 年最后一個程式,運用到了我在2021年所學的大部分知識,絕對算得上是壓軸程式,但是并沒有給界面做美化,

  • 登錄界面
    在這里插入圖片描述
  • 主界面
    在這里插入圖片描述

一、登陸界面搭建

登錄界面用的 Designer 可視化程式搭建的,動動滑鼠就能輕松搭建出一個用戶界面,
在這里插入圖片描述
然后在 Pycharm 中用 PyUIC 把 .ui 檔案轉為 .py 檔案,

二、登陸驗證

在界面程式中給兩個按鈕(登錄 和 退出)系結信號

# 退出
self.retranslateUi(widget)
self.pushButton_2.clicked.connect(widget.close)  # type: ignore

# 登錄
self.pushButton.clicked.connect(self.login_in)  # type: ignore
self.pushButton.setShortcut('Return')

寫登錄信號槽

# 驗證登錄
def login_in(self):
	# 全域變數傳參給其他所有界面
    global gl_db
    global gl_host
    global gl_pwd
    global gl_user
    global gl_port

    gl_db = self.lineEdit_5.text()
    gl_host = self.lineEdit_3.text()
    gl_pwd = self.lineEdit_2.text()
    gl_user = self.lineEdit.text()
    try:
        port = int(self.lineEdit_4.text())
        try:
            conn = pymysql.connect(host=gl_host, port=gl_port, db=gl_db, user=gl_user, password=gl_pwd)
            print('登錄資料庫{}成功'.format(gl_db))
            self.messageDialog('提示', '登錄資料庫{}成功'.format(gl_db))
            conn.close()
            del conn
            # 登錄成功后跳轉到主界面
            self.main_show = Fulling()
            self.main_show.show()
            mainWindow.close()
        except pymysql.err.OperationalError:
            print('由于目標計算機積極拒絕,無法連接,')
            self.messageDialog('警告', '由于目標計算機積極拒絕,無法連接,')
    except ValueError:
        print('埠號錯誤')
        self.messageDialog('警告', '埠號錯誤')
    except Exception as err:
        print('錯誤:', err)
        self.messageDialog('警告', str(err))

# 提示資訊
def messageDialog(self, title, text):
    msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, text)
    msg_box.exec_()

登錄邏輯程式代碼

class Login(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(600, 400)  # 禁止拖動
        self.setWindowIcon(QtGui.QIcon('./img/001.ico'))  # 設定表單標題圖示
        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)  # 禁用最大化

        # 背景圖片
        image = QtGui.QPixmap()
        image.load(r'./img/login_bg.jpg')
        bg = QtGui.QPalette()
        bg.setBrush(self.backgroundRole(), QtGui.QBrush(image))
        self.setPalette(bg)
        self.setAutoFillBackground(True)


if __name__ == '__main__':
    gl_db = ''
    gl_host = ''
    gl_pwd = ''
    gl_user = ''
    gl_port = 0
    # 創建 QApplication 類的實體
    logapp = QApplication(sys.argv)
    # 創建表單
    mainWindow = Login()
    # 關聯login
    ui = Ui_widget()
    ui.setupUi(mainWindow)
    # 打開表單
    mainWindow.show()
    # 退出表單
    sys.exit(logapp.exec_())

在這里插入圖片描述

三、主界面

因為主界面涉及到的控制元件比較復雜,所以直接用代碼寫出來,不使用 Designer,

1、初始化

  • 先給界面初始化,標題,視窗大小,圖示,控制元件,并且連接資料庫
class Fulling(QWidget):
	# 初始化
    def __init__(self):
        super().__init__()
        # 視窗標題
        self.setWindowTitle('學生管理系統')
        # 視窗大小
        self.resize(720, 600)
        # 視窗居中
        self.center()
        # 圖示
        self.setWindowIcon(QIcon('./img/001.ico'))
        # 連接資料庫
        self.conn = pymysql.connect(host=gl_host, port=gl_port, user=gl_user, password=gl_pwd, db=gl_db)
        self.tree_view = None
        self.table_view = None
        self.queryModel = None
        self.text_edit = None
        self.run_button = None
        self.row = None
        self.vol = None
        self.text_browser = None
        self.clear_button = None
        self.add_db_view = None
        self.del_db_view = None
        self.cur = self.conn.cursor()
        self.init_ui()

	# 視窗居中
    def center(self):
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move(round((screen.width() - size.width()) / 2), round((screen.height() - size.height()) / 2))

	# 警告資訊
    @staticmethod
    def message_dialog(title, text):
        msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, text)
        msg_box.exec_()

2、添加控制元件

  • 視窗添加控制元件,并為他們布局
	# 視窗布局
	def create_window(self):
	    # 設定樹屬性
	    self.tree_view = QTreeWidget()
	    # 設定表格屬性
	    self.table_view = QTableWidget()
	    # 設定文本框
	    self.text_edit = QTextEdit()
	    # 設定運行按鈕
	    self.run_button = QPushButton('運行所有代碼')
	    # 設定清空按鈕
	    self.clear_button = QPushButton('清空代碼')
	    # 設定查看文本
	    self.text_browser = QTextBrowser()
	    # 表格寬度自適應
	    self.table_view.horizontalHeader().setStretchLastSection(True)
	    self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
	
	    # 左側布局
	    left_layout = QVBoxLayout()
	    left_layout.addWidget(self.tree_view, 15)
	    left_layout.addWidget(self.text_browser, 9)
	
	    # 右中
	    mid_layout = QHBoxLayout()
	    mid_layout.addWidget(self.run_button)
	    mid_layout.addWidget(self.clear_button)
	    mid_layout.addWidget(QSplitter())
	
	    # 右側布局
	    right_layout = QVBoxLayout()
	    right_layout.addWidget(self.table_view, 15)
	    right_layout.addLayout(mid_layout, 1)
	    right_layout.addWidget(self.text_edit, 8)
	
	    # 創建界面
	    layout = QHBoxLayout(self)
	    layout.addLayout(left_layout, 1)
	    layout.addLayout(right_layout, 3)
	    self.setLayout(layout)

3、設定函式與信號

  • 給每個控制元件添加自己的函式和信號
	# 設定視窗主要部件和信號
	def init_ui(self):
	    # 創建視窗
	    self.create_window()
	    # 設定樹
	    self.set_tree_view()
	    # 設定表格
	    self.set_table_view()
	    # 設定文本框
	    self.set_text_edit()
	    # 創建運行按鈕
	    self.set_run_button()
	    # 創建清空按鈕
	    self.set_clear_button()
	    # 創建查看文本
	    self.set_text_browser()
	
	    # 信號槽
	    self.tree_view.clicked.connect(self.on_tree_clicked)
	    self.run_button.clicked.connect(self.run_program)
	    self.clear_button.clicked.connect(self.clear_all)
	
	    # 給樹添加右鍵
	    self.tree_view.setContextMenuPolicy(Qt.CustomContextMenu)
	    self.tree_view.customContextMenuRequested.connect(self.right_menu_show)
	
	    # 運行按鈕快捷鍵
	    self.run_button.setShortcut('F5')

4、樹的函式

  • 讓樹能夠顯示所有的資料表
  • 本來想的是把所有的資料表、視圖、事件等都顯示出來,但是這里我只寫了顯示資料表
    # 樹
    def set_tree_view(self):
        # 樹行數
        self.tree_view.setColumnCount(1)
        # 樹標題
        self.tree_view.setHeaderLabel(gl_db + '.db')
        # 設定根節點
        root = QtWidgets.QTreeWidgetItem(self.tree_view)
        root.setText(0, '表')  # 只有一列
        root.setIcon(0, QIcon('img/db_logo.png'))
        # 創建游標
        cursor = self.conn.cursor()
        cursor.execute("show tables;")
        res = cursor.fetchall()
        # 遍歷表
        for i in range(len(res)):
            child = QtWidgets.QTreeWidgetItem(root)  # 指定父目錄
            child.setText(0, res[i][0])
            child.setText(1, '{}'.format(i + 1))
            child.setIcon(0, QIcon('img/table_logo.png'))
        # 樹默認收縮
        root.setExpanded(False)
        # 樹根節點
        self.tree_view.addTopLevelItem(root)
  • 樹中左鍵單擊展開樹 或 打開資料表
    在這里插入圖片描述
    # 樹左鍵單擊
    def on_tree_clicked(self):
        try:
        	# 獲取樹中的內容
            item = self.tree_view.currentItem()
            # 如果單擊的是根目錄則展開或收縮樹
            if item.text(0) == '表':
                print('左鍵單擊{}'.format(item.text(0)))
                if self.tree_view.currentItem().isExpanded():
                    self.tree_view.collapseAll()
                else:
                    self.tree_view.expandAll()
                    
            # 如果單擊的是表則打開表
            else:
                item = self.tree_view.currentItem()
                self.cur.execute('select * from ' + item.text(0))
                self.select_run()
                print('左鍵單擊{}'.format(item.text(0)))
        except Exception as e:
            print('樹左鍵單擊{}'.format(e))
            self.message_dialog('提示', '請先輸入資料')
  • 樹中右鍵單擊顯示 右鍵選單選項
    在這里插入圖片描述
    # 樹右鍵單擊
    def right_menu_show(self):
        try:
            item = self.tree_view.currentItem()
            if item.text(0) == '表':
                print('右鍵單擊{}'.format(item.text(0)))
                # 添加選單選項
                self.contextMenu = QMenu()
                self.add_db = self.contextMenu.addAction(u'新建資料表')
                self.flash_db = self.contextMenu.addAction(u'重繪')
                self.close_db = self.contextMenu.addAction(u'退出')
                self.contextMenu.popup(QCursor.pos())
                # 給選單選項系結信號
                self.add_db.triggered.connect(self.add_database)  # type:ignore
                self.flash_db.triggered.connect(self.flash)  # type:ignore
                self.close_db.triggered.connect(self.close_database)  # type:ignore
                self.contextMenu.show()

            else:
                # 資料表的右鍵
                print('右鍵單擊{},序號是{}'.format(item.text(0), item.text(1)))
                self.contextMenu = QMenu()
                self.open = self.contextMenu.addAction(u'打開表')
                self.drop = self.contextMenu.addAction(u'洗掉表')
                self.add = self.contextMenu.addAction(u'添加記錄')
                self.delete = self.contextMenu.addAction(u'洗掉記錄')
                self.update = self.contextMenu.addAction(u'更改記錄')
                self.select = self.contextMenu.addAction(u'查詢記錄')
                self.open.triggered.connect(self.open_table)  # type:ignore
                self.drop.triggered.connect(self.drop_table)  # type:ignore
                self.add.triggered.connect(self.add_table)  # type:ignore
                self.delete.triggered.connect(self.delete_table)  # type:ignore
                self.update.triggered.connect(self.update_table)  # type:ignore
                self.select.triggered.connect(self.select_table)  # type:ignore
                self.contextMenu.popup(QCursor.pos())
                self.contextMenu.show()

        except Exception as e:
            print(e)

5、右鍵選項信號槽

  • 根目錄的右鍵選單
    在這里插入圖片描述
    # 樹重繪
    def flash(self):
        """添加資料表后的重繪操作"""
        print('重繪')
        item = self.tree_view.currentItem()
        root = QtWidgets.QTreeWidgetItem(self.tree_view)
        root.setText(0, '表')  # 只有一列
        root.setIcon(0, QIcon('img/db_logo.png'))
        cursor = self.conn.cursor()
        cursor.execute("show tables;")
        res = cursor.fetchall()

        # 清除樹
        curr_node = self.tree_view.currentItem()
        root_index = self.tree_view.indexOfTopLevelItem(curr_node)
        self.tree_view.takeTopLevelItem(root_index)

		# 再把重繪獲取的樹放上去
        for i in range(len(res)):
            child = QtWidgets.QTreeWidgetItem(root)  # 指定父目錄
            child.setText(0, res[i][0])
            child.setText(1, '{}'.format(i + 1))
            child.setIcon(0, QIcon('img/table_logo.png'))

    # 新建資料表 這里要用另外的視窗作為對話框,在第四點
    def add_database(self):
        try:
        	# 打開對話框
            self.add_db_view = AdDB()
            add_ui = Ui_add_db_object()
            add_ui.setupUi(self.add_db_view)
            self.add_db_view.show()
        except Exception as e:
            print(e)

        print('新建資料表')

    # 退出資料表
    def close_database(self):
        reply = QMessageBox.question(self, '退出', '確定退出', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            sender = self.sender()
            main_app_db = QApplication.instance()
            main_app_db.quit()
        print('退出資料表')
  • 資料表的右鍵選單,下面四個操作沒有寫完,因為需要新建一個對話框
    在這里插入圖片描述
    # 右鍵打開
    def open_table(self):
        item = self.tree_view.currentItem()
        self.cur.execute('select * from ' + item.text(0))
        self.select_run()
        print('打開 {}'.format(item.text(0)))

    # 右鍵洗掉表
    def drop_table(self):
        item = self.tree_view.currentItem()
        reply = QMessageBox.question(self, '洗掉表', '確定要洗掉嗎?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            self.cur.execute('drop table ' + item.text(0))
            self.text_browser.append('洗掉表 {} 成功,右擊根目錄重繪'.format(item.text(0)))
        print('洗掉 {}'.format(item.text(0)))

    # TODO 添加記錄
    def add_table(self):
        self.message_dialog('提示', '功能還沒開發')
        print('添加記錄')

    # TODO 洗掉記錄
    def delete_table(self):
        try:
            self.del_db_view = DelDB()
            del_ui = Ui_delete_win()
            del_ui.setupUi(self.del_db_view)
            self.del_db_view.show()
        except Exception as e:
            print(e)
        print('洗掉記錄')

    # TODO 更改記錄
    def update_table(self):
        self.message_dialog('提示', '功能還沒開發')
        print('更改記錄')

    # TODO 查詢記錄
    def select_table(self):
        self.message_dialog('提示', '功能還沒開發')
        print('查詢記錄')

6、資料表顯示函式

在這里插入圖片描述

  • 定義表格控制元件是用來顯示資料表的
    # 表格控制元件
    def set_table_view(self):
        self.cur.execute('show tables')
        db_len = self.cur.fetchone()
        self.cur.execute('select * from ' + db_len[0])  # 將資料從資料庫中拿出來
        self.select_run()
  • 讓所選表的資料顯示在表格控制元件里

這里的代碼參考的是 PyQt實作讀取MySql資料庫表資料將其顯示在TableWidget并保存為excel表格

    # 表格填充內容
    def table_data(self, i, j, data):
        item = QtWidgets.QTableWidgetItem()
        self.table_view.setItem(i, j, item)
        item = self.table_view.item(i, j)
        item.setText(str(data))

    # 運行查詢
    def select_run(self):
        try:
            total = self.cur.fetchall()
            col_result = self.cur.description
            self.row = self.cur.rowcount  # 取得記錄個數,用于設定表格的行數
            if self.row == 0:
                self.text_browser.moveCursor(QTextCursor.End)
                self.text_browser.append('資料表中沒有任何記錄')
            else:
                self.vol = len(total[0])  # 取得欄位數,用于設定表格的列數
                col_result = list(col_result)
                a = 0
                self.table_view.setColumnCount(self.vol)
                self.table_view.setRowCount(self.row)
                for i in col_result:  # 設定表頭資訊,將mysql資料表中的表頭資訊拿出來,放進TableWidget中
                    item = QtWidgets.QTableWidgetItem()
                    self.table_view.setHorizontalHeaderItem(a, item)
                    item = self.table_view.horizontalHeaderItem(a)
                    item.setText(i[0])
                    a = a + 1

                total = list(total)  # 將資料格式改為串列形式,其是將資料庫中取出的資料整體改為串列形式
                for i in range(len(total)):  # 將相關的資料
                    total[i] = list(total[i])  # 將獲取的資料轉為串列形式
                for i in range(self.row):
                    for j in range(self.vol):
                        self.table_data(i, j, total[i][j])
        except Exception as e:
            print(e)

7、運行代碼按鈕信號槽

在這里插入圖片描述

  • 運行代碼按鈕需要識別文本框內輸入的操作是增、刪、改、查、創建資料表中的哪一個
	# 運行按鈕
    def run_program(self):
        try:
            # 獲取填寫的代碼
            text = self.text_edit.toPlainText()
            # 刪掉所有的換行
            text = text.replace('\n', '')
            # 所有代碼大寫
            text = text.upper()
            # 不同代碼分片
            texts = text.split(';')
            for i in range(len(texts)):
                try:
                    if texts[i][:6] == 'SELECT':
                        print('執行查詢{}'.format(texts[i]))
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.select_run()
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('查詢{}'.format(texts[i]))
                        self.row_ref()
                    elif texts[i][:6] == 'UPDATE':
                        print('執行更新{}'.format(texts[i]))
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('更新{}'.format(texts[i]))
                        self.row_ref()
                    elif texts[i][:6] == 'INSERT':
                        print('執行插入{}'.format(texts[i]))
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('插入{}'.format(texts[i]))
                        self.row_ref()
                    elif texts[i][:6] == 'DELETE':
                        print('執行洗掉{}'.format(texts[i]))
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('洗掉{}'.format(texts[i]))
                        self.row_ref()
                    elif texts[i][:6] == 'CREATE' and texts[i].find('TABLE') != -1:
                        print('創建資料表')
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('創建資料表{}'.format(texts[i]))
                        self.flash()
                except Exception as e:
                    if '1096' in str(e):
                        print('沒有使用資料庫')
                        self.message_dialog('沒有使用資料庫', str(e))
                    elif '1054' in str(e):
                        print('沒有這個資料庫')
                        self.message_dialog('沒有這個資料庫', str(e))
                    elif '1064' in str(e):
                        print('語法錯誤')
                        self.message_dialog('語法錯誤', str(e))
                    else:
                        print('rr', e)
                        self.message_dialog('其他錯誤', str(e))
            print('run', text)
        except Exception as e:
            print('e:', e)
  • 執行 SQL 陳述句之后,查看影響行,把結果列印在富文本瀏覽器中
    在這里插入圖片描述
    在這里插入圖片描述
	# 查看受影響行
    def row_ref(self):
        cur_count = self.cur.rowcount
        if cur_count > 0:
            self.conn.commit()
            self.text_browser.moveCursor(QTextCursor.End)
            self.text_browser.append('執行成功')
        else:
            self.text_browser.moveCursor(QTextCursor.End)
            self.text_browser.append('執行失敗,影響0條記錄')

8、代碼輸入框

  • 顯示初始值
    在這里插入圖片描述
    # 文本框
    def set_text_edit(self):
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(14)
        self.text_edit.setFont(font)
        self.cur.execute('show tables;')
        db_len = self.cur.fetchone()
        self.text_edit.setPlaceholderText('SELECT * FROM {};\nGO;\n\n按F5運行代碼'.format(db_len[0]))

9、清空按鈕與富文本瀏覽器

  • 這兩個控制元件比較簡單,按一下清空代碼按鈕就在富文本瀏覽器中顯示資訊

在這里插入圖片描述

	# 富文本瀏覽器
	 def set_text_browser(self):
        self.text_browser.setPlaceholderText('操作記錄:')

    # 清空按鈕
    def set_clear_button(self):
        pass

    # 清空按鈕左鍵
    def clear_all(self):
        self.text_edit.setText('')
        self.text_browser.append('清空代碼區')

四、新建資料表對話框

1、添加控制元件

  • 界面簡單,就用 Designer 添加相應控制元件
  • 先弄成最多只能添加三個欄位
    在這里插入圖片描述
    在這里插入圖片描述

2、初始化對話框

class Ui_add_db_object(object):
    def __init__(self):
        super().__init__()
        self.conn = pymysql.connect(host=gl_host, port=gl_port, user=gl_user, password=gl_pwd, db=gl_db)
        self.cur = self.conn.cursor()

	# 警告資訊
    @staticmethod
    def message_dialog(title, text):
        msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, text)
        msg_box.exec_()

3、設定控制元件屬性

  • 設定字符長度最大值
  • 系結確定按鈕和取消按鈕的信號
  • 添加下拉選項
		# 設定字符長度最大值
        if self.label_1_comboBox.currentText() == 'char' or 'text' or 'varchar':
            self.label_1_spinBox.setMaximum(255)
        else:
            self.label_1_spinBox.setMaximum(2 ** 20)
        if self.label_2_comboBox.currentText() == 'char' or 'text' or 'varchar':
            self.label_2_spinBox.setMaximum(255)
        else:
            self.label_2_spinBox.setMaximum(2 ** 20)
        if self.label_3_comboBox.currentText() == 'char' or 'text' or 'varchar':
            self.label_3_spinBox.setMaximum(255)
        else:
            self.label_3_spinBox.setMaximum(2 ** 20)
            
		# 系結信號
        self.retranslateUi(add_db_object)
        self.add_no_pushButton_2.clicked.connect(add_db_object.close)  # type: ignore
        self.add_yes_pushButton.clicked.connect(lambda: self.add_true(add_db_object))  # type: ignore
        QtCore.QMetaObject.connectSlotsByName(add_db_object)

		# 添加資料型別下拉選項
        item_attribute = ['', 'char', 'int', 'float', 'text', 'varchar']
        self.label_1_comboBox.addItems(item_attribute)
        self.label_2_comboBox.addItems(item_attribute)
        self.label_3_comboBox.addItems(item_attribute)

4、確定按鈕信號槽

  • 按下確定按鈕后,檢查輸入的資料是否符合規范,包括:
    (1) 只有一個主鍵
    (2) 資料表名和欄位名符合規范
    (3) 是否填入了資料
    def add_true(self, add_db_object):
        try:
        	# 每個欄位的所有屬性添加進一個串列
            label_1 = [self.label_1_lineEdit.text(), self.label_1_comboBox.currentText(), self.label_1_spinBox.text(),
                       self.label_1_checkBox.isChecked()]
            label_2 = [self.label_2_lineEdit.text(), self.label_2_comboBox.currentText(), self.label_2_spinBox.text(),
                       self.label_2_checkBox.isChecked()]
            label_3 = [self.label_3_lineEdit.text(), self.label_3_comboBox.currentText(), self.label_3_spinBox.text(),
                       self.label_3_checkBox.isChecked()]
            print(label_1, label_2, label_3)
            
            add_count = 0
            add_item = []
            word = r'^\w+$'
            
            # 資料表名必填
            if len(self.table_name_lineEdit.text()) == 0:
                print(self.table_name_lineEdit.text())
                match_tana = re.match(word, self.label_1_lineEdit.text())
                self.message_dialog('警告', '資料表名必填')
                return
                if match_tana is None:
                    self.message_dialog('警告', '資料表名只能是英文、數字、下劃線')
                    return
                    
            # 主鍵只能有一個
            if self.label_1_checkBox.isChecked() and self.label_2_checkBox.isChecked() \
                    or self.label_1_checkBox.isChecked() and self.label_3_checkBox.isChecked() \
                    or self.label_2_checkBox.isChecked() and self.label_3_checkBox.isChecked():
                print('主鍵只能有一個')
                self.message_dialog('警告', '主鍵只能有一個')
                return

            else:
            	# 每個欄位的欄位名、欄位型別、欄位長度必填
                if "" not in label_1:
                    print(label_1)
                    # if len(self.label_1_lineEdit.text()) > 0:
                    match_1 = re.match(word, self.label_1_lineEdit.text())
                    if match_1 is None:
                        self.message_dialog('警告', '欄位名只能是英文、數字、下劃線')
                        return
                        
                    # 判斷主鍵是否選上
                    for i in range(len(label_1) - 1):
                        add_item.append(label_1[i])
                    if self.label_1_checkBox.isChecked():
                        add_item.append('primary key')
                    else:
                        add_item.append(' ')
                    add_count += 1

                if "" not in label_2:
                    print(label_2)
                    match_2 = re.match(word, self.label_2_lineEdit.text())
                    if match_2 is None:
                        self.message_dialog('警告', '欄位名只能是英文、數字、下劃線')
                        return
                    for i in range(len(label_2) - 1):
                        add_item.append(label_2[i])
                    if self.label_2_checkBox.isChecked():
                        add_item.append('primary key')
                    else:
                        add_item.append(' ')
                    add_count += 1

                if "" not in label_3:
                    print(label_3)
                    match_3 = re.match(word, self.label_3_lineEdit.text())
                    if match_3 is None:
                        self.message_dialog('警告', '欄位名只能是英文、數字、下劃線')
                        return
                    for i in range(len(label_3) - 1):
                        add_item.append(label_3[i])
                    if self.label_3_checkBox.isChecked():
                        add_item.append('primary key')
                    else:
                        add_item.append(' ')
                    add_count += 1

            if add_count == 0:
                self.message_dialog('警告', '必填欄位名、欄位型別、欄位長度')
                return
                
            # 執行 SQL 陳述句
            if len(add_item) == 4:
                self.cur.execute(
                    'create table ' + self.table_name_lineEdit.text() + '(' + add_item[0] + ' ' + add_item[1] + '(' +
                    add_item[2] + ') ' + add_item[3] + ');')
                self.conn.commit()
                self.message_dialog('提示', '添加完成,重繪資料表')
                self.cur.close()
                add_db_object.close()
            elif len(add_item) == 8:
                self.cur.execute(
                    'create table ' + self.table_name_lineEdit.text() + '(' + add_item[0] + ' ' + add_item[1] + '(' +
                    add_item[2] + ') ' + add_item[3] + ', ' + add_item[4] + ' ' + add_item[5] + '(' + add_item[
                        6] + ') ' +
                    add_item[7] + ');')
                self.conn.commit()
                self.cur.close()
                self.message_dialog('提示', '添加完成,重繪資料表')
                add_db_object.close()
            elif len(add_item) == 12:
                self.cur.execute(
                    'create table ' + self.table_name_lineEdit.text() + '(' + add_item[0] + ' ' + add_item[1] + '(' +
                    add_item[2] + ') ' + add_item[3] + ', ' + add_item[4] + ' ' + add_item[5] + '(' + add_item[
                        6] + ') ' +
                    add_item[7] + ' , ' + add_item[8] + ' ' + add_item[9] + '(' + add_item[10] + ') ' + add_item[
                        11] + ');')
                self.conn.commit()
                self.message_dialog('提示', '添加完成,重繪資料表')
                self.cur.close()
                add_db_object.close()
        except Exception as e:
            self.message_dialog('錯誤', e)

5、連接 UI 表單

class AdDB(QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(441, 511)  # 禁止拖動
        self.setWindowIcon(QtGui.QIcon('./img/001.ico'))  # 設定表單標題圖示
        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)  # 禁用最大化

五、洗掉記錄對話框

  • 只建立了一個表單,沒有操作代碼
    在這里插入圖片描述
class Ui_delete_win(object):
    def __init__(self):
        super().__init__()
        self.conn = pymysql.connect(host=gl_host, port=gl_port, user=gl_user, password=gl_pwd, db=gl_db)
        self.cur = self.conn.cursor()

    def setupUi(self, delete_win):
        delete_win.setObjectName("delete_win")
        delete_win.resize(400, 260)
        self.delete_yes = QtWidgets.QPushButton(delete_win)
        self.delete_yes.setGeometry(QtCore.QRect(80, 200, 81, 31))
        self.delete_yes.setObjectName("delete_yes")
        self.delete_no = QtWidgets.QPushButton(delete_win)
        self.delete_no.setGeometry(QtCore.QRect(220, 200, 81, 31))
        self.delete_no.setObjectName("delete_no")
        self.delete_header = QtWidgets.QTextBrowser(delete_win)
        self.delete_header.setGeometry(QtCore.QRect(120, 20, 171, 31))
        self.delete_header.setObjectName("delete_header")
        self.widget = QtWidgets.QWidget(delete_win)
        self.widget.setGeometry(QtCore.QRect(40, 70, 331, 111))
        self.widget.setObjectName("widget")
        self.gridLayout = QtWidgets.QGridLayout(self.widget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.delete_where_vue3 = QtWidgets.QLineEdit(self.widget)
        self.delete_where_vue3.setObjectName("delete_where_vue3")
        self.gridLayout.addWidget(self.delete_where_vue3, 2, 2, 1, 1)
        self.delete_where_vue2 = QtWidgets.QLineEdit(self.widget)
        self.delete_where_vue2.setObjectName("delete_where_vue2")
        self.gridLayout.addWidget(self.delete_where_vue2, 1, 2, 1, 1)
        self.delete_where_item3 = QtWidgets.QComboBox(self.widget)
        self.delete_where_item3.setObjectName("delete_where_item3")
        self.gridLayout.addWidget(self.delete_where_item3, 2, 1, 1, 1)
        self.delete_where = QtWidgets.QLabel(self.widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(3)
        sizePolicy.setHeightForWidth(self.delete_where.sizePolicy().hasHeightForWidth())
        self.delete_where.setSizePolicy(sizePolicy)
        self.delete_where.setObjectName("delete_where")
        self.gridLayout.addWidget(self.delete_where, 0, 0, 1, 1)
        self.delete_where_vue1 = QtWidgets.QLineEdit(self.widget)
        self.delete_where_vue1.setObjectName("delete_where_vue1")
        self.gridLayout.addWidget(self.delete_where_vue1, 0, 2, 1, 1)
        self.delete_where_item2 = QtWidgets.QComboBox(self.widget)
        self.delete_where_item2.setObjectName("delete_where_item2")
        self.gridLayout.addWidget(self.delete_where_item2, 1, 1, 1, 1)
        self.delete_where_item1 = QtWidgets.QComboBox(self.widget)
        self.delete_where_item1.setObjectName("delete_where_item1")
        self.gridLayout.addWidget(self.delete_where_item1, 0, 1, 1, 1)
        self.delete_and = QtWidgets.QLabel(self.widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(3)
        sizePolicy.setHeightForWidth(self.delete_and.sizePolicy().hasHeightForWidth())
        self.delete_and.setSizePolicy(sizePolicy)
        self.delete_and.setObjectName("delete_and")
        self.gridLayout.addWidget(self.delete_and, 1, 0, 1, 1)
        self.delete_and_2 = QtWidgets.QLabel(self.widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(3)
        sizePolicy.setHeightForWidth(self.delete_and_2.sizePolicy().hasHeightForWidth())
        self.delete_and_2.setSizePolicy(sizePolicy)
        self.delete_and_2.setObjectName("delete_and_2")
        self.gridLayout.addWidget(self.delete_and_2, 2, 0, 1, 1)

        self.retranslateUi(delete_win)
        self.delete_no.clicked.connect(delete_win.close)  # type: ignore
        QtCore.QMetaObject.connectSlotsByName(delete_win)

        self.delete_yes.clicked.connect(lambda: self.delete_fun())  # type: ignore

        delete_win.setTabOrder(self.delete_header, self.delete_where_item1)
        delete_win.setTabOrder(self.delete_where_item1, self.delete_where_vue1)
        delete_win.setTabOrder(self.delete_where_vue1, self.delete_where_item2)
        delete_win.setTabOrder(self.delete_where_item2, self.delete_where_vue2)
        delete_win.setTabOrder(self.delete_where_vue2, self.delete_where_item3)
        delete_win.setTabOrder(self.delete_where_item3, self.delete_where_vue3)
        delete_win.setTabOrder(self.delete_where_vue3, self.delete_yes)
        delete_win.setTabOrder(self.delete_yes, self.delete_no)

    # TODO 洗掉記錄
    def delete_fun(self):
        print('555')

    def retranslateUi(self, delete_win):
        _translate = QtCore.QCoreApplication.translate
        delete_win.setWindowTitle(_translate("delete_win", "洗掉記錄"))
        self.delete_yes.setText(_translate("delete_win", "確定"))
        self.delete_no.setText(_translate("delete_win", "取消"))
        self.delete_where.setText(_translate("delete_win", "where"))
        self.delete_and.setText(_translate("delete_win", "and"))
        self.delete_and_2.setText(_translate("delete_win", "and"))

class DelDB(QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(400, 260)  # 禁止拖動
        self.setWindowIcon(QtGui.QIcon('./img/001.ico'))  # 設定表單標題圖示
        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)  # 禁用最大化

六、全部代碼

#!/bin/sh
# !/usr/bin/python
# !/usr/bin/env
# -*- coding: utf-8 -*-

"""
Author: Fulling
Function: 學生管理系統
Date: 2021-12-31
"""

import sys
import pymysql
import re
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.Qt import *


class Fulling(QWidget):
    def __init__(self):
        super().__init__()
        # 視窗標題
        self.setWindowTitle('學生管理系統')
        # 視窗大小
        self.resize(720, 600)
        # 視窗居中
        self.center()
        # 圖示
        self.setWindowIcon(QIcon('./img/001.ico'))
        # 連接資料庫
        self.conn = pymysql.connect(host=gl_host, port=gl_port, user=gl_user, password=gl_pwd, db=gl_db)
        self.tree_view = None
        self.table_view = None
        self.queryModel = None
        self.text_edit = None
        self.run_button = None
        self.row = None
        self.vol = None
        self.text_browser = None
        self.clear_button = None
        self.add_db_view = None
        self.del_db_view = None
        self.cur = self.conn.cursor()
        self.init_ui()

    # 設定視窗主要部件和信號
    def init_ui(self):
        # 創建視窗
        self.create_window()
        # 設定樹
        self.set_tree_view()
        # 設定表格
        self.set_table_view()
        # 設定文本框
        self.set_text_edit()
        # 創建運行按鈕
        self.set_run_button()
        # 創建清空按鈕
        self.set_clear_button()
        # 創建查看文本
        self.set_text_browser()

        # TODO 信號槽
        self.tree_view.clicked.connect(self.on_tree_clicked)
        self.run_button.clicked.connect(self.run_program)
        self.clear_button.clicked.connect(self.clear_all)

        # 右鍵
        self.tree_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree_view.customContextMenuRequested.connect(self.right_menu_show)
        # self.text_edit.setContextMenuPolicy(Qt.CustomContextMenu)
        # self.text_edit.customContextMenuRequested[QtCore.QPoint].connect(self.text_right_menu)

        # 快捷鍵
        self.run_button.setShortcut('F5')

    # 視窗居中
    def center(self):
        """
        視窗居中
        :return:
        """
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move(round((screen.width() - size.width()) / 2), round((screen.height() - size.height()) / 2))

    # 視窗布局
    def create_window(self):
        # 設定樹屬性
        self.tree_view = QTreeWidget()
        # 設定表格屬性
        self.table_view = QTableWidget()
        # 設定文本框
        self.text_edit = QTextEdit()
        # 設定運行按鈕
        self.run_button = QPushButton('運行所有代碼')
        # 設定清空按鈕
        self.clear_button = QPushButton('清空代碼')
        # 設定查看文本
        self.text_browser = QTextBrowser()
        # 表格寬度自適應
        self.table_view.horizontalHeader().setStretchLastSection(True)
        self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # 左側布局
        left_layout = QVBoxLayout()
        left_layout.addWidget(self.tree_view, 15)
        left_layout.addWidget(self.text_browser, 9)

        # 右中
        mid_layout = QHBoxLayout()
        mid_layout.addWidget(self.run_button)
        mid_layout.addWidget(self.clear_button)
        mid_layout.addWidget(QSplitter())

        # 右側布局
        right_layout = QVBoxLayout()
        right_layout.addWidget(self.table_view, 15)
        right_layout.addLayout(mid_layout, 1)
        right_layout.addWidget(self.text_edit, 8)

        # 創建界面
        layout = QHBoxLayout(self)
        layout.addLayout(left_layout, 1)
        layout.addLayout(right_layout, 3)
        self.setLayout(layout)

    # 表格填充內容
    def table_data(self, i, j, data):
        item = QtWidgets.QTableWidgetItem()
        self.table_view.setItem(i, j, item)
        item = self.table_view.item(i, j)
        item.setText(str(data))

    # 運行查詢
    def select_run(self):
        try:
            total = self.cur.fetchall()
            col_result = self.cur.description
            self.row = self.cur.rowcount  # 取得記錄個數,用于設定表格的行數
            if self.row == 0:
                self.text_browser.moveCursor(QTextCursor.End)
                self.text_browser.append('資料表中沒有任何記錄')
            else:
                self.vol = len(total[0])  # 取得欄位數,用于設定表格的列數
                col_result = list(col_result)
                a = 0
                self.table_view.setColumnCount(self.vol)
                self.table_view.setRowCount(self.row)
                for i in col_result:  # 設定表頭資訊,將mysql資料表中的表頭資訊拿出來,放進TableWidget中
                    item = QtWidgets.QTableWidgetItem()
                    self.table_view.setHorizontalHeaderItem(a, item)
                    item = self.table_view.horizontalHeaderItem(a)
                    item.setText(i[0])
                    a = a + 1

                total = list(total)  # 將資料格式改為串列形式,其是將資料庫中取出的資料整體改為串列形式
                for i in range(len(total)):  # 將相關的資料
                    total[i] = list(total[i])  # 將獲取的資料轉為串列形式
                for i in range(self.row):
                    for j in range(self.vol):
                        self.table_data(i, j, total[i][j])
        except Exception as e:
            print(e)

    # 表格
    def set_table_view(self):
        self.cur.execute('show tables')
        db_len = self.cur.fetchone()
        self.cur.execute('select * from ' + db_len[0])  # 將資料從資料庫中拿出來
        self.select_run()

    # 樹
    def set_tree_view(self):
        # 樹行數
        self.tree_view.setColumnCount(1)
        # 樹標題
        self.tree_view.setHeaderLabel(gl_db + '.db')
        # 設定根節點
        root = QtWidgets.QTreeWidgetItem(self.tree_view)
        root.setText(0, '表')  # 只有一列
        root.setIcon(0, QIcon('img/db_logo.png'))
        # 創建游標
        cursor = self.conn.cursor()
        cursor.execute("show tables;")
        res = cursor.fetchall()
        # 遍歷表
        for i in range(len(res)):
            child = QtWidgets.QTreeWidgetItem(root)  # 指定父目錄
            child.setText(0, res[i][0])
            child.setText(1, '{}'.format(i + 1))
            child.setIcon(0, QIcon('img/table_logo.png'))
        # 樹默認收縮
        root.setExpanded(False)
        # 樹根節點
        self.tree_view.addTopLevelItem(root)

    # 文本框
    def set_text_edit(self):
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(14)
        self.text_edit.setFont(font)
        self.cur.execute('show tables;')
        db_len = self.cur.fetchone()
        self.text_edit.setPlaceholderText('SELECT * FROM {};\nGO;\n\n按F5運行代碼'.format(db_len[0]))

    # 文本瀏覽
    def set_text_browser(self):
        self.text_browser.setPlaceholderText('操作記錄:')

    # 清空按鈕
    def set_clear_button(self):
        pass

    # 清空按鈕左鍵
    def clear_all(self):
        self.text_edit.setText('')
        self.text_browser.append('清空代碼區')

    # 警告資訊
    @staticmethod
    def message_dialog(title, text):
        msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, text)
        msg_box.exec_()

    # 查詢影響行
    def row_ref(self):
        cur_count = self.cur.rowcount
        if cur_count > 0:
            self.conn.commit()
            self.text_browser.moveCursor(QTextCursor.End)
            self.text_browser.append('執行成功')
        else:
            self.text_browser.moveCursor(QTextCursor.End)
            self.text_browser.append('執行失敗,影響0條記錄')

    # 運行按鈕樣式
    def set_run_button(self):
        pass

    # 運行左鍵
    def run_program(self):
        try:
            # 獲取填寫的代碼
            text = self.text_edit.toPlainText()
            # 刪掉所有的換行
            text = text.replace('\n', '')
            # 所有代碼大寫
            text = text.upper()
            # 不同代碼分片
            texts = text.split(';')
            for i in range(len(texts)):
                try:
                    if texts[i][:6] == 'SELECT':
                        print('執行查詢{}'.format(texts[i]))
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.select_run()
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('查詢{}'.format(texts[i]))
                        self.row_ref()
                    elif texts[i][:6] == 'UPDATE':
                        print('執行更新{}'.format(texts[i]))
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('更新{}'.format(texts[i]))
                        self.row_ref()
                    elif texts[i][:6] == 'INSERT':
                        print('執行插入{}'.format(texts[i]))
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('插入{}'.format(texts[i]))
                        self.row_ref()
                    elif texts[i][:6] == 'DELETE':
                        print('執行洗掉{}'.format(texts[i]))
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('洗掉{}'.format(texts[i]))
                        self.row_ref()
                    elif texts[i][:6] == 'CREATE' and texts[i].find('TABLE') != -1:
                        print('創建資料表')
                        self.cur.execute(texts[i])  # 將資料從資料庫中拿出來
                        self.text_browser.moveCursor(QTextCursor.End)
                        self.text_browser.append('創建資料表{}'.format(texts[i]))
                        self.flash()
                except Exception as e:
                    if '1096' in str(e):
                        print('沒有使用資料庫')
                        self.message_dialog('沒有使用資料庫', str(e))
                    elif '1054' in str(e):
                        print('沒有這個資料庫')
                        self.message_dialog('沒有這個資料庫', str(e))
                    elif '1064' in str(e):
                        print('語法錯誤')
                        self.message_dialog('語法錯誤', str(e))
                    else:
                        print('rr', e)
                        self.message_dialog('其他錯誤', str(e))
            print('run', text)
        except Exception as e:
            print('e:', e)

    # 樹左鍵單擊
    def on_tree_clicked(self):
        """
        樹左鍵單擊
        :return:
        """
        try:
            item = self.tree_view.currentItem()
            if item.text(0) == '表':
                print('左鍵單擊{}'.format(item.text(0)))
                if self.tree_view.currentItem().isExpanded():
                    self.tree_view.collapseAll()
                else:
                    self.tree_view.expandAll()
            else:
                # 資料表操作
                item = self.tree_view.currentItem()
                self.cur.execute('select * from ' + item.text(0))
                self.select_run()
                print('左鍵單擊{}'.format(item.text(0)))
        except Exception as e:
            print('樹左鍵單擊{}'.format(e))
            self.message_dialog('提示', '請先輸入資料')

    # 樹右鍵單擊
    def right_menu_show(self):
        """
        樹右鍵單擊
        :return:
        """
        try:
            item = self.tree_view.currentItem()
            if item.text(0) == '表':
                print('右鍵單擊{}'.format(item.text(0)))
                self.contextMenu = QMenu()
                self.add_db = self.contextMenu.addAction(u'新建資料表')
                self.flash_db = self.contextMenu.addAction(u'重繪')
                self.close_db = self.contextMenu.addAction(u'退出')
                self.contextMenu.popup(QCursor.pos())
                self.add_db.triggered.connect(self.add_database)  # type:ignore
                self.flash_db.triggered.connect(self.flash)  # type:ignore
                self.close_db.triggered.connect(self.close_database)  # type:ignore
                self.contextMenu.show()

            # elif id(item.parent()) == tree_root_id:
            else:
                # TODO 資料表的右鍵
                print('右鍵單擊{},序號是{}'.format(item.text(0), item.text(1)))
                self.contextMenu = QMenu()
                self.open = self.contextMenu.addAction(u'打開表')
                self.drop = self.contextMenu.addAction(u'洗掉表')
                self.add = self.contextMenu.addAction(u'添加記錄')
                self.delete = self.contextMenu.addAction(u'洗掉記錄')
                self.update = self.contextMenu.addAction(u'更改記錄')
                self.select = self.contextMenu.addAction(u'查詢記錄')
                self.open.triggered.connect(self.open_table)  # type:ignore
                self.drop.triggered.connect(self.drop_table)  # type:ignore
                self.add.triggered.connect(self.add_table)  # type:ignore
                self.delete.triggered.connect(self.delete_table)  # type:ignore
                self.update.triggered.connect(self.update_table)  # type:ignore
                self.select.triggered.connect(self.select_table)  # type:ignore
                self.contextMenu.popup(QCursor.pos())
                self.contextMenu.show()

        except Exception as e:
            print(e)

    # TODO 文本右鍵
    def text_right_menu(self):
        pass

    # 樹重繪
    def flash(self):
        """
        添加資料表后的重繪操作
        :return:
        """
        print('重繪')
        item = self.tree_view.currentItem()
        root = QtWidgets.QTreeWidgetItem(self.tree_view)
        root.setText(0, '表')  # 只有一列
        root.setIcon(0, QIcon('img/db_logo.png'))
        cursor = self.conn.cursor()
        cursor.execute("show tables;")
        res = cursor.fetchall()

        # 清除樹
        curr_node = self.tree_view.currentItem()
        root_index = self.tree_view.indexOfTopLevelItem(curr_node)
        self.tree_view.takeTopLevelItem(root_index)

        for i in range(len(res)):
            child = QtWidgets.QTreeWidgetItem(root)  # 指定父目錄
            child.setText(0, res[i][0])
            child.setText(1, '{}'.format(i + 1))
            child.setIcon(0, QIcon('img/table_logo.png'))

    # 新建資料表
    def add_database(self):
        try:
            self.add_db_view = AdDB()
            add_ui = Ui_add_db_object()
            add_ui.setupUi(self.add_db_view)
            self.add_db_view.show()
        except Exception as e:
            print(e)

        print('新建資料表')

    # 退出資料表
    def close_database(self):
        reply = QMessageBox.question(self, '退出', '確定退出', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            sender = self.sender()
            main_app_db = QApplication.instance()
            main_app_db.quit()
        print('退出資料表')

    # 右鍵打開
    def open_table(self):
        item = self.tree_view.currentItem()
        self.cur.execute('select * from ' + item.text(0))
        self.select_run()
        print('打開 {}'.format(item.text(0)))

    # 右鍵洗掉表
    def drop_table(self):
        item = self.tree_view.currentItem()
        reply = QMessageBox.question(self, '洗掉表', '確定要洗掉嗎?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            self.cur.execute('drop table ' + item.text(0))
            self.text_browser.append('洗掉表 {} 成功,右擊根目錄重繪'.format(item.text(0)))
        print('洗掉 {}'.format(item.text(0)))

    # TODO 添加記錄
    def add_table(self):
        self.message_dialog('提示', '功能還沒開發')
        print('添加記錄')

    # TODO 洗掉記錄
    def delete_table(self):
        try:
            self.del_db_view = DelDB()
            del_ui = Ui_delete_win()
            del_ui.setupUi(self.del_db_view)
            self.del_db_view.show()
        except Exception as e:
            print(e)
        print('洗掉記錄')

    # TODO 更改記錄
    def update_table(self):
        self.message_dialog('提示', '功能還沒開發')
        print('更改記錄')

    # TODO 查詢記錄
    def select_table(self):
        self.message_dialog('提示', '功能還沒開發')
        print('查詢記錄')


class Ui_add_db_object(object):
    def __init__(self):
        super().__init__()
        self.conn = pymysql.connect(host=gl_host, port=gl_port, user=gl_user, password=gl_pwd, db=gl_db)
        self.cur = self.conn.cursor()

    def setupUi(self, add_db_object):
        add_db_object.setObjectName("add_db_object")
        add_db_object.setEnabled(True)
        add_db_object.resize(441, 511)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(add_db_object.sizePolicy().hasHeightForWidth())
        add_db_object.setSizePolicy(sizePolicy)
        add_db_object.setMaximumSize(QtCore.QSize(500, 600))
        add_db_object.setWindowTitle("Form")
        self.gridLayoutWidget = QtWidgets.QWidget(add_db_object)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 20, 421, 431))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.label_1_len = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_1_len.setObjectName("label_1_len")
        self.gridLayout.addWidget(self.label_1_len, 4, 1, 1, 1)
        self.label_2_checkBox = QtWidgets.QCheckBox(self.gridLayoutWidget)
        self.label_2_checkBox.setObjectName("label_2_checkBox")
        self.gridLayout.addWidget(self.label_2_checkBox, 10, 1, 1, 2)
        self.label_10 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_10.setObjectName("label_10")
        self.gridLayout.addWidget(self.label_10, 8, 1, 1, 1)
        self.label_1_attribute = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_1_attribute.setObjectName("label_1_attribute")
        self.gridLayout.addWidget(self.label_1_attribute, 3, 1, 1, 1)
        self.label_2 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_2.setObjectName("label_2")
        self.gridLayout.addWidget(self.label_2, 6, 1, 1, 2)
        self.label_3_comboBox = QtWidgets.QComboBox(self.gridLayoutWidget)
        self.label_3_comboBox.setObjectName("label_3_comboBox")
        self.gridLayout.addWidget(self.label_3_comboBox, 13, 2, 1, 1)
        self.label_2_comboBox = QtWidgets.QComboBox(self.gridLayoutWidget)
        self.label_2_comboBox.setObjectName("label_2_comboBox")
        self.gridLayout.addWidget(self.label_2_comboBox, 8, 2, 1, 1)
        self.label_2_spinBox = QtWidgets.QSpinBox(self.gridLayoutWidget)
        self.label_2_spinBox.setObjectName("label_2_spinBox")
        self.gridLayout.addWidget(self.label_2_spinBox, 9, 2, 1, 1)
        self.label_1_lineEdit = QtWidgets.QLineEdit(self.gridLayoutWidget)
        self.label_1_lineEdit.setObjectName("label_1_lineEdit")
        self.gridLayout.addWidget(self.label_1_lineEdit, 2, 2, 1, 1)
        self.label_2_len = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_2_len.setObjectName("label_2_len")
        self.gridLayout.addWidget(self.label_2_len, 9, 1, 1, 1)
        self.label_2_lineEdit = QtWidgets.QLineEdit(self.gridLayoutWidget)
        self.label_2_lineEdit.setObjectName("label_2_lineEdit")
        self.gridLayout.addWidget(self.label_2_lineEdit, 7, 2, 1, 1)
        self.label_3_spinBox = QtWidgets.QSpinBox(self.gridLayoutWidget)
        self.label_3_spinBox.setObjectName("label_3_spinBox")
        self.gridLayout.addWidget(self.label_3_spinBox, 14, 2, 1, 1)
        self.label_3_name = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_3_name.setObjectName("label_3_name")
        self.gridLayout.addWidget(self.label_3_name, 12, 1, 1, 1)
        self.label_3_checkBox = QtWidgets.QCheckBox(self.gridLayoutWidget)
        self.label_3_checkBox.setObjectName("label_3_checkBox")
        self.gridLayout.addWidget(self.label_3_checkBox, 15, 1, 1, 2)
        self.label_3_lineEdit = QtWidgets.QLineEdit(self.gridLayoutWidget)
        self.label_3_lineEdit.setObjectName("label_3_lineEdit")
        self.gridLayout.addWidget(self.label_3_lineEdit, 12, 2, 1, 1)
        self.label_6 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_6.setObjectName("label_6")
        self.gridLayout.addWidget(self.label_6, 13, 1, 1, 1)
        self.label_3_len = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_3_len.setObjectName("label_3_len")
        self.gridLayout.addWidget(self.label_3_len, 14, 1, 1, 1)
        self.label_1 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_1.setObjectName("label_1")
        self.gridLayout.addWidget(self.label_1, 1, 1, 1, 2)
        self.label_3 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_3.setObjectName("label_3")
        self.gridLayout.addWidget(self.label_3, 11, 1, 1, 2)
        self.label_1_spinBox = QtWidgets.QSpinBox(self.gridLayoutWidget)
        self.label_1_spinBox.setObjectName("label_1_spinBox")
        self.gridLayout.addWidget(self.label_1_spinBox, 4, 2, 1, 1)
        self.label_1_comboBox = QtWidgets.QComboBox(self.gridLayoutWidget)
        self.label_1_comboBox.setMaximumSize(QtCore.QSize(16777211, 16777215))
        self.label_1_comboBox.setObjectName("label_1_comboBox")
        self.gridLayout.addWidget(self.label_1_comboBox, 3, 2, 1, 1)
        self.label_1_name = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_1_name.setObjectName("label_1_name")
        self.gridLayout.addWidget(self.label_1_name, 2, 1, 1, 1)
        self.label_1_checkBox = QtWidgets.QCheckBox(self.gridLayoutWidget)
        self.label_1_checkBox.setObjectName("label_1_checkBox")
        self.gridLayout.addWidget(self.label_1_checkBox, 5, 1, 1, 2)
        self.label_2_name = QtWidgets.QLabel(self.gridLayoutWidget)
        self.label_2_name.setObjectName("label_2_name")
        self.gridLayout.addWidget(self.label_2_name, 7, 1, 1, 1)
        self.table_name_label = QtWidgets.QLabel(self.gridLayoutWidget)
        self.table_name_label.setObjectName("table_name_label")
        self.gridLayout.addWidget(self.table_name_label, 0, 1, 1, 1)
        self.table_name_lineEdit = QtWidgets.QLineEdit(self.gridLayoutWidget)
        self.table_name_lineEdit.setObjectName("table_name_lineEdit")
        self.gridLayout.addWidget(self.table_name_lineEdit, 0, 2, 1, 1)
        self.add_yes_pushButton = QtWidgets.QPushButton(add_db_object)
        self.add_yes_pushButton.setGeometry(QtCore.QRect(90, 460, 91, 31))
        self.add_yes_pushButton.setObjectName("add_yes_pushButton")
        self.add_no_pushButton_2 = QtWidgets.QPushButton(add_db_object)
        self.add_no_pushButton_2.setGeometry(QtCore.QRect(230, 460, 91, 31))
        self.add_no_pushButton_2.setObjectName("add_no_pushButton_2")

        add_db_object.setTabOrder(self.table_name_lineEdit, self.label_1_lineEdit)
        add_db_object.setTabOrder(self.label_1_lineEdit, self.label_1_comboBox)
        add_db_object.setTabOrder(self.label_1_comboBox, self.label_1_spinBox)
        add_db_object.setTabOrder(self.label_1_spinBox, self.label_1_checkBox)
        add_db_object.setTabOrder(self.label_1_checkBox, self.label_2_lineEdit)
        add_db_object.setTabOrder(self.label_2_lineEdit, self.label_2_comboBox)
        add_db_object.setTabOrder(self.label_2_comboBox, self.label_2_spinBox)
        add_db_object.setTabOrder(self.label_2_spinBox, self.label_2_checkBox)
        add_db_object.setTabOrder(self.label_2_checkBox, self.label_3_lineEdit)
        add_db_object.setTabOrder(self.label_3_lineEdit, self.label_3_comboBox)
        add_db_object.setTabOrder(self.label_3_comboBox, self.label_3_spinBox)
        add_db_object.setTabOrder(self.label_3_spinBox, self.label_3_checkBox)
        add_db_object.setTabOrder(self.label_3_checkBox, self.add_yes_pushButton)
        add_db_object.setTabOrder(self.add_yes_pushButton, self.add_no_pushButton_2)


        if self.label_1_comboBox.currentText() == 'char' or 'text' or 'varchar':
            self.label_1_spinBox.setMaximum(255)
        else:
            self.label_1_spinBox.setMaximum(2 ** 20)
        if self.label_2_comboBox.currentText() == 'char' or 'text' or 'varchar':
            self.label_2_spinBox.setMaximum(255)
        else:
            self.label_2_spinBox.setMaximum(2 ** 20)
        if self.label_3_comboBox.currentText() == 'char' or 'text' or 'varchar':
            self.label_3_spinBox.setMaximum(255)
        else:
            self.label_3_spinBox.setMaximum(2 ** 20)

        self.retranslateUi(add_db_object)
        self.add_no_pushButton_2.clicked.connect(add_db_object.close)  # type: ignore
        self.add_yes_pushButton.clicked.connect(lambda: self.add_true(add_db_object))  # type: ignore
        QtCore.QMetaObject.connectSlotsByName(add_db_object)

        item_attribute = ['', 'char', 'int', 'float', 'text', 'varchar']
        self.label_1_comboBox.addItems(item_attribute)
        self.label_2_comboBox.addItems(item_attribute)
        self.label_3_comboBox.addItems(item_attribute)

    # 警告資訊
    @staticmethod
    def message_dialog(title, text):
        msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, text)
        msg_box.exec_()

    def add_true(self, add_db_object):
        try:
            label_1 = [self.label_1_lineEdit.text(), self.label_1_comboBox.currentText(), self.label_1_spinBox.text(),
                       self.label_1_checkBox.isChecked()]
            label_2 = [self.label_2_lineEdit.text(), self.label_2_comboBox.currentText(), self.label_2_spinBox.text(),
                       self.label_2_checkBox.isChecked()]
            label_3 = [self.label_3_lineEdit.text(), self.label_3_comboBox.currentText(), self.label_3_spinBox.text(),
                       self.label_3_checkBox.isChecked()]
            print(label_1, label_2, label_3)
            add_count = 0
            add_item = []

            word = r'^\w+$'
            if len(self.table_name_lineEdit.text()) == 0:
                print(self.table_name_lineEdit.text())
                match_tana = re.match(word, self.label_1_lineEdit.text())
                self.message_dialog('警告', '資料表名必填')
                return
                if match_tana is None:
                    self.message_dialog('警告', '資料表名只能是英文、數字、下劃線')
                    return

            if self.label_1_checkBox.isChecked() and self.label_2_checkBox.isChecked() \
                    or self.label_1_checkBox.isChecked() and self.label_3_checkBox.isChecked() \
                    or self.label_2_checkBox.isChecked() and self.label_3_checkBox.isChecked():
                print('主鍵只能有一個')
                self.message_dialog('警告', '主鍵只能有一個')
                return

            else:
                if "" not in label_1:
                    print(label_1)
                    # if len(self.label_1_lineEdit.text()) > 0:
                    match_1 = re.match(word, self.label_1_lineEdit.text())
                    if match_1 is None:
                        self.message_dialog('警告', '欄位名只能是英文、數字、下劃線')
                        return

                    for i in range(len(label_1) - 1):
                        add_item.append(label_1[i])
                    if self.label_1_checkBox.isChecked():
                        add_item.append('primary key')
                    else:
                        add_item.append(' ')
                    add_count += 1

                if "" not in label_2:
                    print(label_2)
                    match_2 = re.match(word, self.label_2_lineEdit.text())
                    if match_2 is None:
                        self.message_dialog('警告', '欄位名只能是英文、數字、下劃線')
                        return
                    for i in range(len(label_2) - 1):
                        add_item.append(label_2[i])
                    if self.label_2_checkBox.isChecked():
                        add_item.append('primary key')
                    else:
                        add_item.append(' ')
                    add_count += 1

                if "" not in label_3:
                    print(label_3)
                    match_3 = re.match(word, self.label_3_lineEdit.text())
                    if match_3 is None:
                        self.message_dialog('警告', '欄位名只能是英文、數字、下劃線')
                        return
                    for i in range(len(label_3) - 1):
                        add_item.append(label_3[i])
                    if self.label_3_checkBox.isChecked():
                        add_item.append('primary key')
                    else:
                        add_item.append(' ')
                    add_count += 1

            if add_count == 0:
                self.message_dialog('警告', '必填欄位名、欄位型別、欄位長度')
                return

            if len(add_item) == 4:
                self.cur.execute(
                    'create table ' + self.table_name_lineEdit.text() + '(' + add_item[0] + ' ' + add_item[1] + '(' +
                    add_item[2] + ') ' + add_item[3] + ');')
                self.conn.commit()
                self.message_dialog('提示', '添加完成,重繪資料表')
                self.cur.close()
                add_db_object.close()
            elif len(add_item) == 8:
                self.cur.execute(
                    'create table ' + self.table_name_lineEdit.text() + '(' + add_item[0] + ' ' + add_item[1] + '(' +
                    add_item[2] + ') ' + add_item[3] + ', ' + add_item[4] + ' ' + add_item[5] + '(' + add_item[
                        6] + ') ' +
                    add_item[7] + ');')
                self.conn.commit()
                self.cur.close()
                self.message_dialog('提示', '添加完成,重繪資料表')
                add_db_object.close()
            elif len(add_item) == 12:
                self.cur.execute(
                    'create table ' + self.table_name_lineEdit.text() + '(' + add_item[0] + ' ' + add_item[1] + '(' +
                    add_item[2] + ') ' + add_item[3] + ', ' + add_item[4] + ' ' + add_item[5] + '(' + add_item[
                        6] + ') ' +
                    add_item[7] + ' , ' + add_item[8] + ' ' + add_item[9] + '(' + add_item[10] + ') ' + add_item[
                        11] + ');')
                self.conn.commit()
                self.message_dialog('提示', '添加完成,重繪資料表')
                self.cur.close()
                add_db_object.close()
        except Exception as e:
            self.message_dialog('錯誤', e)

    def retranslateUi(self, add_db_object):
        _translate = QtCore.QCoreApplication.translate
        self.label_1_len.setText(_translate("add_db_object", "欄位長度"))
        self.label_2_checkBox.setText(_translate("add_db_object", "設為主鍵"))
        self.label_10.setText(_translate("add_db_object", "欄位屬性"))
        self.label_1_attribute.setText(_translate("add_db_object", "欄位屬性"))
        self.label_2.setText(_translate("add_db_object", "欄位2"))
        self.label_2_len.setText(_translate("add_db_object", "欄位長度"))
        self.label_3_name.setText(_translate("add_db_object", "欄位名"))
        self.label_3_checkBox.setText(_translate("add_db_object", "設為主鍵"))
        self.label_6.setText(_translate("add_db_object", "欄位屬性"))
        self.label_3_len.setText(_translate("add_db_object", "欄位長度"))
        self.label_1.setText(_translate("add_db_object", "欄位1"))
        self.label_3.setText(_translate("add_db_object", "欄位3"))
        self.label_1_name.setText(_translate("add_db_object", "欄位名"))
        self.label_1_checkBox.setText(_translate("add_db_object", "設為主鍵"))
        self.label_2_name.setText(_translate("add_db_object", "欄位名"))
        self.table_name_label.setText(_translate("add_db_object", "資料表名"))
        self.add_yes_pushButton.setText(_translate("add_db_object", "確定"))
        self.add_no_pushButton_2.setText(_translate("add_db_object", "取消"))


class AdDB(QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(441, 511)  # 禁止拖動
        self.setWindowIcon(QtGui.QIcon('./img/001.ico'))  # 設定表單標題圖示
        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)  # 禁用最大化


class Ui_delete_win(object):
    def __init__(self):
        super().__init__()
        self.conn = pymysql.connect(host=gl_host, port=gl_port, user=gl_user, password=gl_pwd, db=gl_db)
        self.cur = self.conn.cursor()

    def setupUi(self, delete_win):
        delete_win.setObjectName("delete_win")
        delete_win.resize(400, 260)
        self.delete_yes = QtWidgets.QPushButton(delete_win)
        self.delete_yes.setGeometry(QtCore.QRect(80, 200, 81, 31))
        self.delete_yes.setObjectName("delete_yes")
        self.delete_no = QtWidgets.QPushButton(delete_win)
        self.delete_no.setGeometry(QtCore.QRect(220, 200, 81, 31))
        self.delete_no.setObjectName("delete_no")
        self.delete_header = QtWidgets.QTextBrowser(delete_win)
        self.delete_header.setGeometry(QtCore.QRect(120, 20, 171, 31))
        self.delete_header.setObjectName("delete_header")
        self.widget = QtWidgets.QWidget(delete_win)
        self.widget.setGeometry(QtCore.QRect(40, 70, 331, 111))
        self.widget.setObjectName("widget")
        self.gridLayout = QtWidgets.QGridLayout(self.widget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.delete_where_vue3 = QtWidgets.QLineEdit(self.widget)
        self.delete_where_vue3.setObjectName("delete_where_vue3")
        self.gridLayout.addWidget(self.delete_where_vue3, 2, 2, 1, 1)
        self.delete_where_vue2 = QtWidgets.QLineEdit(self.widget)
        self.delete_where_vue2.setObjectName("delete_where_vue2")
        self.gridLayout.addWidget(self.delete_where_vue2, 1, 2, 1, 1)
        self.delete_where_item3 = QtWidgets.QComboBox(self.widget)
        self.delete_where_item3.setObjectName("delete_where_item3")
        self.gridLayout.addWidget(self.delete_where_item3, 2, 1, 1, 1)
        self.delete_where = QtWidgets.QLabel(self.widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(3)
        sizePolicy.setHeightForWidth(self.delete_where.sizePolicy().hasHeightForWidth())
        self.delete_where.setSizePolicy(sizePolicy)
        self.delete_where.setObjectName("delete_where")
        self.gridLayout.addWidget(self.delete_where, 0, 0, 1, 1)
        self.delete_where_vue1 = QtWidgets.QLineEdit(self.widget)
        self.delete_where_vue1.setObjectName("delete_where_vue1")
        self.gridLayout.addWidget(self.delete_where_vue1, 0, 2, 1, 1)
        self.delete_where_item2 = QtWidgets.QComboBox(self.widget)
        self.delete_where_item2.setObjectName("delete_where_item2")
        self.gridLayout.addWidget(self.delete_where_item2, 1, 1, 1, 1)
        self.delete_where_item1 = QtWidgets.QComboBox(self.widget)
        self.delete_where_item1.setObjectName("delete_where_item1")
        self.gridLayout.addWidget(self.delete_where_item1, 0, 1, 1, 1)
        self.delete_and = QtWidgets.QLabel(self.widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(3)
        sizePolicy.setHeightForWidth(self.delete_and.sizePolicy().hasHeightForWidth())
        self.delete_and.setSizePolicy(sizePolicy)
        self.delete_and.setObjectName("delete_and")
        self.gridLayout.addWidget(self.delete_and, 1, 0, 1, 1)
        self.delete_and_2 = QtWidgets.QLabel(self.widget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(3)
        sizePolicy.setHeightForWidth(self.delete_and_2.sizePolicy().hasHeightForWidth())
        self.delete_and_2.setSizePolicy(sizePolicy)
        self.delete_and_2.setObjectName("delete_and_2")
        self.gridLayout.addWidget(self.delete_and_2, 2, 0, 1, 1)

        self.retranslateUi(delete_win)
        self.delete_no.clicked.connect(delete_win.close)  # type: ignore
        QtCore.QMetaObject.connectSlotsByName(delete_win)

        self.delete_yes.clicked.connect(lambda: self.delete_fun())  # type: ignore

        delete_win.setTabOrder(self.delete_header, self.delete_where_item1)
        delete_win.setTabOrder(self.delete_where_item1, self.delete_where_vue1)
        delete_win.setTabOrder(self.delete_where_vue1, self.delete_where_item2)
        delete_win.setTabOrder(self.delete_where_item2, self.delete_where_vue2)
        delete_win.setTabOrder(self.delete_where_vue2, self.delete_where_item3)
        delete_win.setTabOrder(self.delete_where_item3, self.delete_where_vue3)
        delete_win.setTabOrder(self.delete_where_vue3, self.delete_yes)
        delete_win.setTabOrder(self.delete_yes, self.delete_no)

    # TODO 洗掉記錄
    def delete_fun(self):
        print('555')

    def retranslateUi(self, delete_win):
        _translate = QtCore.QCoreApplication.translate
        delete_win.setWindowTitle(_translate("delete_win", "洗掉記錄"))
        self.delete_yes.setText(_translate("delete_win", "確定"))
        self.delete_no.setText(_translate("delete_win", "取消"))
        self.delete_where.setText(_translate("delete_win", "where"))
        self.delete_and.setText(_translate("delete_win", "and"))
        self.delete_and_2.setText(_translate("delete_win", "and"))


class DelDB(QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(400, 260)  # 禁止拖動
        self.setWindowIcon(QtGui.QIcon('./img/001.ico'))  # 設定表單標題圖示
        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)  # 禁用最大化


class Ui_widget(object):
    def __init__(self):
        super().__init__()
        self.main_show = None

    def setupUi(self, widget):
        widget.setObjectName("widget")
        widget.setEnabled(True)
        widget.resize(600, 400)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(widget.sizePolicy().hasHeightForWidth())
        widget.setSizePolicy(sizePolicy)
        self.formLayoutWidget_2 = QtWidgets.QWidget(widget)
        self.formLayoutWidget_2.setGeometry(QtCore.QRect(160, 100, 281, 201))
        self.formLayoutWidget_2.setObjectName("formLayoutWidget_2")
        self.formLayout_2 = QtWidgets.QFormLayout(self.formLayoutWidget_2)
        self.formLayout_2.setContentsMargins(0, 0, 0, 0)
        self.formLayout_2.setObjectName("formLayout_2")
        self.label = QtWidgets.QLabel(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label)
        self.lineEdit = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.lineEdit.setFont(font)
        self.lineEdit.setObjectName("lineEdit")
        self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lineEdit)
        self.label_2 = QtWidgets.QLabel(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_2)
        self.lineEdit_2 = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.lineEdit_2.setFont(font)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineEdit_2)
        self.label_4 = QtWidgets.QLabel(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_4)
        self.label_5 = QtWidgets.QLabel(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5)
        self.label_6 = QtWidgets.QLabel(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_6)
        self.lineEdit_3 = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.lineEdit_3.setFont(font)
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.lineEdit_3)
        self.lineEdit_4 = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.lineEdit_4.setFont(font)
        self.lineEdit_4.setObjectName("lineEdit_4")
        self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.lineEdit_4)
        self.lineEdit_5 = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("楷體")
        font.setPointSize(18)
        self.lineEdit_5.setFont(font)
        self.lineEdit_5.setObjectName("lineEdit_5")
        self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.lineEdit_5)
        self.pushButton = QtWidgets.QPushButton(widget)
        self.pushButton.setGeometry(QtCore.QRect(170, 320, 120, 40))
        font = QtGui.QFont()
        font.setFamily("黑體")
        font.setPointSize(12)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(widget)
        self.pushButton_2.setGeometry(QtCore.QRect(310, 320, 120, 40))
        font = QtGui.QFont()
        font.setFamily("黑體")
        font.setPointSize(12)
        self.pushButton_2.setFont(font)
        self.pushButton_2.setObjectName("pushButton_2")
        self.label_3 = QtWidgets.QLabel(widget)
        self.label_3.setGeometry(QtCore.QRect(230, 40, 151, 31))
        font = QtGui.QFont()
        font.setFamily("黑體")
        font.setPointSize(20)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")

        # 退出事件
        self.retranslateUi(widget)
        self.pushButton_2.clicked.connect(widget.close)  # type: ignore
        QtCore.QMetaObject.connectSlotsByName(widget)

        # 登錄事件
        self.pushButton.clicked.connect(self.login_in)  # type: ignore
        self.pushButton.setShortcut('Return')

    # 驗證登錄
    def login_in(self):
        global gl_db
        global gl_host
        global gl_pwd
        global gl_user
        global gl_port

        gl_db = self.lineEdit_5.text()
        gl_host = self.lineEdit_3.text()
        gl_pwd = self.lineEdit_2.text()
        gl_user = self.lineEdit.text()
        try:
            port = int(self.lineEdit_4.text())
            try:
                conn = pymysql.connect(host=gl_host, port=gl_port, db=gl_db, user=gl_user, password=gl_pwd)
                print('登錄資料庫{}成功'.format(gl_db))
                self.messageDialog('提示', '登錄資料庫{}成功'.format(gl_db))
                conn.close()
                del conn
                self.main_show = Fulling()
                self.main_show.show()
                mainWindow.close()
            except pymysql.err.OperationalError:
                print('由于目標計算機積極拒絕,無法連接,')
                self.messageDialog('警告', '由于目標計算機積極拒絕,無法連接,')
        except ValueError:
            print('埠號錯誤')
            self.messageDialog('警告', '埠號錯誤')
        except Exception as err:
            print('錯誤:', err)
            self.messageDialog('警告', str(err))

        # print(db, port, host, pwd, user)
        # print(type(db), type(port), type(host), type(pwd), type(user))

    def messageDialog(self, title, text):
        # 提示資訊
        msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, text)
        msg_box.exec_()

    def retranslateUi(self, widget):
        _translate = QtCore.QCoreApplication.translate
        widget.setWindowTitle(_translate("widget", "登錄 MySQL"))
        self.label.setText(_translate("widget", "賬  號:"))
        self.label_2.setText(_translate("widget", "密  碼:"))
        self.label_4.setText(_translate("widget", "主  機:"))
        self.label_5.setText(_translate("widget", "埠號:"))
        self.label_6.setText(_translate("widget", "資料庫:"))
        self.pushButton.setText(_translate("widget", "登錄"))
        self.pushButton_2.setText(_translate("widget", "退出"))
        self.label_3.setText(_translate("widget", "登錄 MySQL"))


class Login(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(600, 400)  # 禁止拖動
        self.setWindowIcon(QtGui.QIcon('./img/001.ico'))  # 設定表單標題圖示
        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)  # 禁用最大化

        # 背景圖片
        image = QtGui.QPixmap()
        image.load(r'./img/login_bg.jpg')
        bg = QtGui.QPalette()
        bg.setBrush(self.backgroundRole(), QtGui.QBrush(image))
        self.setPalette(bg)
        self.setAutoFillBackground(True)


if __name__ == '__main__':
    gl_db = ''
    gl_host = ''
    gl_pwd = ''
    gl_user = ''
    gl_port = 0
    # 創建 QApplication 類的實體
    logapp = QApplication(sys.argv)
    # 創建表單
    mainWindow = Login()
    # 關聯login
    ui = Ui_widget()
    ui.setupUi(mainWindow)
    # 打開表單
    mainWindow.show()
    # 退出表單
    sys.exit(logapp.exec_())

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/401649.html

標籤:python

上一篇:第二屆BMZCTF公開賽-easymisc

下一篇:顫振中的可重用類

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more