Python Qt | 白月黑羽
# Install
1 2 pip install pyside2 pip install pyside2 -i https://pypi.douban.com/simple/
# Qt Designer UI
运行 C:\Program Files\Python36\Scripts\pyside2-designer.exe
创建 User Interface: httpclient.ui
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 <?xml version="1.0" encoding="UTF-8"?> <ui version ="4.0" > <class > Form</class > <widget class ="QWidget" name ="Form" > <property name ="geometry" > <rect > <x > 0</x > <y > 0</y > <width > 615</width > <height > 591</height > </rect > </property > <property name ="windowTitle" > <string > HTTP 接口测试</string > </property > <layout class ="QVBoxLayout" name ="verticalLayout_3" > <item > <layout class ="QHBoxLayout" name ="horizontalLayout" stretch ="1,8,1" > <item > <widget class ="QComboBox" name ="methodBox" /> </item > <item > <widget class ="QLineEdit" name ="urlEdit" /> </item > <item > <widget class ="QPushButton" name ="sendButton" > <property name ="text" > <string > 发送</string > </property > </widget > </item > </layout > </item > <item > <widget class ="Line" name ="line" > <property name ="orientation" > <enum > Qt::Horizontal</enum > </property > </widget > </item > <item > <layout class ="QHBoxLayout" name ="horizontalLayout_3" stretch ="3,1,4" > <item > <layout class ="QVBoxLayout" name ="verticalLayout" > <item > <layout class ="QHBoxLayout" name ="horizontalLayout_2" > <item > <widget class ="QLabel" name ="label_3" > <property name ="sizePolicy" > <sizepolicy hsizetype ="Preferred" vsizetype ="Preferred" > <horstretch > 2</horstretch > <verstretch > 0</verstretch > </sizepolicy > </property > <property name ="text" > <string > 消息头</string > </property > </widget > </item > <item > <widget class ="QPushButton" name ="addHeaderButton" > <property name ="sizePolicy" > <sizepolicy hsizetype ="Minimum" vsizetype ="Fixed" > <horstretch > 1</horstretch > <verstretch > 0</verstretch > </sizepolicy > </property > <property name ="baseSize" > <size > <width > 0</width > <height > 0</height > </size > </property > <property name ="text" > <string > +</string > </property > <property name ="iconSize" > <size > <width > 16</width > <height > 16</height > </size > </property > </widget > </item > <item > <spacer name ="horizontalSpacer" > <property name ="orientation" > <enum > Qt::Horizontal</enum > </property > <property name ="sizeHint" stdset ="0" > <size > <width > 20</width > <height > 20</height > </size > </property > </spacer > </item > <item > <widget class ="QPushButton" name ="removeHeaderButton" > <property name ="sizePolicy" > <sizepolicy hsizetype ="Minimum" vsizetype ="Fixed" > <horstretch > 1</horstretch > <verstretch > 0</verstretch > </sizepolicy > </property > <property name ="text" > <string > -</string > </property > </widget > </item > </layout > </item > <item > <widget class ="QTableWidget" name ="headerTable" > <attribute name ="verticalHeaderStretchLastSection" > <bool > false</bool > </attribute > <column > <property name ="text" > <string > 名称</string > </property > </column > <column > <property name ="text" > <string > 值</string > </property > </column > </widget > </item > </layout > </item > <item > <widget class ="Line" name ="line_2" > <property name ="orientation" > <enum > Qt::Vertical</enum > </property > </widget > </item > <item > <layout class ="QVBoxLayout" name ="verticalLayout_2" stretch ="0,0" > <item > <layout class ="QHBoxLayout" name ="horizontalLayout_9" > <property name ="topMargin" > <number > 8</number > </property > <property name ="bottomMargin" > <number > 8</number > </property > <item > <widget class ="QLabel" name ="label_2" > <property name ="sizePolicy" > <sizepolicy hsizetype ="Fixed" vsizetype ="Preferred" > <horstretch > 0</horstretch > <verstretch > 0</verstretch > </sizepolicy > </property > <property name ="text" > <string > 消息体</string > </property > </widget > </item > </layout > </item > <item > <widget class ="QPlainTextEdit" name ="bodyText" /> </item > </layout > </item > </layout > </item > <item > <widget class ="Line" name ="line_3" > <property name ="orientation" > <enum > Qt::Horizontal</enum > </property > </widget > </item > <item > <widget class ="QPlainTextEdit" name ="resultText" > <property name ="placeholderText" > <string /> </property > </widget > </item > <item > <layout class ="QHBoxLayout" name ="horizontalLayout_4" > <item > <widget class ="QPushButton" name ="clearButton" > <property name ="sizePolicy" > <sizepolicy hsizetype ="Fixed" vsizetype ="Fixed" > <horstretch > 0</horstretch > <verstretch > 0</verstretch > </sizepolicy > </property > <property name ="text" > <string > 清除</string > </property > </widget > </item > </layout > </item > </layout > </widget > <resources /> <connections /> </ui >
# Progam Logic
httpclient.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 from PySide2.QtWidgets import QApplicationfrom PySide2.QtUiTools import QUiLoaderfrom PySide2.QtGui import QIconfrom requests import Request, Sessionclass HttpGui : def __init__ (self ): self.ui = QUiLoader().load('httpclient.ui' ) self.ui.methodBox.addItems(['GET' , 'POST' , 'PUT' , 'DELETE' ]) self.ui.headerTable.setColumnWidth(0 , 110 ) self.ui.headerTable.setColumnWidth(1 , 110 ) self.ui.urlEdit.setText('http://localhost:3000/users' ) self.ui.sendButton.clicked.connect(self.handle_request) self.ui.clearButton.clicked.connect(self.handle_clear) self.ui.addHeaderButton.clicked.connect(self.handle_header_add) self.ui.removeHeaderButton.clicked.connect(self.handle_header_remove) def handle_header_add (self ): current_row = self.ui.headerTable.currentRow() self.ui.headerTable.insertRow(current_row + 1 ) def handle_header_remove (self ): current_row = self.ui.headerTable.currentRow() self.ui.headerTable.removeRow(current_row) def handle_request (self ): self.ui.resultText.clear() method = self.ui.methodBox.currentText() url = self.ui.urlEdit.text() headers = {} ht = self.ui.headerTable for row in range (0 , ht.rowCount()): key = ht.item(row, 0 ).text() value = ht.item(row, 1 ).text() if not key.strip(): continue headers[key] = value data = self.ui.bodyText.toPlainText() session = Session() req = Request(method, url, headers=headers, data=data) prepped = req.prepare() resp = session.send(prepped) self.ui.resultText.appendPlainText(resp.text) def handle_clear (self ): self.ui.resultText.clear() app = QApplication([]) app.setWindowIcon(QIcon('logo.png' )) stats = HttpGui() stats.ui.show() app.exec_()
# Publisher
在 Windows 上只需要执行下面的命令,即可制作独立 exe 程序。这样就会在当前目录下产生一个名为 dist
的目录。里面就有一个名为 httpclient 的目录,我们的可执行程序 httpclient.exe 就在里面。
1 pyinstaller httpclient.py --noconsole --hidden-import PySide2.QtXml
--noconsole
指定不要命令行窗口,否则我们的程序运行的时候,还会多一个黑窗口。 但是我建议大家可以先去掉这个参数,等确定运行成功后,再加上参数重新制作 exe。因为这个黑窗口可以显示出程序的报错,这样我们容易找到问题的线索。
--hidden-import PySide2.QtXml
参数是因为这个 QtXml 库是动态导入,PyInstaller 没法分析出来,需要我们告诉它,
最后,别忘了,把程序所需要的 ui 文件拷贝到打包目录中。因为 PyInstaller 只能分析出需要哪些代码文件。 而你的程序动态打开的资源文件,比如 图片、excel、ui 这些,它是不会帮你打包的。在 dist/httpclient
中添加 logo.png, 示例代码需要从 httpclient.ui 中加载界面,也需要手动拷贝到 dist/httpclient
目录中。然后,再双击运行 httpclient.exe
,完美!