├── .gitignore ├── LICENSE ├── README.md ├── app.py ├── config ├── config.py └── skin │ └── white.qss ├── core ├── CpuLineChart.py ├── DynamicSpline.py ├── FileIconProvider.py ├── ImageView.py ├── MetroCircleProgress.py └── MySystemTrayIcon.py ├── doc ├── README_zh.md └── img │ ├── 0.png │ ├── 1.5.png │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ └── 6.png ├── file_verison_info.txt ├── models ├── db.sql └── user.py ├── pyqt5_example.spec ├── pyqt5_example_exe.spec ├── requirements.txt ├── res ├── app.qrc ├── app_rc.py ├── icon │ ├── close.svg │ ├── minimize.svg │ ├── plus.svg │ ├── png_to_ico.py │ └── 首页.ico ├── image │ ├── American_Robin.jpg │ ├── fish.png │ └── register.jpg └── otf │ └── Social Media Circled.otf ├── start-qt-designer.bat ├── ui ├── close_dialog.py ├── close_dialog.ui ├── login_form.py ├── login_form.ui ├── main_window.py ├── main_window.ui ├── mysql_form.py ├── mysql_form.ui ├── register_form.py └── register_form.ui ├── ui_to_py.bat ├── utils ├── CommonHelper.py ├── connect_mysql.py ├── global_var.py └── logs.py └── win ├── close_dialog.py ├── login_form.py ├── main_win.py ├── mysql_form.py ├── register_form.py └── splash ├── core.py └── splash.py /.gitignore: -------------------------------------------------------------------------------- 1 | /other/ 2 | /.idea/ 3 | /dist/ 4 | /build/ 5 | /__pycache__/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## pyqt5_example 2 | 3 | - ✨ This is an pyqt5 example 🔥 4 | - 💻 It can be directly used for rapid development, database connection, login and registration 5 | 6 | 🎯Including the software startup screen, which can be used to load the library in advance 7 |
8 | 🎯Including login interface 9 |
10 |
11 | 🎯Including the registration interface 12 |
13 | 🎯Including database management interface 14 |
15 | 🎯Including the main window, real-time display of CPU utilization 16 |
17 | 18 | 🎯Includes the taskbar minimize icon 19 |
20 |
21 | 22 | ## Project file structure 23 | 24 | ```sh 25 | pyqt5_example/ # → Root 26 | ├─ doc (document related) 27 | ├─ config (program initialization configuration related) 28 | │ │ skin (folder for storing skin) 29 | │ └─ config.py (configuration file) 30 | ├─ core (custom control) 31 | │ │ CpuLineChart.py (line chart showing CPU utilization, which can be improved by yourself) 32 | │ │ DynamicSpline.py (dynamic line chart, which can be improved by yourself) 33 | │ │ FileIconProvider.py (file icon, you can continue to improve yourself) 34 | │ │ ImageView.py (picture viewing control, supports zooming pictures, and can continue to improve by yourself) 35 | │ │ MetroCircleProgress.py (dynamic progress bar, stateless continuous cycle) 36 | │ └─ MySystemTrayIcon.py (custom system tray icon class) 37 | ├─ res (resource folder used by the program) 38 | │ │ app.qrc (qt-designer 💻 Edited resource collection file) 39 | │ └─ app_rc.py (pyrcc5 converted resource file, 🚫 (do not modify)) 40 | ├─ ui (UI folder of the program) 41 | │ │ login_form.ui (login interface) 42 | │ │ register_form.ui (registration interface) 43 | │ │ mysql_form.ui (database management interface) 44 | │ │ close_dialog.ui ((close prompt interface) 45 | │ └─ main_window.ui (main window file) 46 | ├─ models (database related folder) 47 | │ │ db.sql (generate database file) 48 | │ └─ user.py (user table transaction logic) 49 | ├─ utils (folder of tool classes) 50 | │ │ CommonHelper.py (public help class) 51 | │ │ global_var.py (global variable class) 52 | │ │ connect_mysql.py (connect to database) 53 | │ └─ logs.py (Global log display processing) 54 | ├─ win (window logical folder) 55 | │ │ splash (software startup screen, used to load the deep learning library in advance) 56 | │ │ close_dialog.py (close the processing logic of the button prompt box) 57 | │ │ main_win.py (logical processing of main window) 58 | │ │ login_form.py (logical processing of login interface) 59 | │ │ register_form.py (logical processing of registration interface) 60 | │ └─ mysql_form.py (logical processing of database management interface) 61 | ├─ app.py (program entry file) 62 | ├─ .gitignore (git uploads ignored files) 63 | ├─ file_verison_info.txt (software version information) 64 | ├─ LICENSE (open source agreement supported by the project) 65 | ├─ pyqt5_example.spec (file packaged by pyinstaller) 66 | ├─ pyqt5_example_exe.spec (file packaged by pyinstaller) 67 | ├─ requirements.txt (project dependent Library) 68 | ├─ ui_to_py.bat 69 | │ ├─ !Pay attention to coda environment modification 70 | │ ├─ Start 💻 Automatically convert UI files using pyuic and pyrcc5 71 | ├─ start-qt-designer.bat 72 | │ ├─ !Pay attention to modifying the coda environment path 73 | │ ├─ Start 💻 QT designer tool 74 | └─ README.md (project description document) 75 | ``` 76 | 77 | ## Environmental installation 78 | 79 | ```bash 80 | # CONDA creates Python virtual environment 81 | conda create -n learn_pyqt5 python=3.8 82 | # Activate environment 83 | conda activate learn_pyqt5 84 | 85 | # Installation Library 86 | pip install -r requirements.txt 87 | 88 | # Modify the MySQL server configuration information in `/config/config.py` in file 89 | 90 | # Add a database to the database and run `/model/db.sql` file 91 | 92 | # Pack 93 | # It is packaged into many files. It is recommended to use it when it is very dependent 94 | pyinstaller pyqt5_example.spec 95 | 96 | # Package into a separate exe. It is recommended to use small files 97 | # One drawback is that it will first read into memory and decompress the dependency to the cache directory. 98 | # If the application is large, it is recommended to package it into a folder 99 | pyinstaller pyqt5_example_exe.spec 100 | ``` -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | from PyQt5.QtWidgets import QApplication 4 | from loguru import logger 5 | 6 | from utils import global_var as gl, logs 7 | from utils.connect_mysql import db 8 | from win.login_form import login_form 9 | from win.splash.splash import SplashScreen 10 | 11 | os.chdir(os.path.dirname(__file__)) 12 | sys.path.append(os.path.dirname(os.path.abspath(__file__))) 13 | 14 | 15 | class App(QApplication): 16 | def __init__(self): 17 | super().__init__(sys.argv) 18 | self.windows = {} 19 | 20 | def run(self, pytest=False): 21 | logger.info("程序启动 ...") 22 | 23 | splash = SplashScreen() # 启动界面 24 | splash.loadProgress() # 启动界面 25 | 26 | from win.main_win import main_win 27 | self.windows["main"] = main_win() 28 | self.windows["login"] = login_form(self.windows["main"]) 29 | self.windows["login"].show() 30 | 31 | splash.finish(self.windows["main"]) # 启动界面 32 | 33 | if not pytest: 34 | sys.exit(self.exec_()) 35 | 36 | 37 | if __name__ == "__main__": 38 | logs.setting() # log 设置 39 | gl.__init() # 全局变量 40 | db.connect() 41 | App().run() 42 | -------------------------------------------------------------------------------- /config/config.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseSettings 2 | 3 | 4 | class Settings(BaseSettings): 5 | DEBUG: bool = True 6 | 7 | TITLE: str = "pyqt5_example" 8 | 9 | # Mysql 10 | MYSQL_USERNAME: str = "root" 11 | MYSQL_PASSWORD: str = "password" 12 | MYSQL_HOST: str = "127.0.0.1" 13 | MYSQL_PORT: int = 3306 14 | MYSQL_DATABASE: str = 'pyqt5_example_db' 15 | 16 | 17 | settings = Settings() 18 | -------------------------------------------------------------------------------- /config/skin/white.qss: -------------------------------------------------------------------------------- 1 | /* ================================================ * 2 | author:wp19991 3 | lastedited:2022.3 4 | * ================================================ */ 5 | /*hover*/ 6 | /*actived*/ 7 | /*gradient start*/ 8 | /*gradient end*/ 9 | 10 | QWidget#centralwidget{ 11 | border-image: url(:/img/fish.png); 12 | } 13 | 14 | QWidget#widget{ 15 | background-color:rgba(0,0,0,0); 16 | } 17 | 18 | QTextBrowser#textBrowser{ 19 | background-color:rgba(0,0,0,0); 20 | } 21 | 22 | QMenu { 23 | color:black; 24 | background-color:white; 25 | border-radius:12px; 26 | padding:5px; 27 | margin:6px; 28 | } 29 | QMenu::item { 30 | font-size: 8pt; 31 | border: 2px solid #909090; /*item选框*/ 32 | border-radius:12px; 33 | padding:5px 10px; /*设置菜单项文字上下和左右的内边距,效果就是菜单中的条目左右上下有了间隔*/ 34 | margin:2px 2px; /*设置菜单项的外边距*/ 35 | } 36 | QMenu::item:selected{ 37 | color:#1aa3ff; 38 | background-color: #e5f5ff; 39 | border-radius:12px; 40 | } 41 | QMenu::separator{ 42 | height:1px; 43 | background:#bbbbbb; 44 | margin:5px; 45 | margin-left:10px; 46 | margin-right:10px; 47 | } 48 | 49 | QFrame{ 50 | color: #222; 51 | background-color: #FDFDFD;/*不能设置为transparent*/ 52 | } 53 | QMainWindow::separator{ 54 | border: 1px solid #999999; 55 | border-style: outset; 56 | width: 4px; 57 | height: 4px; 58 | } 59 | QMainWindow::separator:hover{ 60 | background: #8BF; 61 | } 62 | QSplitter::handle{ 63 | border: 1px solid #999999; 64 | border-style: outset; 65 | width: 4px; 66 | height: 4px; 67 | } 68 | QSplitter::handle:hover{/*splitter->handle(1)->setAttribute(Qt::WA_Hover, true);才生效*/ 69 | border-color: #EA2; 70 | } 71 | QSplitter::handle:pressed{ 72 | border-color: #59F; 73 | } 74 | QSizeGrip{ 75 | background-color: none; 76 | } 77 | 78 | /* =============================================== */ 79 | /* Label */ 80 | /* =============================================== */ 81 | QLabel { 82 | background: transparent; 83 | border: 1px solid transparent; 84 | padding: 1px; 85 | } 86 | 87 | 88 | /* A QLabel is a QFrame ... */ 89 | /* A QToolTip is a QLabel ... */ 90 | QToolTip { 91 | border: 1px solid #999999; 92 | padding: 5px; 93 | border-radius: 3px; 94 | opacity:210; 95 | } 96 | 97 | /* =============================================== */ 98 | /* TextBox */ 99 | /* =============================================== */ 100 | QLineEdit { 101 | background: #FDFDFD;/*不建议设为透明,否则table编辑时会字显示*/ 102 | selection-background-color: #8BF; 103 | border: 1px solid #999999; 104 | border-radius: 2px; 105 | border-style: inset; 106 | padding: 0 1px; 107 | } 108 | 109 | QLineEdit:hover{ 110 | border-color: #8BF; 111 | } 112 | QLineEdit:focus{ 113 | border-color: #EA2; 114 | } 115 | /*QLineEdit[readOnly="true"] { color: gray }*/ 116 | QLineEdit[echoMode="2"]{ 117 | lineedit-password-character: 9679;/*字符的ascii码35 88等 */ 118 | } 119 | 120 | QLineEdit:read-only { 121 | color: #aba7a6; 122 | } 123 | 124 | QLineEdit:disabled{ 125 | color: lightgray; 126 | background: lightgray; 127 | } 128 | 129 | QTextEdit{ 130 | selection-background-color:#8BF; 131 | border: 1px solid #999999; 132 | border-style: inset; 133 | } 134 | QTextEdit:hover{ 135 | border-radius: 5px; 136 | border-color: #8BF; 137 | } 138 | QTextEdit:focus{ 139 | border-color: #EA2; 140 | } 141 | /* =============================================== */ 142 | /* Button */ 143 | /* =============================================== */ 144 | QPushButton { 145 | border: 1px solid #999999; 146 | border-radius: 5px; 147 | padding: 1px 4px; 148 | min-width: 50px; 149 | min-height: 16px; 150 | } 151 | 152 | QPushButton:hover{ 153 | background-color: #8BF; 154 | border-color: #59F; 155 | } 156 | 157 | QPushButton:pressed 158 | { 159 | border-width: 1px; 160 | background-color: #59F; 161 | border-color: #999999; 162 | } 163 | 164 | QPushButton:focus, QPushButton:default { 165 | border-color: #EA2; /* make the default button prominent */ 166 | } 167 | 168 | 169 | QToolButton,QToolButton:unchecked { /* ToolBar里的按钮和带下拉菜单的按钮 */ 170 | border: 1px solid transparent; 171 | border-radius: 3px; 172 | background-color: transparent; 173 | margin: 1px; 174 | } 175 | QToolButton:checked{ 176 | background-color: #8BF; 177 | border-color: #59F; 178 | } 179 | QToolButton:hover{ 180 | background-color: #8BF; 181 | border-color: #59F; 182 | } 183 | 184 | QToolButton:pressed,QToolButton:checked:hover{ 185 | background-color: #59F; 186 | border-color: #EA2; 187 | } 188 | QToolButton:checked:pressed{ 189 | background-color: #8BF; 190 | } 191 | 192 | /* only for MenuButtonPopup */ 193 | QToolButton[popupMode="1"]{ 194 | padding-left: 1px; 195 | padding-right: 15px; /* make way for the popup button */ 196 | border: 1px solid #999999; 197 | min-height: 15px; 198 | /*background: qlineargradient(x1:0, y1:0 ,x2:0, y2:1 199 | stop: 0 #EEEEEF, stop: 0.05 #DADADF, stop: 0.5 #DADADF 200 | stop: 0.95 #EEEEEF stop: 1#EEEEEF)*/ 201 | } 202 | QToolButton[popupMode="1"]:hover{ 203 | background-color: #8BF; 204 | border-color: #59F; 205 | } 206 | QToolButton[popupMode="1"]:pressed{ 207 | border-width: 1px; 208 | background-color: #59F; 209 | border-color: #999999; 210 | } 211 | QToolButton::menu-button { 212 | border: 1px solid #999999; 213 | border-top-right-radius: 2px; 214 | border-bottom-right-radius: 2px; 215 | width: 16px; 216 | } 217 | 218 | 219 | /* =============================================== */ 220 | /* Slider ProgressBar */ 221 | /* =============================================== */ 222 | QProgressBar { 223 | font:10pt; 224 | border-radius:5px; 225 | text-align:center; 226 | border:1px solid #E8EDF2; 227 | background-color: rgb(255, 255, 255); 228 | border-color: rgb(180, 180, 180); 229 | } 230 | 231 | QProgressBar::chunk { 232 | border-radius:5px; 233 | background-color:#1ABC9C; 234 | } 235 | 236 | QSlider{ 237 | border: 1px solid transparent; 238 | } 239 | QSlider::groove{ 240 | border: 1px solid #999999; 241 | background: #FDFDFD; 242 | } 243 | QSlider::handle {/*设置中间的那个滑动的键*/ 244 | border: 1px solid #999999; 245 | background: #8BF; 246 | } 247 | QSlider::groove:horizontal { 248 | border: none; 249 | height: 6px; 250 | border-radius: 3px; 251 | background: lightgray; 252 | } 253 | QSlider::groove:vertical{ 254 | width: 3px; 255 | top: 5px; bottom: 5px; 256 | } 257 | QSlider::handle:horizontal{ 258 | border: none; 259 | margin: -5px 0px; /* 上下边距和左右边距*/ 260 | width: 16px; 261 | height: 16px; 262 | border-radius: 8px; 263 | background: #e83c3c; 264 | } 265 | QSlider::handle:vertical{ 266 | height: 6px; 267 | margin: -7px; /* height */ 268 | } 269 | QSlider::add-page{/*还没有滑上去的地方*/ 270 | background: lightgray; 271 | height: 4px; 272 | border-radius: 3px; 273 | } 274 | QSlider::sub-page{/*已经划过的从地方*/ 275 | background: #e83c3c; 276 | height: 4px; 277 | border-radius: 3px; 278 | } 279 | 280 | /* =============================================== */ 281 | /* ScrollBar */ 282 | /* =============================================== */ 283 | QScrollBar{ 284 | background-color: #FDFDFD; 285 | border: 1px solid #999999; 286 | border-radius: 5px; 287 | padding: 1px; 288 | height: 10px; 289 | width: 10px; 290 | } 291 | QScrollBar:hover{ 292 | border-color:#8BF; 293 | } 294 | QScrollBar::handle{ 295 | border-radius: 3px; 296 | background: #59F; 297 | min-width: 16px; 298 | min-height: 16px; 299 | } 300 | QScrollBar::handle:hover { 301 | background: #EA2; 302 | } 303 | QScrollBar::add-line, QScrollBar::sub-line, 304 | QScrollBar::add-page, QScrollBar::sub-page { 305 | width: 0px; 306 | background: transparent; 307 | } 308 | QScrollArea{ 309 | border: none; 310 | } 311 | /*QScrollArea QAbstractSlider{ 312 | border-radius: 0px; 313 | }*/ 314 | /* =============================================== */ 315 | /* DockWidget */ 316 | /* =============================================== */ 317 | QDockWidget, QDockWidget > QWidget/*not work*/ 318 | { 319 | border-color: #999999;/*qt bug*/ 320 | background: transparent; 321 | } 322 | QDockWidget::title { 323 | border-bottom: 1px solid #999999; 324 | border-style: inset; 325 | text-align: left; /* align the text to the left */ 326 | padding: 6px; 327 | } 328 | 329 | /* =============================================== */ 330 | /* GroupBox */ 331 | /* =============================================== */ 332 | QGroupBox { 333 | background-color: #FDFDFD; 334 | border: 1px solid #999999; 335 | border-radius: 4px; 336 | margin-top: 0.5em; 337 | } 338 | QGroupBox::title { 339 | subcontrol-origin: margin; 340 | subcontrol-position: top left; 341 | left: 1em; 342 | top: 0.1em; 343 | background-color: #FDFDFD; 344 | } 345 | /* =============================================== */ 346 | /* ToolBox */ 347 | /* =============================================== */ 348 | QToolBox{ 349 | border: 1px solid #999999; 350 | } 351 | QToolBox::tab { 352 | background: #EEEEEF; 353 | border: 1px solid #999999; 354 | border-radius: 1px; 355 | } 356 | QToolBox::tab:hover { 357 | background-color: #8BF; 358 | border-color: transparent; 359 | } 360 | QToolBox::tab:pressed { 361 | background-color: #59F; 362 | border-color: transparent; 363 | } 364 | QToolBox::tab:selected { 365 | font-weight: bold; 366 | border-color: #8BF; 367 | } 368 | 369 | /* =============================================== */ 370 | /* TabWidget */ 371 | /* =============================================== */ 372 | QTabWidget{ 373 | margin-top:10px; 374 | } 375 | QTabWidget::pane{ 376 | border: none; /* 无边框 */ 377 | border-top: 3px solid rgb(0, 160, 230); /*边款顶部:3px 实线 颜色(0,160,230)*/ 378 | background: transparent; /*背景透明*/ 379 | } 380 | QTabWidget::tab-bar { 381 | border: none; 382 | } 383 | QTabBar::tab { 384 | border: none; 385 | border-top-left-radius: 4px; 386 | border-top-right-radius: 4px; 387 | color: rgb(0, 0, 0); 388 | background: rgb(255, 255, 255, 30); 389 | height: 28px; 390 | min-width: 85px; 391 | margin-right: 5px; 392 | padding-left: 5px; 393 | padding-right: 5px; 394 | } 395 | QTabBar::tab:hover { 396 | background: rgb(0, 0, 255, 40); 397 | } 398 | QTabBar::tab:selected { 399 | color: white; 400 | background: rgb(0, 160, 230); 401 | } 402 | QTabBar::tab:pressed { 403 | background: #59F; 404 | border-color: transparent; 405 | } 406 | QTabBar::tab:focus { 407 | border-color: #EA2; 408 | } 409 | QTabBar::tab:top{ 410 | margin-top: 3px; 411 | border-bottom: transparent; 412 | margin-right: 1px; 413 | } 414 | QTabBar::tab:bottom{ 415 | margin-bottom: 3px; 416 | border-top: transparent; 417 | margin-right: 1px; 418 | } 419 | QTabBar::tab:left{ 420 | border-right: transparent; 421 | margin-bottom: 1px; 422 | } 423 | QTabBar::tab:right{ 424 | border-left: transparent; 425 | margin-bottom: 1px; 426 | } 427 | 428 | /* =============================================== */ 429 | /* QHeaderView for list table */ 430 | /* =============================================== */ 431 | QHeaderView { 432 | border: none; 433 | margin: 0px; 434 | padding: 0px; 435 | } 436 | QHeaderView::section, QTableCornerButton::section {/*设置表头属性*//*左上角*/ 437 | background-color: #EEEEEF; 438 | padding: 0 3px; 439 | border-right: 1px solid #999999; 440 | border-bottom: 1px solid #999999; 441 | border-radius: 0px; 442 | } 443 | QHeaderView::section:hover, QTableCornerButton::section:hover{ 444 | background-color: #8BF; 445 | } 446 | QHeaderView::section:pressed{ 447 | background-color: #59F; 448 | } 449 | QHeaderView::section:checked { 450 | background-color: #EA2; 451 | } 452 | 453 | /* =============================================== */ 454 | /* QTableWidget */ 455 | /* =============================================== */ 456 | QTableWidget, QTableView 457 | { 458 | gridline-color: #999999; /*表格中的网格线条颜色*/ 459 | background: #FDFDFD; 460 | /*设置交替颜色,需要在函数属性中设置:tableWidget->setAlternatingRowColors(true)*/ 461 | alternate-background-color: #EEEEEF; 462 | /*selection-color:#FDFDFD; 鼠标选中时前景色:文字颜色*/ 463 | selection-background-color:#8BF; /*鼠标选中时背景色*/ 464 | border:1px solid #999999; /*边框线的宽度、颜色*/ 465 | /*border:none; 去除边界线*/ 466 | /*border-radius:5px;*/ 467 | /*padding:10px 10px;*/ /*表格与边框的间距*/ 468 | } 469 | QTableView::item, QTabWidget::item{ 470 | background: transparent; 471 | outline-style: none; 472 | border: none; 473 | } 474 | 475 | QTableView::item:hover { 476 | background: #8BF; 477 | border: 1px solid #EA2; 478 | } 479 | 480 | QTableView::item:selected { 481 | background: #8BF; 482 | color: #EEEEEF; 483 | } 484 | 485 | QTableView::item:selected:active { 486 | background: #59F; 487 | color: #EEEEEF; 488 | } 489 | 490 | QTableWidget QComboBox{ 491 | margin: 2px; 492 | border: none; 493 | } 494 | -------------------------------------------------------------------------------- /core/CpuLineChart.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtChart import QChart, QSplineSeries, QValueAxis, QDateTimeAxis 2 | from PyQt5.QtCore import Qt, QTimer, QDateTime, QPointF 3 | from PyQt5.QtGui import QPen, QColor 4 | from psutil import cpu_percent 5 | 6 | 7 | class CpuLineChart(QChart): 8 | def __init__(self, *args, **kwargs): 9 | super(CpuLineChart, self).__init__(*args, **kwargs) 10 | self.m_count = 10 11 | # 隐藏图例 12 | self.legend().hide() 13 | self.m_series = QSplineSeries(self) 14 | # 设置画笔 15 | self.m_series.setPen(QPen(QColor('#3B8CFF'), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) 16 | self.addSeries(self.m_series) 17 | # x轴 18 | self.m_axisX = QDateTimeAxis(self) 19 | self.m_axisX.setTickCount(self.m_count + 1) # 设置刻度数量 20 | self.m_axisX.setFormat('ss') # 设置时间显示格式 21 | now = QDateTime.currentDateTime() # 前10秒到现在 22 | self.m_axisX.setRange(now.addSecs(-self.m_count), now) 23 | self.addAxis(self.m_axisX, Qt.AlignBottom) 24 | self.m_series.attachAxis(self.m_axisX) 25 | # y轴 26 | self.m_axisY = QValueAxis(self) 27 | self.m_axisY.setLabelFormat('%d') # 设置文本格式 28 | self.m_axisY.setMinorTickCount(4) # 设置小刻度线的数目 29 | self.m_axisY.setTickCount(self.m_count + 1) 30 | self.m_axisY.setRange(0, 100) 31 | self.addAxis(self.m_axisY, Qt.AlignLeft) 32 | self.m_series.attachAxis(self.m_axisY) 33 | 34 | # 填充11个初始点,注意x轴 需要转为秒的时间戳 35 | self.m_series.append( 36 | [QPointF(now.addSecs(-i).toMSecsSinceEpoch(), 0) for i in range(self.m_count, -1, -1)]) 37 | 38 | # 定时器获取数据 39 | self.m_timer = QTimer() 40 | self.m_timer.timeout.connect(self.update_data) 41 | self.m_timer.start(1000) 42 | 43 | def update_data(self): 44 | value = cpu_percent() 45 | now = QDateTime.currentDateTime() 46 | self.m_axisX.setRange(now.addSecs(-self.m_count), now) # 重新调整x轴的时间范围 47 | # 获取原来的所有点,去掉第一个并追加新的一个 48 | points = self.m_series.pointsVector() 49 | points.pop(0) 50 | points.append(QPointF(now.toMSecsSinceEpoch(), value)) 51 | # 替换法速度更快 52 | self.m_series.replace(points) 53 | -------------------------------------------------------------------------------- /core/DynamicSpline.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtChart import QChart, QSplineSeries, QValueAxis 2 | from PyQt5.QtCore import Qt,QTimer, QRandomGenerator 3 | from PyQt5.QtGui import QPen 4 | 5 | 6 | class DynamicSpline(QChart): 7 | def __init__(self): 8 | super().__init__() 9 | self.m_step = 0 10 | self.m_x = 5 11 | self.m_y = 1 12 | # 初始化图像 13 | self.series = QSplineSeries(self) 14 | green_pen = QPen(Qt.red) 15 | green_pen.setWidth(3) 16 | self.series.setPen(green_pen) 17 | self.axisX = QValueAxis() 18 | self.axisY = QValueAxis() 19 | self.series.append(self.m_x, self.m_y) 20 | 21 | self.addSeries(self.series) 22 | self.addAxis(self.axisX, Qt.AlignBottom) 23 | self.addAxis(self.axisY, Qt.AlignLeft) 24 | self.series.attachAxis(self.axisX) 25 | self.series.attachAxis(self.axisY) 26 | self.axisX.setTickCount(5) 27 | self.axisX.setRange(0, 10) 28 | self.axisY.setRange(-5, 10) 29 | 30 | self.timer = QTimer(self) 31 | self.timer.setInterval(1000) 32 | self.timer.timeout.connect(self.handleTimeout) 33 | self.timer.start() 34 | 35 | def handleTimeout(self): 36 | x = self.plotArea().width() / self.axisX.tickCount() 37 | y = (self.axisX.max() - self.axisX.min()) / self.axisX.tickCount() 38 | self.m_x += y 39 | # 在PyQt5.11.3及以上版本中,QRandomGenerator.global()被重命名为global_() 40 | self.m_y = QRandomGenerator.global_().bounded(5) - 2.5 41 | self.series.append(self.m_x, self.m_y) 42 | self.scroll(x, 0) 43 | if self.m_x >= 100: 44 | self.timer.stop() -------------------------------------------------------------------------------- /core/FileIconProvider.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import QFileInfo 2 | from PyQt5.QtGui import QIcon 3 | from PyQt5.QtWidgets import QFileIconProvider 4 | 5 | 6 | class FileIconProvider(QFileIconProvider): 7 | """图标提供类""" 8 | 9 | def __init__(self, *args, **kwargs): 10 | super(FileIconProvider, self).__init__(*args, **kwargs) 11 | self.DirIcon = QIcon("Data/icons/folder.png") 12 | self.TxtIcon = QIcon("Data/icons/file.png") 13 | 14 | def icon(self, type_info): 15 | ''' 16 | :param fileInfo: 参考http://doc.qt.io/qt-5/qfileinfo.html 17 | ''' 18 | if isinstance(type_info, QFileInfo): 19 | # 如果type_info是QFileInfo类型则用getInfoIcon来返回图标 20 | return self.getInfoIcon(type_info) 21 | # 如果type_info是QFileIconProvider自身的IconType枚举类型则执行下面的方法 22 | # 这里只能自定义通用的几种类型,参考http://doc.qt.io/qt-5/qfileiconprovider.html#IconType-enum 23 | ''' 24 | QFileIconProvider::Computer 0 25 | QFileIconProvider::Desktop 1 26 | QFileIconProvider::Trashcan 2 27 | QFileIconProvider::Network 3 28 | QFileIconProvider::Drive 4 29 | QFileIconProvider::Folder 5 30 | QFileIconProvider::File 6 31 | ''' 32 | if type_info == QFileIconProvider.Folder: 33 | # 如果是文件夹 34 | return self.DirIcon 35 | return super(FileIconProvider, self).icon(type_info) 36 | 37 | def getInfoIcon(self, type_info): 38 | if type_info.isDir(): # 文件夹 39 | return self.DirIcon 40 | if type_info.isFile() and type_info.suffix() == "txt": # 文件并且是txt 41 | return self.TxtIcon 42 | return super(FileIconProvider, self).icon(type_info) 43 | -------------------------------------------------------------------------------- /core/ImageView.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from PyQt5.QtCore import QPointF, Qt, QRectF, QSizeF 4 | from PyQt5.QtGui import QPainter, QColor, QImage, QPixmap 5 | from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsPixmapItem, QGraphicsScene 6 | 7 | 8 | class ImageView(QGraphicsView): 9 | """图片查看控件""" 10 | 11 | def __init__(self, *args, **kwargs): 12 | image = kwargs.pop('image', None) 13 | background = kwargs.pop('background', None) 14 | super(ImageView, self).__init__(*args, **kwargs) 15 | self.setCursor(Qt.OpenHandCursor) 16 | self.setBackground(background) 17 | self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 18 | self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 19 | self.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | 20 | QPainter.SmoothPixmapTransform) 21 | self.setCacheMode(self.CacheBackground) 22 | self.setViewportUpdateMode(self.SmartViewportUpdate) 23 | self._item = QGraphicsPixmapItem() # 放置图像 24 | self._item.setFlags(QGraphicsPixmapItem.ItemIsFocusable | 25 | QGraphicsPixmapItem.ItemIsMovable) 26 | self._scene = QGraphicsScene(self) # 场景 27 | self.setScene(self._scene) 28 | self._scene.addItem(self._item) 29 | rect = QApplication.instance().desktop().availableGeometry(self) 30 | self.resize(int(rect.width() * 2 / 3), int(rect.height() * 2 / 3)) 31 | 32 | self.pixmap = None 33 | self._delta = 0.1 # 缩放 34 | self.setPixmap(image) 35 | 36 | def setBackground(self, color): 37 | """设置背景颜色 38 | :param color: 背景颜色 39 | :type color: QColor or str or GlobalColor 40 | """ 41 | if isinstance(color, QColor): 42 | self.setBackgroundBrush(color) 43 | elif isinstance(color, (str, Qt.GlobalColor)): 44 | color = QColor(color) 45 | if color.isValid(): 46 | self.setBackgroundBrush(color) 47 | 48 | def setPixmap(self, pixmap, fitIn=True): 49 | """加载图片 50 | :param pixmap: 图片或者图片路径 51 | :param fitIn: 是否适应 52 | :type pixmap: QPixmap or QImage or str 53 | :type fitIn: bool 54 | """ 55 | if isinstance(pixmap, QPixmap): 56 | self.pixmap = pixmap 57 | elif isinstance(pixmap, QImage): 58 | self.pixmap = QPixmap.fromImage(pixmap) 59 | elif isinstance(pixmap, str) and os.path.isfile(pixmap): 60 | self.pixmap = QPixmap(pixmap) 61 | else: 62 | return 63 | self._item.setPixmap(self.pixmap) 64 | self._item.update() 65 | self.setSceneDims() 66 | if fitIn: 67 | self.fitInView(QRectF(self._item.pos(), QSizeF( 68 | self.pixmap.size())), Qt.KeepAspectRatio) 69 | self.update() 70 | 71 | def setSceneDims(self): 72 | if not self.pixmap: 73 | return 74 | self.setSceneRect(QRectF(QPointF(0, 0), QPointF(self.pixmap.width(), self.pixmap.height()))) 75 | 76 | def fitInView(self, rect, flags=Qt.IgnoreAspectRatio): 77 | """剧中适应 78 | :param rect: 矩形范围 79 | :param flags: 80 | :return: 81 | """ 82 | if not self.scene() or rect.isNull(): 83 | return 84 | unity = self.transform().mapRect(QRectF(0, 0, 1, 1)) 85 | self.scale(1 / unity.width(), 1 / unity.height()) 86 | viewRect = self.viewport().rect() 87 | sceneRect = self.transform().mapRect(rect) 88 | x_ratio = viewRect.width() / sceneRect.width() 89 | y_ratio = viewRect.height() / sceneRect.height() 90 | if flags == Qt.KeepAspectRatio: 91 | x_ratio = y_ratio = min(x_ratio, y_ratio) 92 | elif flags == Qt.KeepAspectRatioByExpanding: 93 | x_ratio = y_ratio = max(x_ratio, y_ratio) 94 | self.scale(x_ratio, y_ratio) 95 | self.centerOn(rect.center()) 96 | 97 | def wheelEvent(self, event): 98 | if event.angleDelta().y() > 0: 99 | self.zoomIn() 100 | else: 101 | self.zoomOut() 102 | 103 | def zoomIn(self): 104 | """放大""" 105 | self.zoom(1 + self._delta) 106 | 107 | def zoomOut(self): 108 | """缩小""" 109 | self.zoom(1 - self._delta) 110 | 111 | def zoom(self, factor): 112 | """缩放 113 | :param factor: 缩放的比例因子 114 | """ 115 | _factor = self.transform().scale( 116 | factor, factor).mapRect(QRectF(0, 0, 1, 1)).width() 117 | if _factor < 0.07 or _factor > 100: 118 | # 防止过大过小 119 | return 120 | self.scale(factor, factor) 121 | -------------------------------------------------------------------------------- /core/MetroCircleProgress.py: -------------------------------------------------------------------------------- 1 | from PyQt5.QtCore import QSequentialAnimationGroup, QPauseAnimation, QPropertyAnimation, \ 2 | QParallelAnimationGroup, QObject, QSize, Qt, QRectF, pyqtSignal, pyqtProperty 3 | from PyQt5.QtGui import QPainter, QColor 4 | from PyQt5.QtWidgets import QWidget 5 | 6 | 7 | class CircleItem(QObject): 8 | X = 0 # x坐标 9 | Opacity = 1 # 透明度0~1 10 | valueChanged = pyqtSignal() 11 | 12 | @pyqtProperty(float) 13 | def x(self) -> float: 14 | return self.X 15 | 16 | @x.setter 17 | def x(self, x: float): 18 | self.X = x 19 | self.valueChanged.emit() 20 | 21 | @pyqtProperty(float) 22 | def opacity(self) -> float: 23 | return self.Opacity 24 | 25 | @opacity.setter 26 | def opacity(self, opacity: float): 27 | self.Opacity = opacity 28 | 29 | 30 | def qBound(miv, cv, mxv): 31 | return max(min(cv, mxv), miv) 32 | 33 | 34 | class MetroCircleProgress(QWidget): 35 | Radius = 5 # 半径 36 | Color = QColor(24, 189, 155) # 圆圈颜色 37 | BackgroundColor = QColor(Qt.transparent) # 背景颜色 38 | 39 | def __init__(self, *args, radius=5, color=QColor(24, 189, 155), 40 | backgroundColor=QColor(Qt.transparent), **kwargs): 41 | super(MetroCircleProgress, self).__init__(*args, **kwargs) 42 | 43 | self.setMinimumSize(20,50) 44 | self.Radius = radius 45 | self.Color = color 46 | self.BackgroundColor = backgroundColor 47 | self._items = [] 48 | self._initAnimations() 49 | 50 | @pyqtProperty(int) 51 | def radius(self) -> int: 52 | return self.Radius 53 | 54 | @radius.setter 55 | def radius(self, radius: int): 56 | if self.Radius != radius: 57 | self.Radius = radius 58 | self.update() 59 | 60 | @pyqtProperty(QColor) 61 | def color(self) -> QColor: 62 | return self.Color 63 | 64 | @color.setter 65 | def color(self, color: QColor): 66 | if self.Color != color: 67 | self.Color = color 68 | self.update() 69 | 70 | @pyqtProperty(QColor) 71 | def backgroundColor(self) -> QColor: 72 | return self.BackgroundColor 73 | 74 | @backgroundColor.setter 75 | def backgroundColor(self, backgroundColor: QColor): 76 | if self.BackgroundColor != backgroundColor: 77 | self.BackgroundColor = backgroundColor 78 | self.update() 79 | 80 | def paintEvent(self, event): 81 | super(MetroCircleProgress, self).paintEvent(event) 82 | painter = QPainter(self) 83 | painter.setRenderHint(QPainter.Antialiasing) 84 | painter.fillRect(self.rect(), self.BackgroundColor) 85 | painter.setPen(Qt.NoPen) 86 | 87 | for item, _ in self._items: 88 | painter.save() 89 | color = self.Color.toRgb() 90 | color.setAlphaF(item.opacity) 91 | painter.setBrush(color) 92 | # 5<= radius <=10 93 | radius = qBound(self.Radius, self.Radius / 200 * 94 | self.height(), 2 * self.Radius) 95 | diameter = 2 * radius 96 | painter.drawRoundedRect( 97 | QRectF( 98 | item.x / 100 * self.width() - diameter, 99 | (self.height() - radius) / 2, 100 | diameter, diameter 101 | ), radius, radius) 102 | painter.restore() 103 | 104 | def _initAnimations(self): 105 | for index in range(5): # 5个小圆 106 | item = CircleItem(self) 107 | item.valueChanged.connect(self.update) 108 | # 串行动画组 109 | seqAnimation = QSequentialAnimationGroup(self) 110 | seqAnimation.setLoopCount(-1) 111 | self._items.append((item, seqAnimation)) 112 | 113 | # 暂停延迟动画 114 | seqAnimation.addAnimation(QPauseAnimation(150 * index, self)) 115 | 116 | # 加速,并行动画组1 117 | parAnimation1 = QParallelAnimationGroup(self) 118 | # 透明度 119 | parAnimation1.addAnimation( 120 | QPropertyAnimation(item, b'opacity', self, duration=400, startValue=0, endValue=1.0)) 121 | # x坐标 122 | parAnimation1.addAnimation(QPropertyAnimation(item, b'x', self, duration=400, startValue=0, endValue=25.0)) 123 | seqAnimation.addAnimation(parAnimation1) 124 | ## 125 | 126 | # 匀速 127 | seqAnimation.addAnimation( 128 | QPropertyAnimation(item, b'x', self, duration=2000, startValue=25.0, endValue=75.0)) 129 | 130 | # 加速,并行动画组2 131 | parAnimation2 = QParallelAnimationGroup(self) 132 | # 透明度 133 | parAnimation2.addAnimation( 134 | QPropertyAnimation(item, b'opacity', self, duration=400, startValue=1.0, endValue=0)) 135 | # x坐标 136 | parAnimation2.addAnimation( 137 | QPropertyAnimation(item, b'x', self, duration=400, startValue=75.0, endValue=100.0)) 138 | seqAnimation.addAnimation(parAnimation2) 139 | ## 140 | 141 | # 暂停延迟动画 142 | seqAnimation.addAnimation( 143 | QPauseAnimation((5 - index - 1) * 150, self)) 144 | 145 | for _, animation in self._items: 146 | animation.start() 147 | 148 | def sizeHint(self): 149 | return QSize(100, self.Radius * 2) 150 | -------------------------------------------------------------------------------- /core/MySystemTrayIcon.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtGui, QtCore 2 | from PyQt5.QtCore import QTimer 3 | from PyQt5.QtWidgets import QSystemTrayIcon, QAction, QApplication, QMenu, QGraphicsDropShadowEffect, QStyle 4 | from loguru import logger 5 | 6 | 7 | class MySystemTrayIcon(QSystemTrayIcon): 8 | """ 9 | 自定义的系统托盘图标类 10 | """ 11 | 12 | def init(self, parent=None): 13 | self.root = parent 14 | self.setupUi() 15 | 16 | def setupUi(self): 17 | self.icon = QtGui.QIcon() 18 | self.icon.addPixmap(QtGui.QPixmap(":/icon/icon/首页.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 19 | self.setIcon(self.icon) 20 | ''' 21 | Define and add steps to work with the system tray icon 22 | show - show window 23 | hide - hide window 24 | exit - exit from application 25 | ''' 26 | self.show_action = QAction("显示", self) 27 | self.hide_action = QAction("隐藏", self) 28 | self.quit_action = QAction("退出", self) 29 | self.show_action.triggered.connect(self.show_event) 30 | self.hide_action.triggered.connect(self.hide_event) 31 | self.quit_action.triggered.connect(QApplication.instance().quit) 32 | self.tray_menu = QMenu() 33 | self.tray_menu.addAction(self.show_action) 34 | self.tray_menu.addAction(self.hide_action) 35 | self.tray_menu.addAction(self.quit_action) 36 | self.setContextMenu(self.tray_menu) 37 | 38 | self.tray_menu.setAttribute(QtCore.Qt.WA_TranslucentBackground) # 背景透明 39 | self.tray_menu.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 去掉黑边 40 | self.tray_menu.setWindowFlag(QtCore.Qt.NoDropShadowWindowHint) # 去掉阴影 41 | self.tray_menu.setAutoFillBackground(True) 42 | # 增加阴影 43 | self.shadow = QGraphicsDropShadowEffect() 44 | self.shadow.setOffset(0, 0) 45 | self.shadow.setColor(QtCore.Qt.gray) 46 | self.shadow.setBlurRadius(9) 47 | self.tray_menu.setGraphicsEffect(self.shadow) 48 | 49 | self.QMenuStyleSheet = ''' 50 | QMenu { 51 | color:black; 52 | background-color:white; 53 | border-radius:12px; 54 | padding:5px; 55 | margin:6px; 56 | } 57 | QMenu::item { 58 | font-size: 8pt; 59 | border: 2px solid #909090; /*item选框*/ 60 | border-radius:12px; 61 | padding:5px 10px; /*设置菜单项文字上下和左右的内边距,效果就是菜单中的条目左右上下有了间隔*/ 62 | margin:2px 2px; /*设置菜单项的外边距*/ 63 | } 64 | QMenu::item:selected{ 65 | color:#1aa3ff; 66 | background-color: #e5f5ff; 67 | border-radius:12px; 68 | } 69 | QMenu::separator{ 70 | height:1px; 71 | background:#bbbbbb; 72 | margin:5px; 73 | margin-left:10px; 74 | margin-right:10px; 75 | } 76 | ''' 77 | self.tray_menu.setStyleSheet(self.QMenuStyleSheet) 78 | 79 | def show_event(self): 80 | logger.info("显示主窗口") 81 | self.root.show() 82 | self.setupUi() 83 | 84 | def hide_event(self): 85 | logger.info("隐藏主窗口") 86 | self.root.hide() 87 | self.setupUi() 88 | -------------------------------------------------------------------------------- /doc/README_zh.md: -------------------------------------------------------------------------------- 1 | ## pyqt5示例 2 | 3 | - ✨这是一个pyqt5示例🔥 4 | - 💻可以直接拿来快速进行开发功能,数据库连接,登录,注册功能 5 | 6 | 🎯包括了软件启动画面,可以用来提前加载库 7 |
8 | 🎯包括了登录界面 9 |
10 |
11 | 🎯包括了注册界面 12 |
13 | 🎯包括了数据库管理界面 14 |
15 | 🎯包括主窗口,实时显示cpu的利用率 16 |
17 | 18 | 🎯包括了任务栏最小化图标 19 |
20 |
21 | 22 | ## 项目文件结构 23 | 24 | - doc (文档相关) 25 | - config (程序初始化配置相关) 26 | - skin (存放皮肤的文件夹) 27 | - config.py (配置文件) 28 | - core (自定义的控件) 29 | - CpuLineChart.py (显示cpu利用率的折线图,可以自己继续完善) 30 | - DynamicSpline.py (动态变化的折线图,可以自己继续完善) 31 | - FileIconProvider.py (文件图标,可以自己继续完善) 32 | - ImageView.py (图片查看控件,支持缩放图片,可以自己继续完善) 33 | - MetroCircleProgress.py (动态的进度条,无状态的一直循环) 34 | - MySystemTrayIcon.py (自定义的系统托盘图标类) 35 | - res (程序使用的资源文件夹) 36 | - app.qrc (qt-designer💻编辑的资源集合文件) 37 | - app_rc.py (pyrcc5转换的资源文件,🚫不要修改) 38 | - ui (程序的ui文件夹) 39 | - login_form.ui (登录界面) 40 | - register_form.ui (注册界面) 41 | - mysql_form.ui (数据库管理界面) 42 | - close_dialog.ui (关闭提示界面) 43 | - main_window.ui (主窗口文件) 44 | - models (数据库相关文件夹) 45 | - db.sql (生成数据库文件) 46 | - user.py (用户表事务逻辑) 47 | - utils (工具类的文件夹) 48 | - CommonHelper.py (公共帮助类) 49 | - global_var.py (全局变量类) 50 | - connect_mysql.py (连接数据库) 51 | - logs.py (全局的log显示处理) 52 | - win (窗口逻辑文件夹) 53 | - splash (软件启动画面,用于提前加载深度学习库) 54 | - close_dialog.py (关闭按钮提示框的处理逻辑) 55 | - main_win.py (主窗口的逻辑处理) 56 | - login_form.py (登录界面的逻辑处理) 57 | - register_form.py (注册界面的逻辑处理) 58 | - mysql_form.py (数据库管理界面的逻辑处理) 59 | - app.py (程序入口文件) 60 | - .gitignore (git上传忽略的文件) 61 | - file_verison_info.txt (软件的版本信息) 62 | - LICENSE (项目支持的开源协议) 63 | - pyqt5_example.spec (pyinstaller打包使用的文件) 64 | - pyqt5_example_exe.spec (pyinstaller打包使用的文件) 65 | - requirements.txt (项目依赖库) 66 | - ui_to_py.bat 67 | - !注意修改coda环境路径 68 | - 启动💻自动使用pyuic与pyrcc5转换ui文件 69 | - start-qt-designer.bat 70 | - !注意修改coda环境路径 71 | - 启动💻qt-designer工具 72 | - README.md(项目说明文件) 73 | 74 | ## 环境安装 75 | 76 | ```bash 77 | # conda创建python虚拟环境 78 | conda create -n learn_pyqt5 python=3.8 79 | # 激活环境 80 | conda activate learn_pyqt5 81 | 82 | # 安装库 83 | pip install -r requirements.txt 84 | 85 | # 修改mysql服务器配置信息,在 `/config/config.py` 文件中 86 | 87 | # 数据库添加数据库,数据库中运行 `/model/db.sql` 文件 88 | 89 | # 打包 90 | # 打包成很多文件,建议依赖非常大的时候使用 91 | pyinstaller pyqt5_example.spec 92 | 93 | # 打包成单独的一个exe,建议小文件使用 94 | # 有一个缺点,它会先读入内存,把依赖解压到缓存目录,如果应用程序大的话,建议用上面的打包成一个文件夹 95 | pyinstaller pyqt5_example_exe.spec 96 | ``` -------------------------------------------------------------------------------- /doc/img/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/doc/img/0.png -------------------------------------------------------------------------------- /doc/img/1.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/doc/img/1.5.png -------------------------------------------------------------------------------- /doc/img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/doc/img/1.png -------------------------------------------------------------------------------- /doc/img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/doc/img/2.png -------------------------------------------------------------------------------- /doc/img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/doc/img/3.png -------------------------------------------------------------------------------- /doc/img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/doc/img/4.png -------------------------------------------------------------------------------- /doc/img/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/doc/img/5.png -------------------------------------------------------------------------------- /doc/img/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/doc/img/6.png -------------------------------------------------------------------------------- /file_verison_info.txt: -------------------------------------------------------------------------------- 1 | # UTF-8 2 | # 3 | # For more details about fixed file info 'ffi' see: 4 | # http://msdn.microsoft.com/en-us/library/ms646997.aspx 5 | VSVersionInfo( 6 | ffi=FixedFileInfo( 7 | # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) 8 | # Set not needed items to zero 0. 9 | filevers=(0, 0, 0, 2), # 文件版本 10 | prodvers=(0, 0, 0, 2), 11 | # Contains a bitmask that specifies the valid bits 'flags'r 12 | mask=0x3f, 13 | # Contains a bitmask that specifies the Boolean attributes of the file. 14 | flags=0x0, 15 | # The operating system for which this file was designed. 16 | # 0x4 - NT and there is no need to change it. 17 | OS=0x4, 18 | # The general type of file. 19 | # 0x1 - the file is an application. 20 | fileType=0x1, # 类型 21 | # The function of the file. 22 | # 0x0 - the function is not defined for this fileType 23 | subtype=0x0, 24 | # Creation date and time stamp. 25 | date=(0, 0) 26 | ), 27 | kids=[ 28 | StringFileInfo( 29 | [ 30 | StringTable( 31 | u'040904B0', 32 | [StringStruct(u'CompanyName', u'wp19991'), 33 | StringStruct(u'FileDescription', u'pyqt5_example'), # 文件说明 34 | StringStruct(u'FileVersion', u'0.0.2'), 35 | StringStruct(u'InternalName', u'SVN'), 36 | StringStruct(u'LegalCopyright', u'wp19991@c'), #版权 37 | StringStruct(u'OriginalFilename', u'pyqt5_example.exe'), #原始文件名 38 | StringStruct(u'ProductName', u'pyqt5_example'), #产品名称 39 | StringStruct(u'ProductVersion', u'0.0.1')]) #产品版本 40 | ]), 41 | VarFileInfo([VarStruct(u'Translation', [2052, 1200])]) # 语言 42 | ] 43 | ) -------------------------------------------------------------------------------- /models/db.sql: -------------------------------------------------------------------------------- 1 | use mysql; 2 | drop database if exists pyqt5_example_db; 3 | 4 | create database if not exists pyqt5_example_db 5 | default character set utf8mb4 6 | default collate utf8mb4_unicode_ci; 7 | 8 | use pyqt5_example_db; 9 | 10 | 11 | drop table if exists `t_user`; 12 | create table if not exists `t_user` 13 | ( 14 | `id` bigint unsigned not null auto_increment comment '自增id', 15 | `gmt_created` datetime not null default current_timestamp comment '自动生成-创建时间', 16 | `gmt_modified` datetime not null default current_timestamp on update current_timestamp comment '自动生成-修改时间', 17 | 18 | `user_name` varchar(25) not null unique comment '用户名(唯一,不为空)', 19 | `is_valid` tinyint(1) not null default 0 comment '用户是否注销(1:是,0:否)', 20 | `phone_number` varchar(11) unique comment '手机号(唯一,但是可为空)', 21 | `email_address` varchar(50) unique comment '用户邮箱(唯一,但是可为空)', 22 | `encoded_password` varchar(255) not null comment '密码', 23 | `type` tinyint(3) unsigned not null default 1 comment '用户的类型(1:普通用户 2:管理员)', 24 | `brief` varchar(255) not null default '无' comment '用户简要说明', 25 | 26 | constraint t_user_pk primary key (id) 27 | ) engine = InnoDB comment '用户表'; 28 | insert into `t_user`(user_name, encoded_password, type) 29 | values ('admin', md5(123456), 2); 30 | 31 | insert into `t_user`(user_name, encoded_password, type) 32 | values ('user_1', md5(123456), 1), 33 | ('user_2', md5(123456), 1); 34 | 35 | -------------------------------------------------------------------------------- /models/user.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import hashlib 3 | 4 | from peewee import CharField, IntegerField, BooleanField, DateTimeField 5 | 6 | from utils.connect_mysql import BaseModel 7 | 8 | 9 | class User(BaseModel): 10 | """ 11 | 用户信息表 12 | """ 13 | user_name = CharField() 14 | is_valid = BooleanField() 15 | phone_number = CharField() 16 | email_address = CharField() 17 | encoded_password = CharField() 18 | type = IntegerField() 19 | brief = CharField() 20 | 21 | class Meta: 22 | table_name = 't_user' 23 | 24 | @classmethod 25 | def user_create(cls, user_name: str, password: str): 26 | md5_password = hashlib.md5(password.encode(encoding='UTF-8')).hexdigest() 27 | user = User.create(user_name=user_name, encoded_password=md5_password) 28 | user.encoded_password = None 29 | return user 30 | 31 | @classmethod 32 | def user_delete(cls, user_id: int): 33 | res = User.delete().where(User.id == user_id).execute() 34 | if res == 0: 35 | return False 36 | else: 37 | return True 38 | 39 | @classmethod 40 | def user_update(cls, user_id: int, 41 | name: str, phone: str, email: str, password: str): 42 | try: 43 | u = User.get(User.id == user_id) 44 | if u is None: 45 | return False 46 | if name != "": 47 | u.user_name = name 48 | if phone != "": 49 | u.phone_number = phone 50 | if email != "": 51 | u.email_address = email 52 | if password != "": 53 | encoded_password = hashlib.md5(password.encode(encoding='UTF-8')).hexdigest() 54 | u.encoded_password = encoded_password 55 | # print(str(datetime.datetime.now())) 56 | u.gmt_modified = datetime.datetime.now() 57 | res = u.save() 58 | if res == 0: 59 | # 和之前一样,修改失败 60 | return False 61 | else: 62 | return True 63 | except: 64 | # 有重复的名称 65 | return False 66 | 67 | @classmethod 68 | def get_user_datas(cls): 69 | datas = User.select().where(1 == 1) 70 | return datas 71 | 72 | @classmethod 73 | def select_from_user_name_and_password(cls, user_name: str, password: str): 74 | try: 75 | md5_password = hashlib.md5(password.encode(encoding='UTF-8')).hexdigest() 76 | info = User.select().where(User.user_name == user_name)[0] 77 | if info.encoded_password == md5_password: 78 | return info 79 | else: 80 | return None 81 | except: 82 | return None 83 | 84 | @classmethod 85 | def select_from_user_id(cls, user_id: int): 86 | info = User.get(User.id == user_id) 87 | return info 88 | -------------------------------------------------------------------------------- /pyqt5_example.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | import sys 3 | sys.setrecursionlimit(5000) 4 | 5 | block_cipher = None 6 | 7 | 8 | a = Analysis(['app.py'], 9 | pathex=[], 10 | binaries=[], 11 | datas=[(r"res\*",r"res"), 12 | (r"config\skin\white.qss",r"config\skin"), 13 | (r"models\db.sql",r"models")], 14 | hiddenimports=[], 15 | hookspath=[], 16 | hooksconfig={}, 17 | runtime_hooks=[], 18 | excludes=[], 19 | win_no_prefer_redirects=False, 20 | win_private_assemblies=False, 21 | cipher=block_cipher, 22 | noarchive=False) 23 | 24 | for d in a.datas: 25 | if '_C.cp38-win_amd64.pyd' in d[0]: 26 | a.datas.remove(d) 27 | break 28 | 29 | pyz = PYZ(a.pure, a.zipped_data, 30 | cipher=block_cipher) 31 | 32 | exe = EXE(pyz, 33 | a.scripts, 34 | [], 35 | exclude_binaries=True, 36 | name='pyqt5_example', 37 | debug=False, 38 | bootloader_ignore_signals=False, 39 | strip=False, 40 | upx=True, 41 | console=False, 42 | disable_windowed_traceback=False, 43 | target_arch=None, 44 | codesign_identity=None, 45 | entitlements_file=None , icon='res\\icon\\首页.ico', 46 | version="file_verison_info.txt") 47 | coll = COLLECT(exe, 48 | a.binaries, 49 | a.zipfiles, 50 | a.datas, 51 | strip=False, 52 | upx=True, 53 | upx_exclude=[], 54 | name='pyqt5示例') 55 | -------------------------------------------------------------------------------- /pyqt5_example_exe.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | import sys 3 | sys.setrecursionlimit(5000) 4 | 5 | block_cipher = None 6 | 7 | 8 | a = Analysis(['app.py'], 9 | pathex=[], 10 | binaries=[], 11 | datas=[(r"res\*",r"res"), 12 | (r"config\skin\white.qss",r"config\skin"), 13 | (r"models\db.sql",r"models")], 14 | hiddenimports=[], 15 | hookspath=[], 16 | hooksconfig={}, 17 | runtime_hooks=[], 18 | excludes=[], 19 | win_no_prefer_redirects=False, 20 | win_private_assemblies=False, 21 | cipher=block_cipher, 22 | noarchive=False) 23 | 24 | for d in a.datas: 25 | if '_C.cp38-win_amd64.pyd' in d[0]: 26 | a.datas.remove(d) 27 | break 28 | 29 | pyz = PYZ(a.pure, a.zipped_data, 30 | cipher=block_cipher) 31 | 32 | exe = EXE(pyz, 33 | a.scripts, 34 | a.binaries, 35 | a.zipfiles, 36 | a.datas, 37 | [], 38 | name='pyqt5_example', 39 | debug=False, 40 | bootloader_ignore_signals=False, 41 | strip=False, 42 | upx=True, 43 | upx_exclude=[], 44 | runtime_tmpdir=None, 45 | console=False, 46 | disable_windowed_traceback=False, 47 | target_arch=None, 48 | codesign_identity=None, 49 | entitlements_file=None , icon='res\\icon\\首页.ico', 50 | version="file_verison_info.txt") 51 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyqt5~=5.15.4 2 | PyQtChart 3 | pyqt5-tools 4 | loguru 5 | pydantic 6 | peewee 7 | pymysql 8 | pyinstaller 9 | psutil -------------------------------------------------------------------------------- /res/app.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icon/close.svg 4 | icon/minimize.svg 5 | icon/plus.svg 6 | icon/首页.ico 7 | 8 | 9 | image/register.jpg 10 | image/American_Robin.jpg 11 | image/fish.png 12 | 13 | 14 | -------------------------------------------------------------------------------- /res/icon/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /res/icon/minimize.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /res/icon/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /res/icon/png_to_ico.py: -------------------------------------------------------------------------------- 1 | import os 2 | from PIL import Image 3 | 4 | # 获取目录下文件名 5 | files = os.listdir() 6 | # 图标大小 7 | size = (256, 256) 8 | 9 | for inName in files: 10 | # 分离文件名与扩展名 11 | tmp = os.path.splitext(inName) 12 | # 因为python文件跟图片在同目录,所以需要判断一下 13 | if tmp[1] == '.png': 14 | outName = tmp[0] + '.ico' 15 | # 打开图片并设置大小 16 | im = Image.open(inName).resize(size) 17 | try: 18 | # 图标文件保存 19 | im.save(outName) 20 | 21 | print('{} --> {}'.format(inName, outName)) 22 | except IOError: 23 | print('connot convert :', inName) 24 | -------------------------------------------------------------------------------- /res/icon/首页.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/res/icon/首页.ico -------------------------------------------------------------------------------- /res/image/American_Robin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/res/image/American_Robin.jpg -------------------------------------------------------------------------------- /res/image/fish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/res/image/fish.png -------------------------------------------------------------------------------- /res/image/register.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/res/image/register.jpg -------------------------------------------------------------------------------- /res/otf/Social Media Circled.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wp19991/PyQt5_example/fac9627957dfe7d386ac11c4a1ae4ef0d3f70527/res/otf/Social Media Circled.otf -------------------------------------------------------------------------------- /start-qt-designer.bat: -------------------------------------------------------------------------------- 1 | C:\DevelopmentTools\Miniconda3\miniconda3\envs\learn_pyqt5\Lib\site-packages\qt5_applications\Qt\bin\designer.exe -------------------------------------------------------------------------------- /ui/close_dialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/close_dialog.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.15.4 6 | # 7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is 8 | # run again. Do not edit this file unless you know what you are doing. 9 | 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | 13 | 14 | class Ui_Dialog(object): 15 | def setupUi(self, Dialog): 16 | Dialog.setObjectName("Dialog") 17 | Dialog.resize(377, 272) 18 | icon = QtGui.QIcon() 19 | icon.addPixmap(QtGui.QPixmap(":/icon/icon/关闭.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 20 | Dialog.setWindowIcon(icon) 21 | Dialog.setStyleSheet("QTextEdit#textEdit{\n" 22 | " background-color: rgba(0,0,0,0);\n" 23 | " selection-background-color:#88bbff;\n" 24 | " border: 0px solid rgba(0,0,0,0);\n" 25 | "}\n" 26 | "\n" 27 | "QLabel#label{\n" 28 | " color: rgba(0,0,0,0);\n" 29 | "}\n" 30 | "\n" 31 | "QWidget#widget {\n" 32 | " border-image: url(:/img/image/fish.png);\n" 33 | " border-radius:10px;\n" 34 | " background-color: rgba(0,0,0,0);\n" 35 | "}\n" 36 | "\n" 37 | "QDialogButtonBox [text=\"OK\"] {\n" 38 | " qproperty-text: \"好的\";\n" 39 | "}\n" 40 | "QDialogButtonBox [text=\"Save\"] {\n" 41 | " qproperty-text: \"保存\";\n" 42 | "}\n" 43 | "QDialogButtonBox [text=\"Save All\"] {\n" 44 | " qproperty-text: \"保存全部\";\n" 45 | "}\n" 46 | "\n" 47 | "QPushButton#close_pushButton{\n" 48 | " background-color: #ce5137;\n" 49 | " border-radius:10px;\n" 50 | "}\n" 51 | "\n" 52 | "QPushButton#close_pushButton:hover{\n" 53 | " background-size: cover;\n" 54 | " background-image: url(:/icon/icon/close.svg);\n" 55 | "}\n" 56 | "\n" 57 | "QPushButton#min_pushButton{\n" 58 | " background-color: #a1c661;\n" 59 | " border-radius:10px;\n" 60 | "}\n" 61 | "\n" 62 | "QPushButton#min_pushButton:hover{\n" 63 | " background-size: cover;\n" 64 | " background-image: url(:/icon/icon/minimize.svg);\n" 65 | "}") 66 | self.verticalLayout_3 = QtWidgets.QVBoxLayout(Dialog) 67 | self.verticalLayout_3.setObjectName("verticalLayout_3") 68 | self.widget = QtWidgets.QWidget(Dialog) 69 | self.widget.setObjectName("widget") 70 | self.verticalLayout = QtWidgets.QVBoxLayout(self.widget) 71 | self.verticalLayout.setObjectName("verticalLayout") 72 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout() 73 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 74 | self.title_label = QtWidgets.QLabel(self.widget) 75 | font = QtGui.QFont() 76 | font.setFamily("华文楷体") 77 | font.setBold(True) 78 | font.setWeight(75) 79 | self.title_label.setFont(font) 80 | self.title_label.setObjectName("title_label") 81 | self.horizontalLayout_2.addWidget(self.title_label) 82 | spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) 83 | self.horizontalLayout_2.addItem(spacerItem) 84 | self.min_pushButton = QtWidgets.QPushButton(self.widget) 85 | self.min_pushButton.setMinimumSize(QtCore.QSize(20, 20)) 86 | self.min_pushButton.setMaximumSize(QtCore.QSize(20, 20)) 87 | self.min_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 88 | self.min_pushButton.setText("") 89 | self.min_pushButton.setObjectName("min_pushButton") 90 | self.horizontalLayout_2.addWidget(self.min_pushButton) 91 | self.close_pushButton = QtWidgets.QPushButton(self.widget) 92 | self.close_pushButton.setMinimumSize(QtCore.QSize(20, 20)) 93 | self.close_pushButton.setMaximumSize(QtCore.QSize(20, 20)) 94 | self.close_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 95 | self.close_pushButton.setText("") 96 | self.close_pushButton.setObjectName("close_pushButton") 97 | self.horizontalLayout_2.addWidget(self.close_pushButton) 98 | self.verticalLayout.addLayout(self.horizontalLayout_2) 99 | self.add_widget = QtWidgets.QWidget(self.widget) 100 | self.add_widget.setObjectName("add_widget") 101 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.add_widget) 102 | self.verticalLayout_4.setObjectName("verticalLayout_4") 103 | self.is_min_status_checkBox = QtWidgets.QCheckBox(self.add_widget) 104 | self.is_min_status_checkBox.setChecked(True) 105 | self.is_min_status_checkBox.setObjectName("is_min_status_checkBox") 106 | self.verticalLayout_4.addWidget(self.is_min_status_checkBox) 107 | self.verticalLayout.addWidget(self.add_widget) 108 | self.textEdit = QtWidgets.QTextEdit(self.widget) 109 | self.textEdit.setObjectName("textEdit") 110 | self.verticalLayout.addWidget(self.textEdit) 111 | self.buttonBox = QtWidgets.QDialogButtonBox(self.widget) 112 | font = QtGui.QFont() 113 | font.setBold(False) 114 | font.setWeight(50) 115 | self.buttonBox.setFont(font) 116 | self.buttonBox.setOrientation(QtCore.Qt.Horizontal) 117 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok) 118 | self.buttonBox.setCenterButtons(False) 119 | self.buttonBox.setObjectName("buttonBox") 120 | self.verticalLayout.addWidget(self.buttonBox) 121 | self.verticalLayout_3.addWidget(self.widget) 122 | 123 | self.retranslateUi(Dialog) 124 | self.buttonBox.accepted.connect(Dialog.accept) 125 | self.buttonBox.rejected.connect(Dialog.reject) 126 | QtCore.QMetaObject.connectSlotsByName(Dialog) 127 | 128 | def retranslateUi(self, Dialog): 129 | _translate = QtCore.QCoreApplication.translate 130 | Dialog.setWindowTitle(_translate("Dialog", "Dialog")) 131 | self.title_label.setText(_translate("Dialog", "

关闭程序

")) 132 | self.is_min_status_checkBox.setText(_translate("Dialog", "最小化到任务栏图标")) 133 | from res import app_rc 134 | -------------------------------------------------------------------------------- /ui/close_dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 377 10 | 272 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | :/icon/icon/关闭.ico:/icon/icon/关闭.ico 19 | 20 | 21 | QTextEdit#textEdit{ 22 | background-color: rgba(0,0,0,0); 23 | selection-background-color:#88bbff; 24 | border: 0px solid rgba(0,0,0,0); 25 | } 26 | 27 | QLabel#label{ 28 | color: rgba(0,0,0,0); 29 | } 30 | 31 | QWidget#widget { 32 | border-image: url(:/img/image/fish.png); 33 | border-radius:10px; 34 | background-color: rgba(0,0,0,0); 35 | } 36 | 37 | QDialogButtonBox [text="OK"] { 38 | qproperty-text: "好的"; 39 | } 40 | QDialogButtonBox [text="Save"] { 41 | qproperty-text: "保存"; 42 | } 43 | QDialogButtonBox [text="Save All"] { 44 | qproperty-text: "保存全部"; 45 | } 46 | 47 | QPushButton#close_pushButton{ 48 | background-color: #ce5137; 49 | border-radius:10px; 50 | } 51 | 52 | QPushButton#close_pushButton:hover{ 53 | background-size: cover; 54 | background-image: url(:/icon/icon/close.svg); 55 | } 56 | 57 | QPushButton#min_pushButton{ 58 | background-color: #a1c661; 59 | border-radius:10px; 60 | } 61 | 62 | QPushButton#min_pushButton:hover{ 63 | background-size: cover; 64 | background-image: url(:/icon/icon/minimize.svg); 65 | } 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 华文楷体 78 | 75 79 | true 80 | 81 | 82 | 83 | <html><head/><body><p><span style=" font-size:11pt; color:#ffaa7f;">关闭程序</span></p></body></html> 84 | 85 | 86 | 87 | 88 | 89 | 90 | Qt::Horizontal 91 | 92 | 93 | 94 | 40 95 | 20 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 20 105 | 20 106 | 107 | 108 | 109 | 110 | 20 111 | 20 112 | 113 | 114 | 115 | PointingHandCursor 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 20 127 | 20 128 | 129 | 130 | 131 | 132 | 20 133 | 20 134 | 135 | 136 | 137 | PointingHandCursor 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 最小化到任务栏图标 153 | 154 | 155 | true 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 50 170 | false 171 | 172 | 173 | 174 | Qt::Horizontal 175 | 176 | 177 | QDialogButtonBox::Ok 178 | 179 | 180 | false 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | buttonBox 195 | accepted() 196 | Dialog 197 | accept() 198 | 199 | 200 | 248 201 | 254 202 | 203 | 204 | 157 205 | 274 206 | 207 | 208 | 209 | 210 | buttonBox 211 | rejected() 212 | Dialog 213 | reject() 214 | 215 | 216 | 316 217 | 260 218 | 219 | 220 | 286 221 | 274 222 | 223 | 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /ui/login_form.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/login_form.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.15.4 6 | # 7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is 8 | # run again. Do not edit this file unless you know what you are doing. 9 | 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | 13 | 14 | class Ui_Frame(object): 15 | def setupUi(self, Frame): 16 | Frame.setObjectName("Frame") 17 | Frame.resize(625, 613) 18 | icon = QtGui.QIcon() 19 | icon.addPixmap(QtGui.QPixmap(":/icon/icon/首页.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 20 | Frame.setWindowIcon(icon) 21 | self.widget = QtWidgets.QWidget(Frame) 22 | self.widget.setGeometry(QtCore.QRect(30, 30, 550, 550)) 23 | self.widget.setStyleSheet("QPushButton#login_pushButton{\n" 24 | " background-color:qlineargradient(spread:pad,x1:0,y1:0.505682,x2:1,y2:0.477,stop:0 rgba(11,131,120,219),stop:1 rgba(85,98,112,226));\n" 25 | " color:rgba(255,255,255,210);\n" 26 | " border-radius:5px;\n" 27 | "}\n" 28 | "\n" 29 | "QPushButton#login_pushButton:hover{\n" 30 | " background-color:qlineargradient(spread:pad,x1:0,y1:0.505682,x2:1,y2:0.477,stop:0 rgba(150,123,1111,219),stop:1 rgba(85,81,84,226));\n" 31 | "}\n" 32 | "\n" 33 | "QPushButton#login_pushButton:pressed{\n" 34 | " padding-left:5px;\n" 35 | " padding-top:5px;\n" 36 | " background-color:rgba(150,123,111,255);\n" 37 | "}\n" 38 | "\n" 39 | "QPushButton#forget_password_pushButton,#register_pushButton,#mysql_pushButton{\n" 40 | " background-color:rgba(0,0,0,0);\n" 41 | " border:none;\n" 42 | " border-bottom:1px solid rgb(179, 179, 179);\n" 43 | " color:rgba(0,0,0,240);\n" 44 | "}\n" 45 | "\n" 46 | "QPushButton#github_pushButton,#phone_pushButton,#email_pushButton{\n" 47 | " background-color:rgba(0,0,0,0);\n" 48 | " color:rgba(85,98,112,255);\n" 49 | "}\n" 50 | "\n" 51 | "QPushButton#github_pushButton:hover,#phone_pushButton:hover,#email_pushButton:hover{\n" 52 | " color:rgba(131,96,53,255);\n" 53 | "}\n" 54 | "\n" 55 | "QPushButton#github_pushButton:pressed,#phone_pushButton:pressed,#email_pushButton:pressed{\n" 56 | " padding-left:5px;\n" 57 | " padding-top:5px;\n" 58 | " color:rgba(91,88,53,255);\n" 59 | "}\n" 60 | "\n" 61 | "QPushButton#close_pushButton{\n" 62 | " background-color: #ce5137;\n" 63 | " border-radius:10px;\n" 64 | "}\n" 65 | "\n" 66 | "QPushButton#close_pushButton:hover{\n" 67 | " background-size: cover;\n" 68 | " background-image: url(:/icon/icon/close.svg);\n" 69 | "}\n" 70 | "\n" 71 | "QPushButton#min_pushButton{\n" 72 | " background-color: #a1c661;\n" 73 | " border-radius:10px;\n" 74 | "}\n" 75 | "\n" 76 | "QPushButton#min_pushButton:hover{\n" 77 | " background-size: cover;\n" 78 | " background-image: url(:/icon/icon/minimize.svg);\n" 79 | "}\n" 80 | "") 81 | self.widget.setObjectName("widget") 82 | self.label = QtWidgets.QLabel(self.widget) 83 | self.label.setGeometry(QtCore.QRect(40, 30, 280, 430)) 84 | self.label.setStyleSheet("border-image: url(:/img/image/American_Robin.jpg);\n" 85 | "border-top-left-radius:50px;") 86 | self.label.setObjectName("label") 87 | self.label_2 = QtWidgets.QLabel(self.widget) 88 | self.label_2.setGeometry(QtCore.QRect(40, 30, 280, 430)) 89 | self.label_2.setStyleSheet("background-color:rgba(0,0,0,80);\n" 90 | "border-top-left-radius:50px;") 91 | self.label_2.setText("") 92 | self.label_2.setObjectName("label_2") 93 | self.label_3 = QtWidgets.QLabel(self.widget) 94 | self.label_3.setGeometry(QtCore.QRect(270, 30, 240, 430)) 95 | self.label_3.setStyleSheet("background-color:rgba(255,255,255,255);\n" 96 | "border-bottom-right-radius:50px;") 97 | self.label_3.setText("") 98 | self.label_3.setObjectName("label_3") 99 | self.label_4 = QtWidgets.QLabel(self.widget) 100 | self.label_4.setGeometry(QtCore.QRect(300, 80, 180, 40)) 101 | self.label_4.setMinimumSize(QtCore.QSize(180, 40)) 102 | self.label_4.setMaximumSize(QtCore.QSize(180, 40)) 103 | font = QtGui.QFont() 104 | font.setFamily("楷体") 105 | font.setPointSize(20) 106 | font.setBold(True) 107 | font.setWeight(75) 108 | self.label_4.setFont(font) 109 | self.label_4.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) 110 | self.label_4.setStyleSheet("color:rgba(0,0,0,200);") 111 | self.label_4.setAlignment(QtCore.Qt.AlignCenter) 112 | self.label_4.setObjectName("label_4") 113 | self.user_name_lineEdit = QtWidgets.QLineEdit(self.widget) 114 | self.user_name_lineEdit.setGeometry(QtCore.QRect(295, 150, 190, 40)) 115 | self.user_name_lineEdit.setMinimumSize(QtCore.QSize(190, 40)) 116 | self.user_name_lineEdit.setMaximumSize(QtCore.QSize(190, 40)) 117 | font = QtGui.QFont() 118 | font.setFamily("华文楷体") 119 | font.setPointSize(15) 120 | self.user_name_lineEdit.setFont(font) 121 | self.user_name_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 122 | "border:none;\n" 123 | "border-bottom:2px solid rgba(46,82,101,200);\n" 124 | "color:rgba(0,0,0,240);\n" 125 | "padding-bottom:7px;") 126 | self.user_name_lineEdit.setObjectName("user_name_lineEdit") 127 | self.password_lineEdit = QtWidgets.QLineEdit(self.widget) 128 | self.password_lineEdit.setGeometry(QtCore.QRect(295, 215, 190, 40)) 129 | self.password_lineEdit.setMinimumSize(QtCore.QSize(190, 40)) 130 | self.password_lineEdit.setMaximumSize(QtCore.QSize(190, 40)) 131 | font = QtGui.QFont() 132 | font.setFamily("华文楷体") 133 | font.setPointSize(15) 134 | self.password_lineEdit.setFont(font) 135 | self.password_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 136 | "border:none;\n" 137 | "border-bottom:2px solid rgba(46,82,101,200);\n" 138 | "color:rgba(0,0,0,240);\n" 139 | "padding-bottom:7px;") 140 | self.password_lineEdit.setEchoMode(QtWidgets.QLineEdit.Password) 141 | self.password_lineEdit.setObjectName("password_lineEdit") 142 | self.login_pushButton = QtWidgets.QPushButton(self.widget) 143 | self.login_pushButton.setGeometry(QtCore.QRect(295, 295, 190, 40)) 144 | self.login_pushButton.setMinimumSize(QtCore.QSize(190, 40)) 145 | self.login_pushButton.setMaximumSize(QtCore.QSize(190, 40)) 146 | font = QtGui.QFont() 147 | font.setFamily("华文楷体") 148 | font.setPointSize(20) 149 | font.setBold(True) 150 | font.setWeight(75) 151 | self.login_pushButton.setFont(font) 152 | self.login_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 153 | self.login_pushButton.setObjectName("login_pushButton") 154 | self.horizontalLayoutWidget = QtWidgets.QWidget(self.widget) 155 | self.horizontalLayoutWidget.setGeometry(QtCore.QRect(300, 390, 171, 32)) 156 | self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") 157 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget) 158 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0) 159 | self.horizontalLayout.setSpacing(0) 160 | self.horizontalLayout.setObjectName("horizontalLayout") 161 | self.github_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget) 162 | self.github_pushButton.setMinimumSize(QtCore.QSize(30, 30)) 163 | self.github_pushButton.setMaximumSize(QtCore.QSize(30, 30)) 164 | font = QtGui.QFont() 165 | font.setFamily("Social Media Circled") 166 | font.setPointSize(15) 167 | self.github_pushButton.setFont(font) 168 | self.github_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 169 | self.github_pushButton.setStyleSheet("") 170 | self.github_pushButton.setObjectName("github_pushButton") 171 | self.horizontalLayout.addWidget(self.github_pushButton) 172 | self.phone_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget) 173 | self.phone_pushButton.setMinimumSize(QtCore.QSize(30, 30)) 174 | self.phone_pushButton.setMaximumSize(QtCore.QSize(30, 30)) 175 | font = QtGui.QFont() 176 | font.setFamily("Social Media Circled") 177 | font.setPointSize(15) 178 | self.phone_pushButton.setFont(font) 179 | self.phone_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 180 | self.phone_pushButton.setStyleSheet("") 181 | self.phone_pushButton.setObjectName("phone_pushButton") 182 | self.horizontalLayout.addWidget(self.phone_pushButton) 183 | self.email_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget) 184 | self.email_pushButton.setMinimumSize(QtCore.QSize(30, 30)) 185 | self.email_pushButton.setMaximumSize(QtCore.QSize(30, 30)) 186 | font = QtGui.QFont() 187 | font.setFamily("Social Media Circled") 188 | font.setPointSize(15) 189 | self.email_pushButton.setFont(font) 190 | self.email_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 191 | self.email_pushButton.setStyleSheet("") 192 | self.email_pushButton.setObjectName("email_pushButton") 193 | self.horizontalLayout.addWidget(self.email_pushButton) 194 | self.min_pushButton = QtWidgets.QPushButton(self.widget) 195 | self.min_pushButton.setGeometry(QtCore.QRect(455, 40, 20, 20)) 196 | self.min_pushButton.setMinimumSize(QtCore.QSize(20, 20)) 197 | self.min_pushButton.setMaximumSize(QtCore.QSize(20, 20)) 198 | self.min_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 199 | self.min_pushButton.setText("") 200 | self.min_pushButton.setObjectName("min_pushButton") 201 | self.close_pushButton = QtWidgets.QPushButton(self.widget) 202 | self.close_pushButton.setGeometry(QtCore.QRect(480, 40, 20, 20)) 203 | self.close_pushButton.setMinimumSize(QtCore.QSize(20, 20)) 204 | self.close_pushButton.setMaximumSize(QtCore.QSize(20, 20)) 205 | self.close_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 206 | self.close_pushButton.setText("") 207 | self.close_pushButton.setObjectName("close_pushButton") 208 | self.forget_password_pushButton = QtWidgets.QPushButton(self.widget) 209 | self.forget_password_pushButton.setGeometry(QtCore.QRect(300, 350, 75, 23)) 210 | self.forget_password_pushButton.setMinimumSize(QtCore.QSize(75, 23)) 211 | self.forget_password_pushButton.setMaximumSize(QtCore.QSize(75, 23)) 212 | font = QtGui.QFont() 213 | font.setFamily("华文楷体") 214 | font.setPointSize(12) 215 | font.setBold(False) 216 | font.setWeight(50) 217 | self.forget_password_pushButton.setFont(font) 218 | self.forget_password_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 219 | self.forget_password_pushButton.setObjectName("forget_password_pushButton") 220 | self.register_pushButton = QtWidgets.QPushButton(self.widget) 221 | self.register_pushButton.setGeometry(QtCore.QRect(400, 350, 75, 23)) 222 | self.register_pushButton.setMinimumSize(QtCore.QSize(75, 23)) 223 | self.register_pushButton.setMaximumSize(QtCore.QSize(75, 23)) 224 | font = QtGui.QFont() 225 | font.setFamily("华文楷体") 226 | font.setPointSize(12) 227 | self.register_pushButton.setFont(font) 228 | self.register_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 229 | self.register_pushButton.setObjectName("register_pushButton") 230 | self.mysql_pushButton = QtWidgets.QPushButton(self.widget) 231 | self.mysql_pushButton.setGeometry(QtCore.QRect(280, 40, 75, 23)) 232 | self.mysql_pushButton.setMinimumSize(QtCore.QSize(75, 23)) 233 | self.mysql_pushButton.setMaximumSize(QtCore.QSize(75, 23)) 234 | font = QtGui.QFont() 235 | font.setFamily("华文楷体") 236 | font.setPointSize(13) 237 | self.mysql_pushButton.setFont(font) 238 | self.mysql_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 239 | self.mysql_pushButton.setObjectName("mysql_pushButton") 240 | 241 | self.retranslateUi(Frame) 242 | QtCore.QMetaObject.connectSlotsByName(Frame) 243 | 244 | def retranslateUi(self, Frame): 245 | _translate = QtCore.QCoreApplication.translate 246 | Frame.setWindowTitle(_translate("Frame", "登录")) 247 | self.label.setText(_translate("Frame", "TextLabel")) 248 | self.label_4.setText(_translate("Frame", "登录界面")) 249 | self.user_name_lineEdit.setPlaceholderText(_translate("Frame", "用户名")) 250 | self.password_lineEdit.setPlaceholderText(_translate("Frame", "密码")) 251 | self.login_pushButton.setText(_translate("Frame", "登录")) 252 | self.github_pushButton.setText(_translate("Frame", ")")) 253 | self.phone_pushButton.setText(_translate("Frame", "#")) 254 | self.email_pushButton.setText(_translate("Frame", "k")) 255 | self.forget_password_pushButton.setText(_translate("Frame", "忘记密码?")) 256 | self.register_pushButton.setText(_translate("Frame", "用户注册")) 257 | self.mysql_pushButton.setText(_translate("Frame", "数据库")) 258 | from res import app_rc 259 | -------------------------------------------------------------------------------- /ui/login_form.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Frame 4 | 5 | 6 | 7 | 0 8 | 0 9 | 625 10 | 613 11 | 12 | 13 | 14 | 登录 15 | 16 | 17 | 18 | :/icon/icon/首页.ico:/icon/icon/首页.ico 19 | 20 | 21 | 22 | 23 | 30 24 | 30 25 | 550 26 | 550 27 | 28 | 29 | 30 | QPushButton#login_pushButton{ 31 | background-color:qlineargradient(spread:pad,x1:0,y1:0.505682,x2:1,y2:0.477,stop:0 rgba(11,131,120,219),stop:1 rgba(85,98,112,226)); 32 | color:rgba(255,255,255,210); 33 | border-radius:5px; 34 | } 35 | 36 | QPushButton#login_pushButton:hover{ 37 | background-color:qlineargradient(spread:pad,x1:0,y1:0.505682,x2:1,y2:0.477,stop:0 rgba(150,123,1111,219),stop:1 rgba(85,81,84,226)); 38 | } 39 | 40 | QPushButton#login_pushButton:pressed{ 41 | padding-left:5px; 42 | padding-top:5px; 43 | background-color:rgba(150,123,111,255); 44 | } 45 | 46 | QPushButton#forget_password_pushButton,#register_pushButton,#mysql_pushButton{ 47 | background-color:rgba(0,0,0,0); 48 | border:none; 49 | border-bottom:1px solid rgb(179, 179, 179); 50 | color:rgba(0,0,0,240); 51 | } 52 | 53 | QPushButton#github_pushButton,#phone_pushButton,#email_pushButton{ 54 | background-color:rgba(0,0,0,0); 55 | color:rgba(85,98,112,255); 56 | } 57 | 58 | QPushButton#github_pushButton:hover,#phone_pushButton:hover,#email_pushButton:hover{ 59 | color:rgba(131,96,53,255); 60 | } 61 | 62 | QPushButton#github_pushButton:pressed,#phone_pushButton:pressed,#email_pushButton:pressed{ 63 | padding-left:5px; 64 | padding-top:5px; 65 | color:rgba(91,88,53,255); 66 | } 67 | 68 | QPushButton#close_pushButton{ 69 | background-color: #ce5137; 70 | border-radius:10px; 71 | } 72 | 73 | QPushButton#close_pushButton:hover{ 74 | background-size: cover; 75 | background-image: url(:/icon/icon/close.svg); 76 | } 77 | 78 | QPushButton#min_pushButton{ 79 | background-color: #a1c661; 80 | border-radius:10px; 81 | } 82 | 83 | QPushButton#min_pushButton:hover{ 84 | background-size: cover; 85 | background-image: url(:/icon/icon/minimize.svg); 86 | } 87 | 88 | 89 | 90 | 91 | 92 | 40 93 | 30 94 | 280 95 | 430 96 | 97 | 98 | 99 | border-image: url(:/img/image/American_Robin.jpg); 100 | border-top-left-radius:50px; 101 | 102 | 103 | TextLabel 104 | 105 | 106 | 107 | 108 | 109 | 40 110 | 30 111 | 280 112 | 430 113 | 114 | 115 | 116 | background-color:rgba(0,0,0,80); 117 | border-top-left-radius:50px; 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 270 127 | 30 128 | 240 129 | 430 130 | 131 | 132 | 133 | background-color:rgba(255,255,255,255); 134 | border-bottom-right-radius:50px; 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 300 144 | 80 145 | 180 146 | 40 147 | 148 | 149 | 150 | 151 | 180 152 | 40 153 | 154 | 155 | 156 | 157 | 180 158 | 40 159 | 160 | 161 | 162 | 163 | 楷体 164 | 20 165 | 75 166 | true 167 | 168 | 169 | 170 | ArrowCursor 171 | 172 | 173 | color:rgba(0,0,0,200); 174 | 175 | 176 | 登录界面 177 | 178 | 179 | Qt::AlignCenter 180 | 181 | 182 | 183 | 184 | 185 | 295 186 | 150 187 | 190 188 | 40 189 | 190 | 191 | 192 | 193 | 190 194 | 40 195 | 196 | 197 | 198 | 199 | 190 200 | 40 201 | 202 | 203 | 204 | 205 | 华文楷体 206 | 15 207 | 208 | 209 | 210 | background-color:rgba(0,0,0,0); 211 | border:none; 212 | border-bottom:2px solid rgba(46,82,101,200); 213 | color:rgba(0,0,0,240); 214 | padding-bottom:7px; 215 | 216 | 217 | 用户名 218 | 219 | 220 | 221 | 222 | 223 | 295 224 | 215 225 | 190 226 | 40 227 | 228 | 229 | 230 | 231 | 190 232 | 40 233 | 234 | 235 | 236 | 237 | 190 238 | 40 239 | 240 | 241 | 242 | 243 | 华文楷体 244 | 15 245 | 246 | 247 | 248 | background-color:rgba(0,0,0,0); 249 | border:none; 250 | border-bottom:2px solid rgba(46,82,101,200); 251 | color:rgba(0,0,0,240); 252 | padding-bottom:7px; 253 | 254 | 255 | QLineEdit::Password 256 | 257 | 258 | 密码 259 | 260 | 261 | 262 | 263 | 264 | 295 265 | 295 266 | 190 267 | 40 268 | 269 | 270 | 271 | 272 | 190 273 | 40 274 | 275 | 276 | 277 | 278 | 190 279 | 40 280 | 281 | 282 | 283 | 284 | 华文楷体 285 | 20 286 | 75 287 | true 288 | 289 | 290 | 291 | PointingHandCursor 292 | 293 | 294 | 登录 295 | 296 | 297 | 298 | 299 | 300 | 300 301 | 390 302 | 171 303 | 32 304 | 305 | 306 | 307 | 308 | 0 309 | 310 | 311 | 312 | 313 | 314 | 30 315 | 30 316 | 317 | 318 | 319 | 320 | 30 321 | 30 322 | 323 | 324 | 325 | 326 | Social Media Circled 327 | 15 328 | 329 | 330 | 331 | PointingHandCursor 332 | 333 | 334 | 335 | 336 | 337 | ) 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 30 346 | 30 347 | 348 | 349 | 350 | 351 | 30 352 | 30 353 | 354 | 355 | 356 | 357 | Social Media Circled 358 | 15 359 | 360 | 361 | 362 | PointingHandCursor 363 | 364 | 365 | 366 | 367 | 368 | # 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 30 377 | 30 378 | 379 | 380 | 381 | 382 | 30 383 | 30 384 | 385 | 386 | 387 | 388 | Social Media Circled 389 | 15 390 | 391 | 392 | 393 | PointingHandCursor 394 | 395 | 396 | 397 | 398 | 399 | k 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 455 409 | 40 410 | 20 411 | 20 412 | 413 | 414 | 415 | 416 | 20 417 | 20 418 | 419 | 420 | 421 | 422 | 20 423 | 20 424 | 425 | 426 | 427 | PointingHandCursor 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 480 437 | 40 438 | 20 439 | 20 440 | 441 | 442 | 443 | 444 | 20 445 | 20 446 | 447 | 448 | 449 | 450 | 20 451 | 20 452 | 453 | 454 | 455 | PointingHandCursor 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 300 465 | 350 466 | 75 467 | 23 468 | 469 | 470 | 471 | 472 | 75 473 | 23 474 | 475 | 476 | 477 | 478 | 75 479 | 23 480 | 481 | 482 | 483 | 484 | 华文楷体 485 | 12 486 | 50 487 | false 488 | 489 | 490 | 491 | PointingHandCursor 492 | 493 | 494 | 忘记密码? 495 | 496 | 497 | 498 | 499 | 500 | 400 501 | 350 502 | 75 503 | 23 504 | 505 | 506 | 507 | 508 | 75 509 | 23 510 | 511 | 512 | 513 | 514 | 75 515 | 23 516 | 517 | 518 | 519 | 520 | 华文楷体 521 | 12 522 | 523 | 524 | 525 | PointingHandCursor 526 | 527 | 528 | 用户注册 529 | 530 | 531 | 532 | 533 | 534 | 280 535 | 40 536 | 75 537 | 23 538 | 539 | 540 | 541 | 542 | 75 543 | 23 544 | 545 | 546 | 547 | 548 | 75 549 | 23 550 | 551 | 552 | 553 | 554 | 华文楷体 555 | 13 556 | 557 | 558 | 559 | PointingHandCursor 560 | 561 | 562 | 数据库 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | -------------------------------------------------------------------------------- /ui/main_window.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/main_window.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.15.4 6 | # 7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is 8 | # run again. Do not edit this file unless you know what you are doing. 9 | 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | 13 | 14 | class Ui_MainWindow(object): 15 | def setupUi(self, MainWindow): 16 | MainWindow.setObjectName("MainWindow") 17 | MainWindow.resize(561, 521) 18 | MainWindow.setMinimumSize(QtCore.QSize(500, 500)) 19 | icon = QtGui.QIcon() 20 | icon.addPixmap(QtGui.QPixmap(":/icon/icon/首页.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 21 | MainWindow.setWindowIcon(icon) 22 | MainWindow.setStyleSheet("QWidget#centralwidget{\n" 23 | " border-image: url(:/img/fish.png);\n" 24 | "}\n" 25 | "\n" 26 | "QWidget#widget{\n" 27 | " background-color:rgba(0,0,0,0);\n" 28 | "}\n" 29 | "\n" 30 | "QTextBrowser#textBrowser{\n" 31 | " background-color:rgba(0,0,0,0);\n" 32 | "}\n" 33 | "") 34 | self.centralwidget = QtWidgets.QWidget(MainWindow) 35 | self.centralwidget.setObjectName("centralwidget") 36 | self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) 37 | self.verticalLayout.setObjectName("verticalLayout") 38 | MainWindow.setCentralWidget(self.centralwidget) 39 | 40 | self.retranslateUi(MainWindow) 41 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 42 | 43 | def retranslateUi(self, MainWindow): 44 | _translate = QtCore.QCoreApplication.translate 45 | MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 46 | from res import app_rc 47 | -------------------------------------------------------------------------------- /ui/main_window.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 561 10 | 521 11 | 12 | 13 | 14 | 15 | 500 16 | 500 17 | 18 | 19 | 20 | MainWindow 21 | 22 | 23 | 24 | :/icon/icon/首页.ico:/icon/icon/首页.ico 25 | 26 | 27 | QWidget#centralwidget{ 28 | border-image: url(:/img/fish.png); 29 | } 30 | 31 | QWidget#widget{ 32 | background-color:rgba(0,0,0,0); 33 | } 34 | 35 | QTextBrowser#textBrowser{ 36 | background-color:rgba(0,0,0,0); 37 | } 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ui/mysql_form.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/mysql_form.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.15.4 6 | # 7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is 8 | # run again. Do not edit this file unless you know what you are doing. 9 | 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | 13 | 14 | class Ui_Frame(object): 15 | def setupUi(self, Frame): 16 | Frame.setObjectName("Frame") 17 | Frame.resize(980, 568) 18 | Frame.setMinimumSize(QtCore.QSize(980, 0)) 19 | icon = QtGui.QIcon() 20 | icon.addPixmap(QtGui.QPixmap(":/icon/icon/首页.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 21 | Frame.setWindowIcon(icon) 22 | Frame.setStyleSheet("QPushButton#close_pushButton{\n" 23 | " background-color: #ce5137;\n" 24 | " border-radius:10px;\n" 25 | "}\n" 26 | "\n" 27 | "QPushButton#close_pushButton:hover{\n" 28 | " background-size: cover;\n" 29 | " background-image: url(:/icon/icon/close.svg);\n" 30 | "}\n" 31 | "\n" 32 | "QPushButton#min_pushButton{\n" 33 | " background-color: #a1c661;\n" 34 | " border-radius:10px;\n" 35 | "}\n" 36 | "\n" 37 | "QPushButton#min_pushButton:hover{\n" 38 | " background-size: cover;\n" 39 | " background-image: url(:/icon/icon/minimize.svg);\n" 40 | "}\n" 41 | "\n" 42 | "QWidget#widget{\n" 43 | "background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0.0284091 rgba(129, 255, 251, 255), stop:0.9375 rgba(255, 255, 255, 255));\n" 44 | "\n" 45 | "border-radius: 14;\n" 46 | "}\n" 47 | "\n" 48 | "QTableWidget, QTableView\n" 49 | "{\n" 50 | " gridline-color: #999999; /*表格中的网格线条颜色*/\n" 51 | " background: #FDFDFD;\n" 52 | " /*设置交替颜色,需要在函数属性中设置:tableWidget->setAlternatingRowColors(true)*/\n" 53 | " alternate-background-color: #EEEEEF;\n" 54 | " /*selection-color:#FDFDFD; 鼠标选中时前景色:文字颜色*/\n" 55 | " selection-background-color:#8BF; /*鼠标选中时背景色*/\n" 56 | " border:1px solid #999999; /*边框线的宽度、颜色*/\n" 57 | " /*border:none; 去除边界线*/\n" 58 | " /*border-radius:5px;*/\n" 59 | " /*padding:10px 10px;*/ /*表格与边框的间距*/\n" 60 | "}\n" 61 | "QTableView::item, QTabWidget::item{\n" 62 | " background: transparent;\n" 63 | " outline-style: none;\n" 64 | " border: none;\n" 65 | "}\n" 66 | "\n" 67 | "QTableView::item:hover {\n" 68 | " background: #8BF;\n" 69 | " border: 1px solid #EA2;\n" 70 | "}\n" 71 | "\n" 72 | "QTableView::item:selected {\n" 73 | " background: #8BF;\n" 74 | " color: #EEEEEF;\n" 75 | "}\n" 76 | "\n" 77 | "QTableView::item:selected:active {\n" 78 | " background: #59F;\n" 79 | " color: #EEEEEF;\n" 80 | "}\n" 81 | "\n" 82 | "QTableWidget QComboBox{\n" 83 | " margin: 2px;\n" 84 | " border: none;\n" 85 | "}\n" 86 | "\n" 87 | "\n" 88 | "QGroupBox {\n" 89 | "border: 2px solid #999999;\n" 90 | "border-radius: 4px;\n" 91 | "margin-top: 0.5em;\n" 92 | "}\n" 93 | "QGroupBox::title {\n" 94 | "subcontrol-origin: margin;\n" 95 | "subcontrol-position: top left;\n" 96 | "left: 1em;\n" 97 | "top: 0.1em;\n" 98 | "}\n" 99 | "") 100 | self.horizontalLayout = QtWidgets.QHBoxLayout(Frame) 101 | self.horizontalLayout.setObjectName("horizontalLayout") 102 | self.widget = QtWidgets.QWidget(Frame) 103 | self.widget.setMinimumSize(QtCore.QSize(950, 550)) 104 | self.widget.setObjectName("widget") 105 | self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.widget) 106 | self.verticalLayout_5.setObjectName("verticalLayout_5") 107 | self.horizontalLayout_6 = QtWidgets.QHBoxLayout() 108 | self.horizontalLayout_6.setObjectName("horizontalLayout_6") 109 | self.groupBox_4 = QtWidgets.QGroupBox(self.widget) 110 | self.groupBox_4.setMinimumSize(QtCore.QSize(240, 110)) 111 | self.groupBox_4.setMaximumSize(QtCore.QSize(240, 16777215)) 112 | font = QtGui.QFont() 113 | font.setPointSize(11) 114 | self.groupBox_4.setFont(font) 115 | self.groupBox_4.setObjectName("groupBox_4") 116 | self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox_4) 117 | self.horizontalLayout_4.setObjectName("horizontalLayout_4") 118 | self.verticalLayout_3 = QtWidgets.QVBoxLayout() 119 | self.verticalLayout_3.setObjectName("verticalLayout_3") 120 | self.admin_login_of_user_name_lineEdit = QtWidgets.QLineEdit(self.groupBox_4) 121 | self.admin_login_of_user_name_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 122 | self.admin_login_of_user_name_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 123 | font = QtGui.QFont() 124 | font.setPointSize(9) 125 | self.admin_login_of_user_name_lineEdit.setFont(font) 126 | self.admin_login_of_user_name_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 127 | "border:none;\n" 128 | "border-bottom:2px solid rgba(46,82,101,200);\n" 129 | "color:rgba(0,0,0,240);\n" 130 | "padding-bottom:2px;") 131 | self.admin_login_of_user_name_lineEdit.setObjectName("admin_login_of_user_name_lineEdit") 132 | self.verticalLayout_3.addWidget(self.admin_login_of_user_name_lineEdit) 133 | self.admin_login_of_password_lineEdit = QtWidgets.QLineEdit(self.groupBox_4) 134 | self.admin_login_of_password_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 135 | self.admin_login_of_password_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 136 | font = QtGui.QFont() 137 | font.setPointSize(9) 138 | self.admin_login_of_password_lineEdit.setFont(font) 139 | self.admin_login_of_password_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 140 | "border:none;\n" 141 | "border-bottom:2px solid rgba(46,82,101,200);\n" 142 | "color:rgba(0,0,0,240);\n" 143 | "padding-bottom:2px;") 144 | self.admin_login_of_password_lineEdit.setObjectName("admin_login_of_password_lineEdit") 145 | self.verticalLayout_3.addWidget(self.admin_login_of_password_lineEdit) 146 | self.horizontalLayout_4.addLayout(self.verticalLayout_3) 147 | self.admin_login_pushButton = QtWidgets.QPushButton(self.groupBox_4) 148 | self.admin_login_pushButton.setMinimumSize(QtCore.QSize(90, 30)) 149 | self.admin_login_pushButton.setMaximumSize(QtCore.QSize(90, 30)) 150 | self.admin_login_pushButton.setObjectName("admin_login_pushButton") 151 | self.horizontalLayout_4.addWidget(self.admin_login_pushButton) 152 | self.horizontalLayout_6.addWidget(self.groupBox_4) 153 | self.horizontalLayout_5 = QtWidgets.QHBoxLayout() 154 | self.horizontalLayout_5.setObjectName("horizontalLayout_5") 155 | self.label = QtWidgets.QLabel(self.widget) 156 | font = QtGui.QFont() 157 | font.setFamily("楷体") 158 | font.setPointSize(16) 159 | font.setBold(False) 160 | font.setWeight(50) 161 | self.label.setFont(font) 162 | self.label.setObjectName("label") 163 | self.horizontalLayout_5.addWidget(self.label) 164 | spacerItem = QtWidgets.QSpacerItem(88, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) 165 | self.horizontalLayout_5.addItem(spacerItem) 166 | self.fresh_pushButton = QtWidgets.QPushButton(self.widget) 167 | self.fresh_pushButton.setMinimumSize(QtCore.QSize(130, 45)) 168 | font = QtGui.QFont() 169 | font.setPointSize(11) 170 | self.fresh_pushButton.setFont(font) 171 | self.fresh_pushButton.setObjectName("fresh_pushButton") 172 | self.horizontalLayout_5.addWidget(self.fresh_pushButton) 173 | spacerItem1 = QtWidgets.QSpacerItem(138, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) 174 | self.horizontalLayout_5.addItem(spacerItem1) 175 | self.min_pushButton = QtWidgets.QPushButton(self.widget) 176 | self.min_pushButton.setMinimumSize(QtCore.QSize(20, 20)) 177 | self.min_pushButton.setMaximumSize(QtCore.QSize(20, 20)) 178 | self.min_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 179 | self.min_pushButton.setText("") 180 | self.min_pushButton.setObjectName("min_pushButton") 181 | self.horizontalLayout_5.addWidget(self.min_pushButton) 182 | self.close_pushButton = QtWidgets.QPushButton(self.widget) 183 | self.close_pushButton.setMinimumSize(QtCore.QSize(20, 20)) 184 | self.close_pushButton.setMaximumSize(QtCore.QSize(20, 20)) 185 | self.close_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 186 | self.close_pushButton.setText("") 187 | self.close_pushButton.setObjectName("close_pushButton") 188 | self.horizontalLayout_5.addWidget(self.close_pushButton) 189 | self.horizontalLayout_6.addLayout(self.horizontalLayout_5) 190 | self.verticalLayout_5.addLayout(self.horizontalLayout_6) 191 | self.formLayout_3 = QtWidgets.QFormLayout() 192 | self.formLayout_3.setObjectName("formLayout_3") 193 | self.verticalLayout_4 = QtWidgets.QVBoxLayout() 194 | self.verticalLayout_4.setObjectName("verticalLayout_4") 195 | self.groupBox_2 = QtWidgets.QGroupBox(self.widget) 196 | self.groupBox_2.setMinimumSize(QtCore.QSize(240, 110)) 197 | self.groupBox_2.setMaximumSize(QtCore.QSize(240, 16777215)) 198 | font = QtGui.QFont() 199 | font.setPointSize(11) 200 | self.groupBox_2.setFont(font) 201 | self.groupBox_2.setObjectName("groupBox_2") 202 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_2) 203 | self.horizontalLayout_3.setObjectName("horizontalLayout_3") 204 | self.verticalLayout_2 = QtWidgets.QVBoxLayout() 205 | self.verticalLayout_2.setObjectName("verticalLayout_2") 206 | self.add_user_of_user_name_lineEdit = QtWidgets.QLineEdit(self.groupBox_2) 207 | self.add_user_of_user_name_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 208 | self.add_user_of_user_name_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 209 | font = QtGui.QFont() 210 | font.setPointSize(9) 211 | self.add_user_of_user_name_lineEdit.setFont(font) 212 | self.add_user_of_user_name_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 213 | "border:none;\n" 214 | "border-bottom:2px solid rgba(46,82,101,200);\n" 215 | "color:rgba(0,0,0,240);\n" 216 | "padding-bottom:2px;") 217 | self.add_user_of_user_name_lineEdit.setObjectName("add_user_of_user_name_lineEdit") 218 | self.verticalLayout_2.addWidget(self.add_user_of_user_name_lineEdit) 219 | self.add_user_of_password_lineEdit = QtWidgets.QLineEdit(self.groupBox_2) 220 | self.add_user_of_password_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 221 | self.add_user_of_password_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 222 | font = QtGui.QFont() 223 | font.setPointSize(9) 224 | self.add_user_of_password_lineEdit.setFont(font) 225 | self.add_user_of_password_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 226 | "border:none;\n" 227 | "border-bottom:2px solid rgba(46,82,101,200);\n" 228 | "color:rgba(0,0,0,240);\n" 229 | "padding-bottom:2px;") 230 | self.add_user_of_password_lineEdit.setObjectName("add_user_of_password_lineEdit") 231 | self.verticalLayout_2.addWidget(self.add_user_of_password_lineEdit) 232 | self.horizontalLayout_3.addLayout(self.verticalLayout_2) 233 | self.add_user_pushButton = QtWidgets.QPushButton(self.groupBox_2) 234 | self.add_user_pushButton.setMinimumSize(QtCore.QSize(90, 30)) 235 | self.add_user_pushButton.setMaximumSize(QtCore.QSize(90, 30)) 236 | self.add_user_pushButton.setObjectName("add_user_pushButton") 237 | self.horizontalLayout_3.addWidget(self.add_user_pushButton) 238 | self.verticalLayout_4.addWidget(self.groupBox_2) 239 | self.groupBox = QtWidgets.QGroupBox(self.widget) 240 | self.groupBox.setMinimumSize(QtCore.QSize(240, 80)) 241 | self.groupBox.setMaximumSize(QtCore.QSize(240, 16777215)) 242 | font = QtGui.QFont() 243 | font.setPointSize(11) 244 | self.groupBox.setFont(font) 245 | self.groupBox.setObjectName("groupBox") 246 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox) 247 | self.horizontalLayout_2.setObjectName("horizontalLayout_2") 248 | self.delete_user_of_id_lineEdit = QtWidgets.QLineEdit(self.groupBox) 249 | self.delete_user_of_id_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 250 | self.delete_user_of_id_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 251 | font = QtGui.QFont() 252 | font.setPointSize(9) 253 | self.delete_user_of_id_lineEdit.setFont(font) 254 | self.delete_user_of_id_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 255 | "border:none;\n" 256 | "border-bottom:2px solid rgba(46,82,101,200);\n" 257 | "color:rgba(0,0,0,240);\n" 258 | "padding-bottom:2px;") 259 | self.delete_user_of_id_lineEdit.setText("") 260 | self.delete_user_of_id_lineEdit.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) 261 | self.delete_user_of_id_lineEdit.setObjectName("delete_user_of_id_lineEdit") 262 | self.horizontalLayout_2.addWidget(self.delete_user_of_id_lineEdit) 263 | self.delete_user_pushButton = QtWidgets.QPushButton(self.groupBox) 264 | self.delete_user_pushButton.setMinimumSize(QtCore.QSize(90, 30)) 265 | self.delete_user_pushButton.setMaximumSize(QtCore.QSize(90, 30)) 266 | self.delete_user_pushButton.setObjectName("delete_user_pushButton") 267 | self.horizontalLayout_2.addWidget(self.delete_user_pushButton) 268 | self.verticalLayout_4.addWidget(self.groupBox) 269 | self.groupBox_3 = QtWidgets.QGroupBox(self.widget) 270 | self.groupBox_3.setMinimumSize(QtCore.QSize(240, 160)) 271 | self.groupBox_3.setMaximumSize(QtCore.QSize(240, 16777215)) 272 | font = QtGui.QFont() 273 | font.setPointSize(11) 274 | self.groupBox_3.setFont(font) 275 | self.groupBox_3.setObjectName("groupBox_3") 276 | self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox_3) 277 | self.verticalLayout.setObjectName("verticalLayout") 278 | self.formLayout_2 = QtWidgets.QFormLayout() 279 | self.formLayout_2.setLabelAlignment(QtCore.Qt.AlignCenter) 280 | self.formLayout_2.setFormAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop) 281 | self.formLayout_2.setObjectName("formLayout_2") 282 | self.change_user_of_id_lineEdit = QtWidgets.QLineEdit(self.groupBox_3) 283 | self.change_user_of_id_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 284 | self.change_user_of_id_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 285 | font = QtGui.QFont() 286 | font.setPointSize(9) 287 | self.change_user_of_id_lineEdit.setFont(font) 288 | self.change_user_of_id_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 289 | "border:none;\n" 290 | "border-bottom:2px solid rgba(46,82,101,200);\n" 291 | "color:rgba(0,0,0,240);\n" 292 | "padding-bottom:2px;") 293 | self.change_user_of_id_lineEdit.setObjectName("change_user_of_id_lineEdit") 294 | self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.change_user_of_id_lineEdit) 295 | self.change_user_pushButton = QtWidgets.QPushButton(self.groupBox_3) 296 | self.change_user_pushButton.setMinimumSize(QtCore.QSize(90, 30)) 297 | self.change_user_pushButton.setMaximumSize(QtCore.QSize(90, 30)) 298 | self.change_user_pushButton.setObjectName("change_user_pushButton") 299 | self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.change_user_pushButton) 300 | self.verticalLayout.addLayout(self.formLayout_2) 301 | self.change_user_of_user_name_lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_3) 302 | self.change_user_of_user_name_lineEdit_2.setEnabled(False) 303 | self.change_user_of_user_name_lineEdit_2.setMaximumSize(QtCore.QSize(16777215, 5)) 304 | font = QtGui.QFont() 305 | font.setPointSize(9) 306 | self.change_user_of_user_name_lineEdit_2.setFont(font) 307 | self.change_user_of_user_name_lineEdit_2.setStyleSheet("background-color:rgba(0,0,0,0);\n" 308 | "border:none;\n" 309 | "border-bottom:1px dashed rgba(46,82,101,200);\n" 310 | "color:rgba(0,0,0,240);\n" 311 | "padding-bottom:1px;") 312 | self.change_user_of_user_name_lineEdit_2.setReadOnly(True) 313 | self.change_user_of_user_name_lineEdit_2.setPlaceholderText("") 314 | self.change_user_of_user_name_lineEdit_2.setObjectName("change_user_of_user_name_lineEdit_2") 315 | self.verticalLayout.addWidget(self.change_user_of_user_name_lineEdit_2) 316 | self.formLayout = QtWidgets.QFormLayout() 317 | self.formLayout.setLabelAlignment(QtCore.Qt.AlignCenter) 318 | self.formLayout.setFormAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop) 319 | self.formLayout.setObjectName("formLayout") 320 | self.change_user_of_user_name_lineEdit = QtWidgets.QLineEdit(self.groupBox_3) 321 | self.change_user_of_user_name_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 322 | self.change_user_of_user_name_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 323 | font = QtGui.QFont() 324 | font.setPointSize(9) 325 | self.change_user_of_user_name_lineEdit.setFont(font) 326 | self.change_user_of_user_name_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 327 | "border:none;\n" 328 | "border-bottom:2px solid rgba(46,82,101,200);\n" 329 | "color:rgba(0,0,0,240);\n" 330 | "padding-bottom:1px;") 331 | self.change_user_of_user_name_lineEdit.setObjectName("change_user_of_user_name_lineEdit") 332 | self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.change_user_of_user_name_lineEdit) 333 | self.change_user_of_phone_lineEdit = QtWidgets.QLineEdit(self.groupBox_3) 334 | self.change_user_of_phone_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 335 | self.change_user_of_phone_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 336 | font = QtGui.QFont() 337 | font.setPointSize(9) 338 | self.change_user_of_phone_lineEdit.setFont(font) 339 | self.change_user_of_phone_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 340 | "border:none;\n" 341 | "border-bottom:2px solid rgba(46,82,101,200);\n" 342 | "color:rgba(0,0,0,240);\n" 343 | "padding-bottom:2px;") 344 | self.change_user_of_phone_lineEdit.setObjectName("change_user_of_phone_lineEdit") 345 | self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.change_user_of_phone_lineEdit) 346 | self.change_user_of_email_lineEdit = QtWidgets.QLineEdit(self.groupBox_3) 347 | self.change_user_of_email_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 348 | self.change_user_of_email_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 349 | font = QtGui.QFont() 350 | font.setPointSize(9) 351 | self.change_user_of_email_lineEdit.setFont(font) 352 | self.change_user_of_email_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 353 | "border:none;\n" 354 | "border-bottom:2px solid rgba(46,82,101,200);\n" 355 | "color:rgba(0,0,0,240);\n" 356 | "padding-bottom:2px;") 357 | self.change_user_of_email_lineEdit.setObjectName("change_user_of_email_lineEdit") 358 | self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.change_user_of_email_lineEdit) 359 | self.change_user_of_password_lineEdit = QtWidgets.QLineEdit(self.groupBox_3) 360 | self.change_user_of_password_lineEdit.setMinimumSize(QtCore.QSize(90, 30)) 361 | self.change_user_of_password_lineEdit.setMaximumSize(QtCore.QSize(90, 30)) 362 | font = QtGui.QFont() 363 | font.setPointSize(9) 364 | self.change_user_of_password_lineEdit.setFont(font) 365 | self.change_user_of_password_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 366 | "border:none;\n" 367 | "border-bottom:2px solid rgba(46,82,101,200);\n" 368 | "color:rgba(0,0,0,240);\n" 369 | "padding-bottom:2px;") 370 | self.change_user_of_password_lineEdit.setObjectName("change_user_of_password_lineEdit") 371 | self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.change_user_of_password_lineEdit) 372 | self.verticalLayout.addLayout(self.formLayout) 373 | self.verticalLayout_4.addWidget(self.groupBox_3) 374 | self.formLayout_3.setLayout(0, QtWidgets.QFormLayout.LabelRole, self.verticalLayout_4) 375 | self.tableWidget = QtWidgets.QTableWidget(self.widget) 376 | self.tableWidget.setMinimumSize(QtCore.QSize(600, 400)) 377 | self.tableWidget.setObjectName("tableWidget") 378 | self.tableWidget.setColumnCount(0) 379 | self.tableWidget.setRowCount(0) 380 | self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.tableWidget) 381 | self.verticalLayout_5.addLayout(self.formLayout_3) 382 | self.horizontalLayout.addWidget(self.widget) 383 | 384 | self.retranslateUi(Frame) 385 | QtCore.QMetaObject.connectSlotsByName(Frame) 386 | 387 | def retranslateUi(self, Frame): 388 | _translate = QtCore.QCoreApplication.translate 389 | Frame.setWindowTitle(_translate("Frame", "数据库")) 390 | self.groupBox_4.setTitle(_translate("Frame", "数据管理员登录")) 391 | self.admin_login_of_user_name_lineEdit.setPlaceholderText(_translate("Frame", "管理员用户名")) 392 | self.admin_login_of_password_lineEdit.setPlaceholderText(_translate("Frame", "管理员密码")) 393 | self.admin_login_pushButton.setText(_translate("Frame", "登录")) 394 | self.label.setText(_translate("Frame", "数据库")) 395 | self.fresh_pushButton.setText(_translate("Frame", "查询user表内容")) 396 | self.groupBox_2.setTitle(_translate("Frame", "添加用户")) 397 | self.add_user_of_user_name_lineEdit.setPlaceholderText(_translate("Frame", "用户名")) 398 | self.add_user_of_password_lineEdit.setPlaceholderText(_translate("Frame", "密码")) 399 | self.add_user_pushButton.setText(_translate("Frame", "添加用户")) 400 | self.groupBox.setTitle(_translate("Frame", "删除用户")) 401 | self.delete_user_of_id_lineEdit.setPlaceholderText(_translate("Frame", "用户ID")) 402 | self.delete_user_pushButton.setText(_translate("Frame", "删除用户")) 403 | self.groupBox_3.setTitle(_translate("Frame", "修改用户")) 404 | self.change_user_of_id_lineEdit.setPlaceholderText(_translate("Frame", "需要修改的ID")) 405 | self.change_user_pushButton.setText(_translate("Frame", "修改用户")) 406 | self.change_user_of_user_name_lineEdit.setPlaceholderText(_translate("Frame", "用户名")) 407 | self.change_user_of_phone_lineEdit.setPlaceholderText(_translate("Frame", "手机号")) 408 | self.change_user_of_email_lineEdit.setPlaceholderText(_translate("Frame", "邮箱")) 409 | self.change_user_of_password_lineEdit.setPlaceholderText(_translate("Frame", "密码")) 410 | from res import app_rc 411 | -------------------------------------------------------------------------------- /ui/mysql_form.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Frame 4 | 5 | 6 | 7 | 0 8 | 0 9 | 980 10 | 568 11 | 12 | 13 | 14 | 15 | 980 16 | 0 17 | 18 | 19 | 20 | 数据库 21 | 22 | 23 | 24 | :/icon/icon/首页.ico:/icon/icon/首页.ico 25 | 26 | 27 | QPushButton#close_pushButton{ 28 | background-color: #ce5137; 29 | border-radius:10px; 30 | } 31 | 32 | QPushButton#close_pushButton:hover{ 33 | background-size: cover; 34 | background-image: url(:/icon/icon/close.svg); 35 | } 36 | 37 | QPushButton#min_pushButton{ 38 | background-color: #a1c661; 39 | border-radius:10px; 40 | } 41 | 42 | QPushButton#min_pushButton:hover{ 43 | background-size: cover; 44 | background-image: url(:/icon/icon/minimize.svg); 45 | } 46 | 47 | QWidget#widget{ 48 | background-color: qlineargradient(spread:pad, x1:0.5, y1:0, x2:0.5, y2:1, stop:0.0284091 rgba(129, 255, 251, 255), stop:0.9375 rgba(255, 255, 255, 255)); 49 | 50 | border-radius: 14; 51 | } 52 | 53 | QTableWidget, QTableView 54 | { 55 | gridline-color: #999999; /*表格中的网格线条颜色*/ 56 | background: #FDFDFD; 57 | /*设置交替颜色,需要在函数属性中设置:tableWidget->setAlternatingRowColors(true)*/ 58 | alternate-background-color: #EEEEEF; 59 | /*selection-color:#FDFDFD; 鼠标选中时前景色:文字颜色*/ 60 | selection-background-color:#8BF; /*鼠标选中时背景色*/ 61 | border:1px solid #999999; /*边框线的宽度、颜色*/ 62 | /*border:none; 去除边界线*/ 63 | /*border-radius:5px;*/ 64 | /*padding:10px 10px;*/ /*表格与边框的间距*/ 65 | } 66 | QTableView::item, QTabWidget::item{ 67 | background: transparent; 68 | outline-style: none; 69 | border: none; 70 | } 71 | 72 | QTableView::item:hover { 73 | background: #8BF; 74 | border: 1px solid #EA2; 75 | } 76 | 77 | QTableView::item:selected { 78 | background: #8BF; 79 | color: #EEEEEF; 80 | } 81 | 82 | QTableView::item:selected:active { 83 | background: #59F; 84 | color: #EEEEEF; 85 | } 86 | 87 | QTableWidget QComboBox{ 88 | margin: 2px; 89 | border: none; 90 | } 91 | 92 | 93 | QGroupBox { 94 | border: 2px solid #999999; 95 | border-radius: 4px; 96 | margin-top: 0.5em; 97 | } 98 | QGroupBox::title { 99 | subcontrol-origin: margin; 100 | subcontrol-position: top left; 101 | left: 1em; 102 | top: 0.1em; 103 | } 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 950 112 | 550 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 240 123 | 110 124 | 125 | 126 | 127 | 128 | 240 129 | 16777215 130 | 131 | 132 | 133 | 134 | 11 135 | 136 | 137 | 138 | 数据管理员登录 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 90 148 | 30 149 | 150 | 151 | 152 | 153 | 90 154 | 30 155 | 156 | 157 | 158 | 159 | 9 160 | 161 | 162 | 163 | background-color:rgba(0,0,0,0); 164 | border:none; 165 | border-bottom:2px solid rgba(46,82,101,200); 166 | color:rgba(0,0,0,240); 167 | padding-bottom:2px; 168 | 169 | 170 | 管理员用户名 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 90 179 | 30 180 | 181 | 182 | 183 | 184 | 90 185 | 30 186 | 187 | 188 | 189 | 190 | 9 191 | 192 | 193 | 194 | background-color:rgba(0,0,0,0); 195 | border:none; 196 | border-bottom:2px solid rgba(46,82,101,200); 197 | color:rgba(0,0,0,240); 198 | padding-bottom:2px; 199 | 200 | 201 | 管理员密码 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 90 212 | 30 213 | 214 | 215 | 216 | 217 | 90 218 | 30 219 | 220 | 221 | 222 | 登录 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 楷体 236 | 16 237 | 50 238 | false 239 | 240 | 241 | 242 | 数据库 243 | 244 | 245 | 246 | 247 | 248 | 249 | Qt::Horizontal 250 | 251 | 252 | 253 | 88 254 | 20 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 130 264 | 45 265 | 266 | 267 | 268 | 269 | 11 270 | 271 | 272 | 273 | 查询user表内容 274 | 275 | 276 | 277 | 278 | 279 | 280 | Qt::Horizontal 281 | 282 | 283 | 284 | 138 285 | 20 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 20 295 | 20 296 | 297 | 298 | 299 | 300 | 20 301 | 20 302 | 303 | 304 | 305 | PointingHandCursor 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 20 317 | 20 318 | 319 | 320 | 321 | 322 | 20 323 | 20 324 | 325 | 326 | 327 | PointingHandCursor 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 240 347 | 110 348 | 349 | 350 | 351 | 352 | 240 353 | 16777215 354 | 355 | 356 | 357 | 358 | 11 359 | 360 | 361 | 362 | 添加用户 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 90 372 | 30 373 | 374 | 375 | 376 | 377 | 90 378 | 30 379 | 380 | 381 | 382 | 383 | 9 384 | 385 | 386 | 387 | background-color:rgba(0,0,0,0); 388 | border:none; 389 | border-bottom:2px solid rgba(46,82,101,200); 390 | color:rgba(0,0,0,240); 391 | padding-bottom:2px; 392 | 393 | 394 | 用户名 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 90 403 | 30 404 | 405 | 406 | 407 | 408 | 90 409 | 30 410 | 411 | 412 | 413 | 414 | 9 415 | 416 | 417 | 418 | background-color:rgba(0,0,0,0); 419 | border:none; 420 | border-bottom:2px solid rgba(46,82,101,200); 421 | color:rgba(0,0,0,240); 422 | padding-bottom:2px; 423 | 424 | 425 | 密码 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 90 436 | 30 437 | 438 | 439 | 440 | 441 | 90 442 | 30 443 | 444 | 445 | 446 | 添加用户 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 240 458 | 80 459 | 460 | 461 | 462 | 463 | 240 464 | 16777215 465 | 466 | 467 | 468 | 469 | 11 470 | 471 | 472 | 473 | 删除用户 474 | 475 | 476 | 477 | 478 | 479 | 480 | 90 481 | 30 482 | 483 | 484 | 485 | 486 | 90 487 | 30 488 | 489 | 490 | 491 | 492 | 9 493 | 494 | 495 | 496 | background-color:rgba(0,0,0,0); 497 | border:none; 498 | border-bottom:2px solid rgba(46,82,101,200); 499 | color:rgba(0,0,0,240); 500 | padding-bottom:2px; 501 | 502 | 503 | 504 | 505 | 506 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 507 | 508 | 509 | 用户ID 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 90 518 | 30 519 | 520 | 521 | 522 | 523 | 90 524 | 30 525 | 526 | 527 | 528 | 删除用户 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 240 540 | 160 541 | 542 | 543 | 544 | 545 | 240 546 | 16777215 547 | 548 | 549 | 550 | 551 | 11 552 | 553 | 554 | 555 | 修改用户 556 | 557 | 558 | 559 | 560 | 561 | Qt::AlignCenter 562 | 563 | 564 | Qt::AlignHCenter|Qt::AlignTop 565 | 566 | 567 | 568 | 569 | 570 | 90 571 | 30 572 | 573 | 574 | 575 | 576 | 90 577 | 30 578 | 579 | 580 | 581 | 582 | 9 583 | 584 | 585 | 586 | background-color:rgba(0,0,0,0); 587 | border:none; 588 | border-bottom:2px solid rgba(46,82,101,200); 589 | color:rgba(0,0,0,240); 590 | padding-bottom:2px; 591 | 592 | 593 | 需要修改的ID 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 90 602 | 30 603 | 604 | 605 | 606 | 607 | 90 608 | 30 609 | 610 | 611 | 612 | 修改用户 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | false 622 | 623 | 624 | 625 | 16777215 626 | 5 627 | 628 | 629 | 630 | 631 | 9 632 | 633 | 634 | 635 | background-color:rgba(0,0,0,0); 636 | border:none; 637 | border-bottom:1px dashed rgba(46,82,101,200); 638 | color:rgba(0,0,0,240); 639 | padding-bottom:1px; 640 | 641 | 642 | true 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | Qt::AlignCenter 653 | 654 | 655 | Qt::AlignHCenter|Qt::AlignTop 656 | 657 | 658 | 659 | 660 | 661 | 90 662 | 30 663 | 664 | 665 | 666 | 667 | 90 668 | 30 669 | 670 | 671 | 672 | 673 | 9 674 | 675 | 676 | 677 | background-color:rgba(0,0,0,0); 678 | border:none; 679 | border-bottom:2px solid rgba(46,82,101,200); 680 | color:rgba(0,0,0,240); 681 | padding-bottom:1px; 682 | 683 | 684 | 用户名 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 90 693 | 30 694 | 695 | 696 | 697 | 698 | 90 699 | 30 700 | 701 | 702 | 703 | 704 | 9 705 | 706 | 707 | 708 | background-color:rgba(0,0,0,0); 709 | border:none; 710 | border-bottom:2px solid rgba(46,82,101,200); 711 | color:rgba(0,0,0,240); 712 | padding-bottom:2px; 713 | 714 | 715 | 手机号 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 90 724 | 30 725 | 726 | 727 | 728 | 729 | 90 730 | 30 731 | 732 | 733 | 734 | 735 | 9 736 | 737 | 738 | 739 | background-color:rgba(0,0,0,0); 740 | border:none; 741 | border-bottom:2px solid rgba(46,82,101,200); 742 | color:rgba(0,0,0,240); 743 | padding-bottom:2px; 744 | 745 | 746 | 邮箱 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 90 755 | 30 756 | 757 | 758 | 759 | 760 | 90 761 | 30 762 | 763 | 764 | 765 | 766 | 9 767 | 768 | 769 | 770 | background-color:rgba(0,0,0,0); 771 | border:none; 772 | border-bottom:2px solid rgba(46,82,101,200); 773 | color:rgba(0,0,0,240); 774 | padding-bottom:2px; 775 | 776 | 777 | 密码 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 600 793 | 400 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | -------------------------------------------------------------------------------- /ui/register_form.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'ui/register_form.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.15.4 6 | # 7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is 8 | # run again. Do not edit this file unless you know what you are doing. 9 | 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | 13 | 14 | class Ui_Frame(object): 15 | def setupUi(self, Frame): 16 | Frame.setObjectName("Frame") 17 | Frame.resize(621, 602) 18 | icon = QtGui.QIcon() 19 | icon.addPixmap(QtGui.QPixmap(":/icon/icon/首页.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 20 | Frame.setWindowIcon(icon) 21 | self.widget = QtWidgets.QWidget(Frame) 22 | self.widget.setGeometry(QtCore.QRect(30, 30, 550, 550)) 23 | self.widget.setStyleSheet("QPushButton#register_pushButton{\n" 24 | " background-color:qlineargradient(spread:pad,x1:0,y1:0.505682,x2:1,y2:0.477,stop:0 rgba(11,131,120,219),stop:1 rgba(85,98,112,226));\n" 25 | " color:rgba(255,255,255,210);\n" 26 | " border-radius:5px;\n" 27 | "}\n" 28 | "\n" 29 | "QPushButton#register_pushButton:hover{\n" 30 | " background-color:qlineargradient(spread:pad,x1:0,y1:0.505682,x2:1,y2:0.477,stop:0 rgba(150,123,1111,219),stop:1 rgba(85,81,84,226));\n" 31 | "}\n" 32 | "\n" 33 | "QPushButton#register_pushButton:pressed{\n" 34 | " padding-left:5px;\n" 35 | " padding-top:5px;\n" 36 | " background-color:rgba(150,123,111,255);\n" 37 | "}\n" 38 | "\n" 39 | "QPushButton#forget_password_pushButton,#register_pushButton{\n" 40 | " background-color:rgba(0,0,0,0);\n" 41 | " border:none;\n" 42 | " border-bottom:1px solid rgb(179, 179, 179);\n" 43 | " color:rgba(0,0,0,240);\n" 44 | "}\n" 45 | "\n" 46 | "QPushButton#github_pushButton,#phone_pushButton,#email_pushButton{\n" 47 | " background-color:rgba(0,0,0,0);\n" 48 | " color:rgba(85,98,112,255);\n" 49 | "}\n" 50 | "\n" 51 | "QPushButton#github_pushButton:hover,#phone_pushButton:hover,#email_pushButton:hover{\n" 52 | " color:rgba(131,96,53,255);\n" 53 | "}\n" 54 | "\n" 55 | "QPushButton#github_pushButton:pressed,#phone_pushButton:pressed,#email_pushButton:pressed{\n" 56 | " padding-left:5px;\n" 57 | " padding-top:5px;\n" 58 | " color:rgba(91,88,53,255);\n" 59 | "}\n" 60 | "\n" 61 | "QPushButton#close_pushButton{\n" 62 | " background-color: #ce5137;\n" 63 | " border-radius:10px;\n" 64 | "}\n" 65 | "\n" 66 | "QPushButton#close_pushButton:hover{\n" 67 | " background-size: cover;\n" 68 | " background-image: url(:/icon/icon/close.svg);\n" 69 | "}\n" 70 | "\n" 71 | "QPushButton#min_pushButton{\n" 72 | " background-color: #a1c661;\n" 73 | " border-radius:10px;\n" 74 | "}\n" 75 | "\n" 76 | "QPushButton#min_pushButton:hover{\n" 77 | " background-size: cover;\n" 78 | " background-image: url(:/icon/icon/minimize.svg);\n" 79 | "}\n" 80 | "") 81 | self.widget.setObjectName("widget") 82 | self.label = QtWidgets.QLabel(self.widget) 83 | self.label.setGeometry(QtCore.QRect(40, 30, 280, 430)) 84 | self.label.setStyleSheet("border-image: url(:/img/image/register.jpg);\n" 85 | "border-top-left-radius:50px;") 86 | self.label.setObjectName("label") 87 | self.label_2 = QtWidgets.QLabel(self.widget) 88 | self.label_2.setGeometry(QtCore.QRect(40, 30, 280, 430)) 89 | self.label_2.setStyleSheet("background-color:rgba(0,0,0,80);\n" 90 | "border-top-left-radius:50px;") 91 | self.label_2.setText("") 92 | self.label_2.setObjectName("label_2") 93 | self.label_3 = QtWidgets.QLabel(self.widget) 94 | self.label_3.setGeometry(QtCore.QRect(270, 30, 240, 430)) 95 | self.label_3.setStyleSheet("background-color:rgba(255,255,255,255);\n" 96 | "border-bottom-right-radius:50px;") 97 | self.label_3.setText("") 98 | self.label_3.setObjectName("label_3") 99 | self.label_4 = QtWidgets.QLabel(self.widget) 100 | self.label_4.setGeometry(QtCore.QRect(300, 80, 180, 40)) 101 | self.label_4.setMinimumSize(QtCore.QSize(180, 40)) 102 | self.label_4.setMaximumSize(QtCore.QSize(180, 40)) 103 | font = QtGui.QFont() 104 | font.setFamily("楷体") 105 | font.setPointSize(20) 106 | font.setBold(True) 107 | font.setWeight(75) 108 | self.label_4.setFont(font) 109 | self.label_4.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) 110 | self.label_4.setStyleSheet("color:rgba(0,0,0,200);") 111 | self.label_4.setAlignment(QtCore.Qt.AlignCenter) 112 | self.label_4.setObjectName("label_4") 113 | self.user_name_lineEdit = QtWidgets.QLineEdit(self.widget) 114 | self.user_name_lineEdit.setGeometry(QtCore.QRect(295, 150, 190, 40)) 115 | self.user_name_lineEdit.setMinimumSize(QtCore.QSize(190, 40)) 116 | self.user_name_lineEdit.setMaximumSize(QtCore.QSize(190, 40)) 117 | font = QtGui.QFont() 118 | font.setFamily("华文楷体") 119 | font.setPointSize(15) 120 | self.user_name_lineEdit.setFont(font) 121 | self.user_name_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 122 | "border:none;\n" 123 | "border-bottom:2px solid rgba(46,82,101,200);\n" 124 | "color:rgba(0,0,0,240);\n" 125 | "padding-bottom:7px;") 126 | self.user_name_lineEdit.setObjectName("user_name_lineEdit") 127 | self.password_lineEdit = QtWidgets.QLineEdit(self.widget) 128 | self.password_lineEdit.setGeometry(QtCore.QRect(295, 200, 190, 40)) 129 | self.password_lineEdit.setMinimumSize(QtCore.QSize(190, 40)) 130 | self.password_lineEdit.setMaximumSize(QtCore.QSize(190, 40)) 131 | font = QtGui.QFont() 132 | font.setFamily("华文楷体") 133 | font.setPointSize(15) 134 | self.password_lineEdit.setFont(font) 135 | self.password_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 136 | "border:none;\n" 137 | "border-bottom:2px solid rgba(46,82,101,200);\n" 138 | "color:rgba(0,0,0,240);\n" 139 | "padding-bottom:7px;") 140 | self.password_lineEdit.setEchoMode(QtWidgets.QLineEdit.Password) 141 | self.password_lineEdit.setObjectName("password_lineEdit") 142 | self.register_pushButton = QtWidgets.QPushButton(self.widget) 143 | self.register_pushButton.setGeometry(QtCore.QRect(295, 330, 190, 40)) 144 | self.register_pushButton.setMinimumSize(QtCore.QSize(190, 40)) 145 | self.register_pushButton.setMaximumSize(QtCore.QSize(190, 40)) 146 | font = QtGui.QFont() 147 | font.setFamily("华文楷体") 148 | font.setPointSize(20) 149 | font.setBold(True) 150 | font.setWeight(75) 151 | self.register_pushButton.setFont(font) 152 | self.register_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 153 | self.register_pushButton.setObjectName("register_pushButton") 154 | self.horizontalLayoutWidget = QtWidgets.QWidget(self.widget) 155 | self.horizontalLayoutWidget.setGeometry(QtCore.QRect(300, 390, 171, 32)) 156 | self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") 157 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget) 158 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0) 159 | self.horizontalLayout.setSpacing(0) 160 | self.horizontalLayout.setObjectName("horizontalLayout") 161 | self.github_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget) 162 | self.github_pushButton.setMinimumSize(QtCore.QSize(30, 30)) 163 | self.github_pushButton.setMaximumSize(QtCore.QSize(30, 30)) 164 | font = QtGui.QFont() 165 | font.setFamily("Social Media Circled") 166 | font.setPointSize(15) 167 | self.github_pushButton.setFont(font) 168 | self.github_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 169 | self.github_pushButton.setStyleSheet("") 170 | self.github_pushButton.setObjectName("github_pushButton") 171 | self.horizontalLayout.addWidget(self.github_pushButton) 172 | self.phone_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget) 173 | self.phone_pushButton.setMinimumSize(QtCore.QSize(30, 30)) 174 | self.phone_pushButton.setMaximumSize(QtCore.QSize(30, 30)) 175 | font = QtGui.QFont() 176 | font.setFamily("Social Media Circled") 177 | font.setPointSize(15) 178 | self.phone_pushButton.setFont(font) 179 | self.phone_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 180 | self.phone_pushButton.setStyleSheet("") 181 | self.phone_pushButton.setObjectName("phone_pushButton") 182 | self.horizontalLayout.addWidget(self.phone_pushButton) 183 | self.email_pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget) 184 | self.email_pushButton.setMinimumSize(QtCore.QSize(30, 30)) 185 | self.email_pushButton.setMaximumSize(QtCore.QSize(30, 30)) 186 | font = QtGui.QFont() 187 | font.setFamily("Social Media Circled") 188 | font.setPointSize(15) 189 | self.email_pushButton.setFont(font) 190 | self.email_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 191 | self.email_pushButton.setStyleSheet("") 192 | self.email_pushButton.setObjectName("email_pushButton") 193 | self.horizontalLayout.addWidget(self.email_pushButton) 194 | self.min_pushButton = QtWidgets.QPushButton(self.widget) 195 | self.min_pushButton.setGeometry(QtCore.QRect(455, 40, 20, 20)) 196 | self.min_pushButton.setMinimumSize(QtCore.QSize(20, 20)) 197 | self.min_pushButton.setMaximumSize(QtCore.QSize(20, 20)) 198 | self.min_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 199 | self.min_pushButton.setText("") 200 | self.min_pushButton.setObjectName("min_pushButton") 201 | self.close_pushButton = QtWidgets.QPushButton(self.widget) 202 | self.close_pushButton.setGeometry(QtCore.QRect(480, 40, 20, 20)) 203 | self.close_pushButton.setMinimumSize(QtCore.QSize(20, 20)) 204 | self.close_pushButton.setMaximumSize(QtCore.QSize(20, 20)) 205 | self.close_pushButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 206 | self.close_pushButton.setText("") 207 | self.close_pushButton.setObjectName("close_pushButton") 208 | self.password2_lineEdit = QtWidgets.QLineEdit(self.widget) 209 | self.password2_lineEdit.setGeometry(QtCore.QRect(295, 250, 190, 40)) 210 | self.password2_lineEdit.setMinimumSize(QtCore.QSize(190, 40)) 211 | self.password2_lineEdit.setMaximumSize(QtCore.QSize(190, 40)) 212 | font = QtGui.QFont() 213 | font.setFamily("华文楷体") 214 | font.setPointSize(15) 215 | self.password2_lineEdit.setFont(font) 216 | self.password2_lineEdit.setStyleSheet("background-color:rgba(0,0,0,0);\n" 217 | "border:none;\n" 218 | "border-bottom:2px solid rgba(46,82,101,200);\n" 219 | "color:rgba(0,0,0,240);\n" 220 | "padding-bottom:7px;") 221 | self.password2_lineEdit.setEchoMode(QtWidgets.QLineEdit.Password) 222 | self.password2_lineEdit.setObjectName("password2_lineEdit") 223 | self.regsiter_res_label = QtWidgets.QLabel(self.widget) 224 | self.regsiter_res_label.setGeometry(QtCore.QRect(295, 290, 191, 31)) 225 | font = QtGui.QFont() 226 | font.setFamily("华文楷体") 227 | font.setPointSize(10) 228 | self.regsiter_res_label.setFont(font) 229 | self.regsiter_res_label.setText("") 230 | self.regsiter_res_label.setObjectName("regsiter_res_label") 231 | 232 | self.retranslateUi(Frame) 233 | QtCore.QMetaObject.connectSlotsByName(Frame) 234 | 235 | def retranslateUi(self, Frame): 236 | _translate = QtCore.QCoreApplication.translate 237 | Frame.setWindowTitle(_translate("Frame", "Frame")) 238 | self.label.setText(_translate("Frame", "TextLabel")) 239 | self.label_4.setText(_translate("Frame", "注册界面")) 240 | self.user_name_lineEdit.setPlaceholderText(_translate("Frame", "用户名")) 241 | self.password_lineEdit.setPlaceholderText(_translate("Frame", "密码")) 242 | self.register_pushButton.setText(_translate("Frame", "注册")) 243 | self.github_pushButton.setText(_translate("Frame", ")")) 244 | self.phone_pushButton.setText(_translate("Frame", "#")) 245 | self.email_pushButton.setText(_translate("Frame", "k")) 246 | self.password2_lineEdit.setPlaceholderText(_translate("Frame", "再次输入密码")) 247 | from res import app_rc 248 | -------------------------------------------------------------------------------- /ui/register_form.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Frame 4 | 5 | 6 | 7 | 0 8 | 0 9 | 621 10 | 602 11 | 12 | 13 | 14 | Frame 15 | 16 | 17 | 18 | :/icon/icon/首页.ico:/icon/icon/首页.ico 19 | 20 | 21 | 22 | 23 | 30 24 | 30 25 | 550 26 | 550 27 | 28 | 29 | 30 | QPushButton#register_pushButton{ 31 | background-color:qlineargradient(spread:pad,x1:0,y1:0.505682,x2:1,y2:0.477,stop:0 rgba(11,131,120,219),stop:1 rgba(85,98,112,226)); 32 | color:rgba(255,255,255,210); 33 | border-radius:5px; 34 | } 35 | 36 | QPushButton#register_pushButton:hover{ 37 | background-color:qlineargradient(spread:pad,x1:0,y1:0.505682,x2:1,y2:0.477,stop:0 rgba(150,123,1111,219),stop:1 rgba(85,81,84,226)); 38 | } 39 | 40 | QPushButton#register_pushButton:pressed{ 41 | padding-left:5px; 42 | padding-top:5px; 43 | background-color:rgba(150,123,111,255); 44 | } 45 | 46 | QPushButton#forget_password_pushButton,#register_pushButton{ 47 | background-color:rgba(0,0,0,0); 48 | border:none; 49 | border-bottom:1px solid rgb(179, 179, 179); 50 | color:rgba(0,0,0,240); 51 | } 52 | 53 | QPushButton#github_pushButton,#phone_pushButton,#email_pushButton{ 54 | background-color:rgba(0,0,0,0); 55 | color:rgba(85,98,112,255); 56 | } 57 | 58 | QPushButton#github_pushButton:hover,#phone_pushButton:hover,#email_pushButton:hover{ 59 | color:rgba(131,96,53,255); 60 | } 61 | 62 | QPushButton#github_pushButton:pressed,#phone_pushButton:pressed,#email_pushButton:pressed{ 63 | padding-left:5px; 64 | padding-top:5px; 65 | color:rgba(91,88,53,255); 66 | } 67 | 68 | QPushButton#close_pushButton{ 69 | background-color: #ce5137; 70 | border-radius:10px; 71 | } 72 | 73 | QPushButton#close_pushButton:hover{ 74 | background-size: cover; 75 | background-image: url(:/icon/icon/close.svg); 76 | } 77 | 78 | QPushButton#min_pushButton{ 79 | background-color: #a1c661; 80 | border-radius:10px; 81 | } 82 | 83 | QPushButton#min_pushButton:hover{ 84 | background-size: cover; 85 | background-image: url(:/icon/icon/minimize.svg); 86 | } 87 | 88 | 89 | 90 | 91 | 92 | 40 93 | 30 94 | 280 95 | 430 96 | 97 | 98 | 99 | border-image: url(:/img/image/register.jpg); 100 | border-top-left-radius:50px; 101 | 102 | 103 | TextLabel 104 | 105 | 106 | 107 | 108 | 109 | 40 110 | 30 111 | 280 112 | 430 113 | 114 | 115 | 116 | background-color:rgba(0,0,0,80); 117 | border-top-left-radius:50px; 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 270 127 | 30 128 | 240 129 | 430 130 | 131 | 132 | 133 | background-color:rgba(255,255,255,255); 134 | border-bottom-right-radius:50px; 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 300 144 | 80 145 | 180 146 | 40 147 | 148 | 149 | 150 | 151 | 180 152 | 40 153 | 154 | 155 | 156 | 157 | 180 158 | 40 159 | 160 | 161 | 162 | 163 | 楷体 164 | 20 165 | 75 166 | true 167 | 168 | 169 | 170 | ArrowCursor 171 | 172 | 173 | color:rgba(0,0,0,200); 174 | 175 | 176 | 注册界面 177 | 178 | 179 | Qt::AlignCenter 180 | 181 | 182 | 183 | 184 | 185 | 295 186 | 150 187 | 190 188 | 40 189 | 190 | 191 | 192 | 193 | 190 194 | 40 195 | 196 | 197 | 198 | 199 | 190 200 | 40 201 | 202 | 203 | 204 | 205 | 华文楷体 206 | 15 207 | 208 | 209 | 210 | background-color:rgba(0,0,0,0); 211 | border:none; 212 | border-bottom:2px solid rgba(46,82,101,200); 213 | color:rgba(0,0,0,240); 214 | padding-bottom:7px; 215 | 216 | 217 | 用户名 218 | 219 | 220 | 221 | 222 | 223 | 295 224 | 200 225 | 190 226 | 40 227 | 228 | 229 | 230 | 231 | 190 232 | 40 233 | 234 | 235 | 236 | 237 | 190 238 | 40 239 | 240 | 241 | 242 | 243 | 华文楷体 244 | 15 245 | 246 | 247 | 248 | background-color:rgba(0,0,0,0); 249 | border:none; 250 | border-bottom:2px solid rgba(46,82,101,200); 251 | color:rgba(0,0,0,240); 252 | padding-bottom:7px; 253 | 254 | 255 | QLineEdit::Password 256 | 257 | 258 | 密码 259 | 260 | 261 | 262 | 263 | 264 | 295 265 | 330 266 | 190 267 | 40 268 | 269 | 270 | 271 | 272 | 190 273 | 40 274 | 275 | 276 | 277 | 278 | 190 279 | 40 280 | 281 | 282 | 283 | 284 | 华文楷体 285 | 20 286 | 75 287 | true 288 | 289 | 290 | 291 | PointingHandCursor 292 | 293 | 294 | 注册 295 | 296 | 297 | 298 | 299 | 300 | 300 301 | 390 302 | 171 303 | 32 304 | 305 | 306 | 307 | 308 | 0 309 | 310 | 311 | 312 | 313 | 314 | 30 315 | 30 316 | 317 | 318 | 319 | 320 | 30 321 | 30 322 | 323 | 324 | 325 | 326 | Social Media Circled 327 | 15 328 | 329 | 330 | 331 | PointingHandCursor 332 | 333 | 334 | 335 | 336 | 337 | ) 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 30 346 | 30 347 | 348 | 349 | 350 | 351 | 30 352 | 30 353 | 354 | 355 | 356 | 357 | Social Media Circled 358 | 15 359 | 360 | 361 | 362 | PointingHandCursor 363 | 364 | 365 | 366 | 367 | 368 | # 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 30 377 | 30 378 | 379 | 380 | 381 | 382 | 30 383 | 30 384 | 385 | 386 | 387 | 388 | Social Media Circled 389 | 15 390 | 391 | 392 | 393 | PointingHandCursor 394 | 395 | 396 | 397 | 398 | 399 | k 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 455 409 | 40 410 | 20 411 | 20 412 | 413 | 414 | 415 | 416 | 20 417 | 20 418 | 419 | 420 | 421 | 422 | 20 423 | 20 424 | 425 | 426 | 427 | PointingHandCursor 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 480 437 | 40 438 | 20 439 | 20 440 | 441 | 442 | 443 | 444 | 20 445 | 20 446 | 447 | 448 | 449 | 450 | 20 451 | 20 452 | 453 | 454 | 455 | PointingHandCursor 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 295 465 | 250 466 | 190 467 | 40 468 | 469 | 470 | 471 | 472 | 190 473 | 40 474 | 475 | 476 | 477 | 478 | 190 479 | 40 480 | 481 | 482 | 483 | 484 | 华文楷体 485 | 15 486 | 487 | 488 | 489 | background-color:rgba(0,0,0,0); 490 | border:none; 491 | border-bottom:2px solid rgba(46,82,101,200); 492 | color:rgba(0,0,0,240); 493 | padding-bottom:7px; 494 | 495 | 496 | QLineEdit::Password 497 | 498 | 499 | 再次输入密码 500 | 501 | 502 | 503 | 504 | 505 | 295 506 | 290 507 | 191 508 | 31 509 | 510 | 511 | 512 | 513 | 华文楷体 514 | 10 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | -------------------------------------------------------------------------------- /ui_to_py.bat: -------------------------------------------------------------------------------- 1 | call C:\DevelopmentTools\Miniconda3\miniconda3\Scripts\activate.bat C:\DevelopmentTools\Miniconda3\miniconda3\envs\learn_pyqt5 2 | pyrcc5 res/app.qrc -o res/app_rc.py 3 | python -m PyQt5.uic.pyuic ui/main_window.ui -o ui/main_window.py --import-from=res 4 | python -m PyQt5.uic.pyuic ui/login_form.ui -o ui/login_form.py --import-from=res 5 | python -m PyQt5.uic.pyuic ui/register_form.ui -o ui/register_form.py --import-from=res 6 | python -m PyQt5.uic.pyuic ui/mysql_form.ui -o ui/mysql_form.py --import-from=res 7 | python -m PyQt5.uic.pyuic ui/close_dialog.ui -o ui/close_dialog.py --import-from=res -------------------------------------------------------------------------------- /utils/CommonHelper.py: -------------------------------------------------------------------------------- 1 | class CommonHelper: 2 | def __init__(self): 3 | pass 4 | 5 | @staticmethod 6 | def read_qss_file(qss_file="./config/skin/white.qss"): 7 | with open(qss_file, 'r', encoding='utf-8') as f: 8 | return f.read() 9 | -------------------------------------------------------------------------------- /utils/connect_mysql.py: -------------------------------------------------------------------------------- 1 | from peewee import _ConnectionState, Model, DateTimeField, IntegerField 2 | from contextvars import ContextVar 3 | from playhouse.pool import PooledMySQLDatabase 4 | 5 | from config.config import settings 6 | 7 | db_state_default = {"closed": None, "conn": None, "ctx": None, "transactions": None} 8 | db_state = ContextVar("db_state", default=db_state_default.copy()) 9 | 10 | 11 | class PeeweeConnectionState(_ConnectionState): 12 | def __init__(self, **kwargs): 13 | super().__setattr__("_state", db_state) 14 | super().__init__(**kwargs) 15 | 16 | def __setattr__(self, name, value): 17 | self._state.get()[name] = value 18 | 19 | def __getattr__(self, name): 20 | return self._state.get()[name] 21 | 22 | 23 | db = PooledMySQLDatabase( 24 | settings.MYSQL_DATABASE, 25 | max_connections=8, 26 | stale_timeout=300, 27 | user=settings.MYSQL_USERNAME, 28 | host=settings.MYSQL_HOST, 29 | password=settings.MYSQL_PASSWORD, 30 | port=settings.MYSQL_PORT 31 | ) 32 | 33 | db._state = PeeweeConnectionState() 34 | 35 | 36 | class BaseModel(Model): 37 | id = IntegerField() 38 | gmt_created = DateTimeField() 39 | gmt_modified = DateTimeField() 40 | 41 | class Meta: 42 | database = db 43 | -------------------------------------------------------------------------------- /utils/global_var.py: -------------------------------------------------------------------------------- 1 | # 全局变量管理模块 2 | def __init(): 3 | global _global_dict 4 | _global_dict = {} 5 | 6 | 7 | def set_value(name, value): 8 | _global_dict[name] = value 9 | 10 | 11 | def get_value(name, default_value=None): 12 | return _global_dict.get(name, default_value) 13 | -------------------------------------------------------------------------------- /utils/logs.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import sys 3 | from loguru import logger 4 | 5 | 6 | # import matplotlib.pyplot as plt 7 | # plt.set_loglevel('WARNING') 8 | 9 | # 日志模块 10 | 11 | class InterceptHandler(logging.Handler): 12 | def emit(self, record: logging.LogRecord) -> None: # pragma: no cover 13 | logger_opt = logger.opt(depth=7, exception=record.exc_info) 14 | logger_opt.log(record.levelname, record.getMessage()) 15 | 16 | 17 | def setting(): 18 | # logging configuration 19 | LOGGING_LEVEL = logging.DEBUG 20 | logging.basicConfig( 21 | handlers=[InterceptHandler(level=LOGGING_LEVEL)], level=LOGGING_LEVEL 22 | ) 23 | logger.configure(handlers=[{"sink": sys.stderr, "level": LOGGING_LEVEL}]) 24 | -------------------------------------------------------------------------------- /win/close_dialog.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore 2 | from PyQt5.QtWidgets import QDialog, QMainWindow, QDialogButtonBox, QApplication 3 | from loguru import logger 4 | 5 | from ui.close_dialog import Ui_Dialog as c_dialog 6 | 7 | 8 | class close_dialog(QDialog, c_dialog): 9 | def __init__(self, parent: QMainWindow = None): 10 | super(close_dialog, self).__init__() 11 | self.setupUi(self) 12 | self.root = parent 13 | 14 | # 隐藏原始的框,关闭缩小按钮事件绑定 15 | self.setWindowFlag(QtCore.Qt.FramelessWindowHint) 16 | self.setAttribute(QtCore.Qt.WA_TranslucentBackground) 17 | self.close_pushButton.clicked.connect(self.close_event) 18 | self.min_pushButton.clicked.connect(self.showMinimized) 19 | 20 | # ok 按钮事件绑定 21 | self.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.ok_event) 22 | 23 | # 关闭的逻辑 24 | def close_event(self): 25 | logger.info("关闭dialog窗口") 26 | # 直接关闭的话主界面就显示出来 27 | self.close() 28 | self.root.show() 29 | 30 | # ok 按钮的逻辑 31 | def ok_event(self): 32 | logger.info("点击ok按钮") 33 | # 选择按钮之后,这个 dialog 窗口就关闭了 34 | if not self.is_min_status_checkBox.isChecked(): 35 | logger.info("没有选择缩小") 36 | # 退出应用程序 37 | QApplication.instance().quit() 38 | else: 39 | logger.info("选择缩小") 40 | self.root.hide() 41 | -------------------------------------------------------------------------------- /win/login_form.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui 2 | from PyQt5.QtCore import Qt, QPoint 3 | from PyQt5.QtGui import QMouseEvent 4 | 5 | from PyQt5.QtWidgets import QFrame, QMainWindow, QApplication, QMessageBox 6 | from loguru import logger 7 | from playhouse.shortcuts import model_to_dict 8 | 9 | from models.user import User 10 | from ui.login_form import Ui_Frame as ui_form 11 | from win.mysql_form import mysql_form 12 | from win.register_form import register_form 13 | 14 | 15 | class login_form(ui_form, QFrame): 16 | def __init__(self, parent: QMainWindow = None): 17 | super(login_form, self).__init__() 18 | self.setupUi(self) 19 | self.root = parent 20 | self.root.tray_icon.hide() # 先隐藏托盘图标 21 | 22 | # 加载字体 23 | QtGui.QFontDatabase.addApplicationFont("res/otf/Social Media Circled.otf") 24 | 25 | # 隐藏原始的框 26 | self.setWindowFlag(QtCore.Qt.FramelessWindowHint) 27 | self.setAttribute(QtCore.Qt.WA_TranslucentBackground) 28 | 29 | # 按钮事件绑定 30 | self.close_pushButton.clicked.connect(self.close_event) 31 | self.min_pushButton.clicked.connect(self.showMinimized) 32 | 33 | self.login_pushButton.clicked.connect(self.login_pushButton_event) 34 | self.forget_password_pushButton.clicked.connect(self.forget_password_pushButton_event) 35 | self.register_pushButton.clicked.connect(self.register_pushButton_event) 36 | 37 | self.mysql_pushButton.clicked.connect(self.mysql_pushButton_event) 38 | 39 | # 底部按钮 40 | self.github_pushButton.clicked.connect(self.github_pushButton_event) 41 | self.phone_pushButton.clicked.connect(self.phone_pushButton_event) 42 | self.email_pushButton.clicked.connect(self.email_pushButton_event) 43 | 44 | # 关闭的逻辑 45 | def close_event(self): 46 | logger.info("关闭登录窗口") 47 | # 退出应用程序 48 | QApplication.instance().quit() 49 | 50 | # 数据库 51 | def mysql_pushButton_event(self): 52 | logger.info("数据库窗口") 53 | self.mysql_form = mysql_form() 54 | self.mysql_form.show() 55 | 56 | def login_pushButton_event(self): 57 | logger.info("用户登录") 58 | # 登录的逻辑写在这里 59 | user_name = self.user_name_lineEdit.text() 60 | password = self.password_lineEdit.text() 61 | if user_name == "" or password == "": 62 | QMessageBox.information(self, "错误提示", "请输入用户名密码") 63 | return 64 | info = User.select_from_user_name_and_password(user_name, password) 65 | if info is not None: 66 | # 登录成功 67 | QMessageBox.information(self, "登录成功", "欢迎用户:\n" + str(info.user_name) 68 | + "\n" + str(model_to_dict(info))) 69 | self.root.show() # 显示主窗体 70 | self.root.tray_icon.show() # 显示托盘图标 71 | self.hide() 72 | else: 73 | QMessageBox.information(self, "错误提示", "用户名密码错误,请重试") 74 | 75 | def forget_password_pushButton_event(self): 76 | logger.info("忘记密码") 77 | QMessageBox.information(self, "忘记密码", "请联系管理员admin") 78 | 79 | def register_pushButton_event(self): 80 | logger.info("用户注册") 81 | self.register_form = register_form() 82 | self.register_form.show() 83 | 84 | def github_pushButton_event(self): 85 | logger.info("跳转到github网站") 86 | QMessageBox.information(self, "GitHub", "wp19991") 87 | QtGui.QDesktopServices.openUrl(QtCore.QUrl("https://github.com/wp19991")) 88 | 89 | def phone_pushButton_event(self): 90 | logger.info("手机号") 91 | QMessageBox.information(self, "手机号", "手机号\n13170190193") 92 | 93 | def email_pushButton_event(self): 94 | logger.info("邮箱") 95 | QMessageBox.information(self, "邮箱", "邮箱\nwpycahrm@outlook.com") 96 | 97 | def mousePressEvent(self, e: QMouseEvent): 98 | if e.button() == Qt.LeftButton: 99 | self._isTracking = True 100 | self._startPos = QPoint(e.x(), e.y()) 101 | 102 | def mouseMoveEvent(self, e: QMouseEvent): # 重写移动事件 103 | self._endPos = e.pos() - self._startPos 104 | self.move(self.pos() + self._endPos) 105 | 106 | def mouseReleaseEvent(self, e: QMouseEvent): 107 | if e.button() == Qt.LeftButton: 108 | self._isTracking = False 109 | self._startPos = None 110 | self._endPos = None 111 | -------------------------------------------------------------------------------- /win/main_win.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtWidgets, QtCore 2 | from PyQt5.QtChart import QChart, QLineSeries, QChartView 3 | from PyQt5.QtCore import Qt 4 | from PyQt5.QtGui import QPainter 5 | from PyQt5.QtWidgets import QMainWindow, QSystemTrayIcon, QFileSystemModel, QTreeView 6 | from loguru import logger 7 | 8 | from core.CpuLineChart import CpuLineChart 9 | from core.DynamicSpline import DynamicSpline 10 | from core.FileIconProvider import FileIconProvider 11 | from core.ImageView import ImageView 12 | from core.MetroCircleProgress import MetroCircleProgress 13 | from core.MySystemTrayIcon import MySystemTrayIcon 14 | from ui.main_window import Ui_MainWindow as main_window 15 | from utils.CommonHelper import CommonHelper 16 | from win.close_dialog import close_dialog 17 | from utils import global_var as gl 18 | 19 | 20 | class main_win(QMainWindow, main_window): 21 | def __init__(self): 22 | super(main_win, self).__init__() 23 | self.setupUi(self) 24 | 25 | # 程序托盘图标 26 | self.show_tray_icon = close_dialog(parent=self) 27 | self.tray_icon = MySystemTrayIcon() 28 | self.tray_icon.init(self) # 将自己传进去 29 | self.tray_icon.show() 30 | 31 | 32 | # verticalLayout 添加 cpu动态折线图 33 | self.add_cpu_chart() 34 | 35 | # 添加无状态的动态进度条 36 | self.verticalLayout.addWidget(MetroCircleProgress(self, styleSheet="""qproperty-color: #ff0000;""")) 37 | 38 | # verticalLayout 添加 折线图 39 | # self.add_chart() 40 | 41 | # verticalLayout 添加 动态曲线图 42 | # self.add_dynamic_chart() 43 | 44 | # 添加图片查看器控件 45 | # self.image_view = ImageView(image='res/American_Robin.jpg', background=Qt.black) 46 | # self.image_view.setPixmap("res/fish.png") 47 | # self.verticalLayout.addWidget(self.image_view) 48 | 49 | # 添加文件路径控件 50 | # self.add_file_system() 51 | 52 | def add_file_system(self): 53 | self.model = QFileSystemModel() 54 | self.model.setIconProvider(FileIconProvider()) # 设置为自定义的图标提供类 55 | self.model.setRootPath("") 56 | self.tree = QTreeView() 57 | self.tree.setModel(self.model) 58 | 59 | self.tree.setAnimated(False) 60 | self.tree.setIndentation(20) 61 | self.tree.setSortingEnabled(True) 62 | 63 | self.tree.setWindowTitle("Dir View") 64 | self.tree.resize(640, 480) 65 | self.verticalLayout.addWidget(self.tree) 66 | self.tree.show() 67 | 68 | def add_cpu_chart(self): 69 | self.cpu_chart = CpuLineChart() 70 | self.cpu_chart.setTitle('cpu') 71 | self.cpu_chart.setAnimationOptions(QChart.SeriesAnimations) 72 | 73 | self.zxt_QChartView = QChartView() 74 | self.zxt_QChartView.setObjectName("zxt_QChartView") 75 | self.verticalLayout.addWidget(self.zxt_QChartView) 76 | self.zxt_QChartView.setChart(self.cpu_chart) 77 | self.zxt_QChartView.setRenderHint(QPainter.Antialiasing) # 抗锯齿 78 | self.zxt_QChartView.resize(800, 600) 79 | self.zxt_QChartView.show() 80 | 81 | def add_dynamic_chart(self): 82 | self.dynamic_chart = DynamicSpline() 83 | self.dynamic_chart.setTitle("Dynamic spline chart") 84 | self.dynamic_chart.legend().hide() 85 | self.dynamic_chart.setAnimationOptions(QChart.AllAnimations) 86 | 87 | self.zxt_QChartView = QChartView() 88 | self.zxt_QChartView.setObjectName("zxt_QChartView") 89 | self.verticalLayout.addWidget(self.zxt_QChartView) 90 | self.zxt_QChartView.setChart(self.dynamic_chart) 91 | self.zxt_QChartView.setRenderHint(QPainter.Antialiasing) # 抗锯齿 92 | self.zxt_QChartView.resize(800, 600) 93 | self.zxt_QChartView.show() 94 | 95 | def add_chart(self): 96 | self.chart = QChart() 97 | self.chart.setTitle('Line Chart 1') 98 | self.series = QLineSeries(self.chart) 99 | self.series.append(0, 6) 100 | self.series.append(2, 4) 101 | self.series.append(3, 14) 102 | self.chart.addSeries(self.series) 103 | self.chart.createDefaultAxes() # 创建默认轴 104 | 105 | self.zxt_QChartView = QChartView() 106 | self.zxt_QChartView.setObjectName("zxt_QChartView") 107 | self.verticalLayout.addWidget(self.zxt_QChartView) 108 | self.zxt_QChartView.setChart(self.chart) 109 | self.zxt_QChartView.setRenderHint(QPainter.Antialiasing) # 抗锯齿 110 | self.zxt_QChartView.resize(800, 600) 111 | self.zxt_QChartView.show() 112 | 113 | # 重写关闭的逻辑 114 | def closeEvent(self, event): 115 | logger.info("是否关闭主窗口") 116 | event.ignore() 117 | self.show_tray_icon.show() 118 | -------------------------------------------------------------------------------- /win/mysql_form.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from PyQt5 import QtCore, QtGui 4 | from PyQt5.QtCore import Qt, QPoint 5 | from PyQt5.QtGui import QMouseEvent 6 | from PyQt5.QtWidgets import QFrame, QMessageBox, QTableWidgetItem, QApplication, QHeaderView 7 | from loguru import logger 8 | from playhouse.shortcuts import model_to_dict 9 | 10 | from models.user import User 11 | from ui.mysql_form import Ui_Frame as ui_form 12 | from utils.connect_mysql import db 13 | 14 | 15 | class mysql_form(ui_form, QFrame): 16 | def __init__(self): 17 | super(mysql_form, self).__init__() 18 | self.setupUi(self) 19 | icon = QtGui.QIcon() 20 | icon.addPixmap(QtGui.QPixmap(":/icon/icon/探测声音.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) 21 | self.setWindowIcon(icon) 22 | 23 | # 加载字体 24 | QtGui.QFontDatabase.addApplicationFont("res/Social Media Circled.otf") 25 | # 隐藏原始的框 26 | self.setWindowFlag(QtCore.Qt.FramelessWindowHint) 27 | self.setAttribute(QtCore.Qt.WA_TranslucentBackground) 28 | 29 | # 按钮事件绑定 30 | self.close_pushButton.clicked.connect(self.close_event) 31 | self.min_pushButton.clicked.connect(self.showMinimized) 32 | 33 | self.is_admin_login = False 34 | 35 | self.admin_login_pushButton.clicked.connect(self.admin_login_pushButton_event) 36 | self.fresh_pushButton.clicked.connect(self.fresh_pushButton_event) 37 | self.delete_user_pushButton.clicked.connect(self.delete_user_pushButton_event) 38 | self.add_user_pushButton.clicked.connect(self.add_user_pushButton_event) 39 | self.change_user_pushButton.clicked.connect(self.change_user_pushButton_event) 40 | 41 | # 后期需要删除 42 | self.admin_login_of_user_name_lineEdit.setText("admin") 43 | self.admin_login_of_password_lineEdit.setText("123456") 44 | 45 | # 关闭的逻辑 46 | def close_event(self): 47 | logger.info("关闭窗口") 48 | self.close() 49 | 50 | def admin_login_pushButton_event(self): 51 | logger.info("管理员登录") 52 | user_name = self.admin_login_of_user_name_lineEdit.text() 53 | password = self.admin_login_of_password_lineEdit.text() 54 | if user_name == "" or password == "": 55 | QMessageBox.information(self, "管理员登录", "请输入用户名密码") 56 | return 57 | info = User.select_from_user_name_and_password(user_name, password) 58 | 59 | if info is None: 60 | QMessageBox.information(self, "管理员登录", "登录错误,请重试") 61 | return 62 | 63 | if info.type != 2: 64 | QMessageBox.information(self, "管理员登录", "不是管理员,请重新登录") 65 | return 66 | 67 | # 登录成功 68 | QMessageBox.information(self, "登录成功", "欢迎用户管理员") 69 | self.is_admin_login = True 70 | self.groupBox_4.hide() 71 | self.fresh_pushButton_event() # 刷新数据表 72 | 73 | def fresh_pushButton_event(self): 74 | logger.info("更新user表内容") 75 | if not self.is_admin_login: 76 | QMessageBox.information(self, "权限错误", "管理员未登录") 77 | return 78 | self.datas = User.get_user_datas() 79 | 80 | # print("len(self.datas):", len(self.datas)) 81 | self.rowNum = len(self.datas) # 获取查询到的行数 82 | self.columnNum = 0 # 获取查询到的列数 83 | for _ in model_to_dict(self.datas[0]).keys(): 84 | self.columnNum += 1 85 | # print("self.rowNum", self.rowNum) 86 | # print("self.columnNum", self.columnNum) 87 | 88 | self.data_name_list = [] 89 | self.data_name_list_zw = ["id", "创建时间", "修改时间", "用户名", "是否注销", "手机号", "邮箱", "密码", "类型", "简要说明"] 90 | for i in model_to_dict(self.datas[0]).keys(): 91 | self.data_name_list.append(i) 92 | # print("self.data_name_list", self.data_name_list) 93 | 94 | self.data_list = [] 95 | for i in self.datas: 96 | temp = [] 97 | for j in model_to_dict(i).values(): 98 | temp.append(j) 99 | self.data_list.append(temp) 100 | # print("self.data_list", self.data_list) 101 | 102 | self.tableWidget.setRowCount(self.rowNum) # 设置表格行数 103 | self.tableWidget.setColumnCount(self.columnNum) # 设置表格列数 104 | self.tableWidget.setHorizontalHeaderLabels(self.data_name_list_zw) # 设置表头 105 | 106 | for i, da in enumerate(self.data_list): 107 | for j in range(self.columnNum): 108 | if j == 8: 109 | da_temp = "普通用户" if da[j] == 1 else "管理员" 110 | self.itemContent = QTableWidgetItem('%s' % da_temp) 111 | self.tableWidget.setItem(i, j, self.itemContent) 112 | continue 113 | da_temp = "无" if da[j] is None else da[j] 114 | self.itemContent = QTableWidgetItem('%s' % da_temp) 115 | self.tableWidget.setItem(i, j, self.itemContent) 116 | 117 | for i in range(self.columnNum): 118 | # 设置列宽 119 | self.tableWidget.horizontalHeader().setSectionResizeMode(i, QHeaderView.ResizeToContents) 120 | 121 | def delete_user_pushButton_event(self): 122 | logger.info("删除用户") 123 | if not self.is_admin_login: 124 | QMessageBox.information(self, "权限错误", "管理员未登录") 125 | return 126 | user_id = self.delete_user_of_id_lineEdit.text() 127 | # 字段检查 128 | if user_id == "": 129 | QMessageBox.information(self, "删除用户", "请输入用户id") 130 | return 131 | if user_id == "1": 132 | QMessageBox.information(self, "删除用户", "你删除的是管理员,操作错误") 133 | return 134 | # 进行删除用户 135 | if User.user_delete(int(user_id)): 136 | QMessageBox.information(self, "删除用户", "删除用户成功") 137 | self.delete_user_of_id_lineEdit.setText("") 138 | self.fresh_pushButton_event() 139 | else: 140 | QMessageBox.information(self, "删除用户", "删除用户失败,请检查输入") 141 | 142 | def add_user_pushButton_event(self): 143 | logger.info("添加用户") 144 | if not self.is_admin_login: 145 | QMessageBox.information(self, "权限错误", "管理员未登录") 146 | return 147 | user_name = self.add_user_of_user_name_lineEdit.text() 148 | password = self.add_user_of_password_lineEdit.text() 149 | # 字段检查 150 | if user_name == "" or password == "": 151 | QMessageBox.information(self, "添加用户", "请输入输入用户名和密码") 152 | return 153 | # 进行添加用户 154 | try: 155 | User.user_create(user_name, password) 156 | QMessageBox.information(self, "添加用户", "添加用户成功") 157 | self.add_user_of_user_name_lineEdit.setText("") 158 | self.add_user_of_password_lineEdit.setText("") 159 | self.fresh_pushButton_event() 160 | except: 161 | QMessageBox.information(self, "添加用户", "用户名重复,请重新输入") 162 | 163 | def change_user_pushButton_event(self): 164 | logger.info("修改用户") 165 | if not self.is_admin_login: 166 | QMessageBox.information(self, "权限错误", "管理员未登录") 167 | return 168 | user_id = self.change_user_of_id_lineEdit.text() 169 | user_name = self.change_user_of_user_name_lineEdit.text() 170 | phone = self.change_user_of_phone_lineEdit.text() 171 | email = self.change_user_of_email_lineEdit.text() 172 | password = self.change_user_of_password_lineEdit.text() 173 | # 字段检查 174 | if user_id == "": 175 | QMessageBox.information(self, "修改用户", "请输入输入需要修改的用户id") 176 | return 177 | # 进行修改用户 178 | res = User.user_update(int(user_id), user_name, phone, email, password) 179 | if res: 180 | QMessageBox.information(self, "修改用户", "修改用户成功") 181 | self.change_user_of_user_name_lineEdit.setText("") 182 | self.change_user_of_phone_lineEdit.setText("") 183 | self.change_user_of_email_lineEdit.setText("") 184 | self.change_user_of_password_lineEdit.setText("") 185 | self.fresh_pushButton_event() 186 | else: 187 | QMessageBox.information(self, "修改用户", "修改失败,请检查输入") 188 | 189 | def mousePressEvent(self, e: QMouseEvent): 190 | if e.button() == Qt.LeftButton: 191 | self._isTracking = True 192 | self._startPos = QPoint(e.x(), e.y()) 193 | 194 | def mouseMoveEvent(self, e: QMouseEvent): # 重写移动事件 195 | self._endPos = e.pos() - self._startPos 196 | self.move(self.pos() + self._endPos) 197 | 198 | def mouseReleaseEvent(self, e: QMouseEvent): 199 | if e.button() == Qt.LeftButton: 200 | self._isTracking = False 201 | self._startPos = None 202 | self._endPos = None 203 | 204 | 205 | if __name__ == "__main__": 206 | db.connect() 207 | app = QApplication(sys.argv) 208 | A1 = mysql_form() 209 | A1.show() 210 | sys.exit(app.exec_()) 211 | -------------------------------------------------------------------------------- /win/register_form.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui 2 | from PyQt5.QtCore import Qt, QPoint 3 | from PyQt5.QtGui import QMouseEvent 4 | from PyQt5.QtWidgets import QFrame, QMessageBox 5 | from loguru import logger 6 | 7 | from models.user import User 8 | from ui.register_form import Ui_Frame as ui_form 9 | 10 | 11 | class register_form(ui_form, QFrame): 12 | def __init__(self): 13 | super(register_form, self).__init__() 14 | self.setupUi(self) 15 | 16 | # 加载字体 17 | QtGui.QFontDatabase.addApplicationFont("res/otf/Social Media Circled.otf") 18 | 19 | # 隐藏原始的框 20 | self.setWindowFlag(QtCore.Qt.FramelessWindowHint) 21 | self.setAttribute(QtCore.Qt.WA_TranslucentBackground) 22 | 23 | # 按钮事件绑定 24 | self.close_pushButton.clicked.connect(self.close_event) 25 | self.min_pushButton.clicked.connect(self.showMinimized) 26 | 27 | self.register_pushButton.clicked.connect(self.register_pushButton_event) 28 | 29 | # 底部按钮 30 | self.github_pushButton.clicked.connect(self.github_pushButton_event) 31 | self.phone_pushButton.clicked.connect(self.phone_pushButton_event) 32 | self.email_pushButton.clicked.connect(self.email_pushButton_event) 33 | 34 | # 关闭的逻辑 35 | def close_event(self): 36 | logger.info("关闭登录窗口") 37 | # 退出应用程序 38 | self.close() 39 | 40 | def register_pushButton_event(self): 41 | logger.info("用户注册") 42 | user_name = self.user_name_lineEdit.text() 43 | password = self.password_lineEdit.text() 44 | password2 = self.password2_lineEdit.text() 45 | if password != password2: 46 | QMessageBox.information(self, "错误提示", "两次密码输入不对,请重新输入") 47 | return 48 | try: 49 | User.user_create(user_name, password) 50 | QMessageBox.information(self, "注册成功", "注册成功,请登录") 51 | self.close() 52 | except: 53 | QMessageBox.information(self, "错误提示", "用户名重复,请重新注册") 54 | 55 | def github_pushButton_event(self): 56 | logger.info("跳转到github网站") 57 | QMessageBox.information(self, "GitHub", "wp19991") 58 | QtGui.QDesktopServices.openUrl(QtCore.QUrl("https://github.com/wp19991")) 59 | 60 | def phone_pushButton_event(self): 61 | logger.info("手机号") 62 | QMessageBox.information(self, "手机号", "手机号\n13170190193") 63 | 64 | def email_pushButton_event(self): 65 | logger.info("邮箱") 66 | QMessageBox.information(self, "邮箱", "邮箱\nwpycahrm@outlook.com") 67 | 68 | def mousePressEvent(self, e: QMouseEvent): 69 | if e.button() == Qt.LeftButton: 70 | self._isTracking = True 71 | self._startPos = QPoint(e.x(), e.y()) 72 | 73 | def mouseMoveEvent(self, e: QMouseEvent): # 重写移动事件 74 | self._endPos = e.pos() - self._startPos 75 | self.move(self.pos() + self._endPos) 76 | 77 | def mouseReleaseEvent(self, e: QMouseEvent): 78 | if e.button() == Qt.LeftButton: 79 | self._isTracking = False 80 | self._startPos = None 81 | self._endPos = None 82 | -------------------------------------------------------------------------------- /win/splash/core.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import sys 4 | from collections.abc import Iterable 5 | from importlib import import_module 6 | from time import time 7 | 8 | from loguru import logger 9 | 10 | 11 | def preimport(*moduleNames): 12 | for moduleName in moduleNames: 13 | if isinstance(moduleName, str): 14 | if moduleName in sys.modules: 15 | logger.info("[Note]:{} already imported.".format(moduleName)) 16 | else: 17 | timeStart = time() 18 | try: 19 | import_module(moduleName) 20 | except ModuleNotFoundError: 21 | logger.warning("import {} ... ".format("'" + moduleName + "'") + " ModuleNotFound.") 22 | except: 23 | logger.error("import {} ... ".format("'" + moduleName + "'") + "Unexpected error happened") 24 | else: 25 | logger.info("import {} ... ".format("'" + moduleName + "'") + " successfully in {:.2}s.".format( 26 | time() - timeStart)) 27 | elif isinstance(moduleName, Iterable): 28 | preimport(*moduleName) 29 | else: 30 | logger.error("import error, moduleName must be str or Iterable.") 31 | -------------------------------------------------------------------------------- /win/splash/splash.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import time 3 | from PyQt5.QtCore import Qt 4 | from PyQt5.QtGui import QPixmap 5 | from PyQt5.QtWidgets import QApplication, QSplashScreen 6 | from res import app_rc 7 | from win.splash.core import preimport 8 | 9 | 10 | class SplashScreen(QSplashScreen): 11 | def __init__(self): 12 | pixmap = QPixmap(":/img/image/fish.png") 13 | super(SplashScreen, self).__init__(pixmap) 14 | 15 | self.labelAlignment = int(Qt.AlignBottom | Qt.AlignHCenter | Qt.AlignAbsolute) 16 | self.show() 17 | QApplication.flush() 18 | 19 | def showMessage(self, msg): 20 | """Show the progress message on the splash image""" 21 | super(SplashScreen, self).showMessage(msg, self.labelAlignment, Qt.white) 22 | QApplication.processEvents() 23 | 24 | def clearMessage(self): 25 | """Clear message on the splash image""" 26 | super(SplashScreen, self).clearMessage() 27 | QApplication.processEvents() 28 | 29 | def setProgressText(self, percent, delay=0.1): 30 | time.sleep(delay) # 延时,给查看splashscreen更新数值 31 | self.showMessage("正在加载 ... {0}%".format(percent)) 32 | 33 | def loadProgress(self): 34 | self.setProgressText(0, 0) 35 | time.sleep(0.1) 36 | self.setProgressText(5) 37 | time.sleep(0.1) 38 | self.setProgressText(10) 39 | time.sleep(0.1) 40 | self.setProgressText(15) 41 | time.sleep(0.1) 42 | self.setProgressText(20) 43 | preimport(["torch"]) 44 | self.setProgressText(40) 45 | time.sleep(0.1) 46 | self.setProgressText(60) 47 | time.sleep(0.1) 48 | self.setProgressText(80) 49 | time.sleep(0.1) 50 | self.setProgressText(100) 51 | self.hide() 52 | --------------------------------------------------------------------------------