21.md 13.8 KB
Newer Older
W
init  
wizardforcel 已提交
1 2 3 4 5 6 7 8
# PyQt5 中的第一个程序

> 原文: [http://zetcode.com/gui/pyqt5/firstprograms/](http://zetcode.com/gui/pyqt5/firstprograms/)

在 PyQt5 教程的这一部分中,我们学习一些基本功能。 这些示例显示了一个工具提示和一个图标,关闭了一个窗口,显示了一个消息框,并在桌面上将窗口居中。

## 简单的例子

W
wizardforcel 已提交
9
这是一个显示小窗口的简单示例。 然而,我们可以利用这个窗口做很多事情。 我们可以调整大小,最大化或最小化它。 这需要大量的编码。 已经有人对该功能进行了编码。 由于它在大多数应用中都重复执行,因此无需再次编码。 PyQt5 是高级工具包。 如果我们使用较低级的工具箱进行编码,则下面的代码示例可能很容易包含数百行。
W
init  
wizardforcel 已提交
10 11 12

`simple.py`

W
wizardforcel 已提交
13
```py
W
init  
wizardforcel 已提交
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
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

In this example, we create a simple
window in PyQt5.

Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""

import sys
from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':

    app = QApplication(sys.argv)

    w = QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple')
    w.show()

    sys.exit(app.exec_())

```

上面的代码示例在屏幕上显示了一个小窗口。

W
wizardforcel 已提交
47
```py
W
init  
wizardforcel 已提交
48 49 50 51 52
import sys
from PyQt5.QtWidgets import QApplication, QWidget

```

W
wizardforcel 已提交
53
在这里,我们提供必要的导入。 基本窗口小部件位于`PyQt5.QtWidgets`模块中。
W
init  
wizardforcel 已提交
54

W
wizardforcel 已提交
55
```py
W
init  
wizardforcel 已提交
56 57 58 59
app = QApplication(sys.argv)

```

W
wizardforcel 已提交
60
每个 PyQt5 应用都必须创建一个应用对象。 `sys.argv`参数是命令行中的参数列表。 可以从外壳运行 Python 脚本。 这是我们可以控制脚本启动的方式。
W
init  
wizardforcel 已提交
61

W
wizardforcel 已提交
62
```py
W
init  
wizardforcel 已提交
63 64 65 66 67 68
w = QWidget()

```

`QWidget`小部件是 PyQt5 中所有用户界面对象的基类。 我们为`QWidget`提供了默认的构造函数。 默认构造函数没有父代。 没有父级的窗口小部件称为窗口。

W
wizardforcel 已提交
69
```py
W
init  
wizardforcel 已提交
70 71 72 73 74 75
w.resize(250, 150)

```

`resize()`方法调整窗口小部件的大小。 宽 250 像素,高 150 像素。

W
wizardforcel 已提交
76
```py
W
init  
wizardforcel 已提交
77 78 79 80
w.move(300, 300)

```

W
wizardforcel 已提交
81
`move()`方法将窗口小部件移动到屏幕上`x = 300``y = 300`坐标的位置。
W
init  
wizardforcel 已提交
82

W
wizardforcel 已提交
83
```py
W
init  
wizardforcel 已提交
84 85 86 87 88 89
w.setWindowTitle('Simple')

```

我们用`setWindowTitle()`设置窗口的标题。 标题显示在标题栏中。

W
wizardforcel 已提交
90
```py
W
init  
wizardforcel 已提交
91 92 93 94 95 96
w.show()

```

`show()`方法在屏幕上显示小部件。 首先在内存中创建一个小部件,然后将其显示在屏幕上。

W
wizardforcel 已提交
97
```py
W
init  
wizardforcel 已提交
98 99 100 101
sys.exit(app.exec_())

```

W
wizardforcel 已提交
102
最后,我们进入应用的主循环。 事件处理从这一点开始。 mainloop 从窗口系统接收事件,并将其分配给应用小部件。 如果调用`exit()`方法或主窗口小部件被销毁,则主循环结束。 `sys.exit()`方法可确保干净退出。 将告知环境应用如何结束。
W
init  
wizardforcel 已提交
103 104 105 106 107

`exec_()`方法带有下划线。 这是因为`exec`是 Python 关键字。 因此,使用了`exec_()`

![Simple](img/0a65d25d0b0e047b0706e7505851f171.jpg)

W
wizardforcel 已提交
108
图:简单
W
init  
wizardforcel 已提交
109

W
wizardforcel 已提交
110
## 应用图标
W
init  
wizardforcel 已提交
111

W
wizardforcel 已提交
112
应用图标是一个小图像,通常显示在标题栏的左上角。 在下面的示例中,我们将展示如何在 PyQt5 中做到这一点。 我们还将介绍一些新方法。
W
init  
wizardforcel 已提交
113 114 115 116 117

某些环境在标题栏中不显示图标。 我们需要启用它们。 如果没有看到图标,请参阅我在 Stackoverflow 上的[答案](https://stackoverflow.com/questions/44080247/pyqt5-does-now-show-icons/45439678#45439678)以获取解决方案。

`icon.py`

W
wizardforcel 已提交
118
```py
W
init  
wizardforcel 已提交
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
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

This example shows an icon
in the titlebar of the window.

Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon

class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('web.png'))        

        self.show()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

```

前面的示例以过程样式编码。 Python 编程语言支持过程和面向对象的编程风格。 在 PyQt5 中编程意味着在 OOP 中编程。

W
wizardforcel 已提交
162
```py
W
init  
wizardforcel 已提交
163 164 165 166 167 168 169 170 171 172
class Example(QWidget):

    def __init__(self):
        super().__init__()
        ...

```

面向对象编程中的三个重要方面是类,数据和方法。 在这里,我们创建了一个名为`Example`的新类。 `Example`类继承自`QWidget`类。 这意味着我们调用了两个构造函数:第一个构造函数用于`Example`类,第二个构造函数用于继承的类。 `super()`方法返回`Example`类的父对象,我们将其称为构造函数。 `__init__()`方法是 Python 语言的构造方法。

W
wizardforcel 已提交
173
```py
W
init  
wizardforcel 已提交
174 175 176 177 178 179
self.initUI() 

```

GUI 的创建委托给`initUI()`方法。

W
wizardforcel 已提交
180
```py
W
init  
wizardforcel 已提交
181 182 183 184 185 186
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('web.png'))  

```

W
wizardforcel 已提交
187
所有这三种方法都从`QWidget`类继承。 `setGeometry()`做两件事:在屏幕上找到窗口并设置其大小。 前两个参数是窗口的 x 和 y 位置。 第三个是窗口的宽度,第四个是窗口的高度。 实际上,它将`resize()``move()`方法结合在一起。 最后一种方法设置应用图标。 为此,我们创建了一个`QIcon`对象。 `QIcon`接收到要显示的图标的路径。
W
init  
wizardforcel 已提交
188

W
wizardforcel 已提交
189
```py
W
init  
wizardforcel 已提交
190 191 192 193 194 195 196 197
if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())  

```

W
wizardforcel 已提交
198
将创建应用和示例对象。 主循环开始。
W
init  
wizardforcel 已提交
199 200 201

![Icon](img/fde5558ff960d66134deda62f76234cc.jpg)

W
wizardforcel 已提交
202
图:图标
W
init  
wizardforcel 已提交
203 204 205 206 207 208 209

## 显示工具提示

我们可以为我们的任何小部件提供气球帮助。

`tooltip.py`

W
wizardforcel 已提交
210
```py
W
init  
wizardforcel 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

This example shows a tooltip on 
a window and a button.

Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""

import sys
from PyQt5.QtWidgets import (QWidget, QToolTip, 
    QPushButton, QApplication)
from PyQt5.QtGui import QFont    

class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        QToolTip.setFont(QFont('SansSerif', 10))

        self.setToolTip('This is a <b>QWidget</b> widget')

        btn = QPushButton('Button', self)
        btn.setToolTip('This is a <b>QPushButton</b> widget')
        btn.resize(btn.sizeHint())
        btn.move(50, 50)       

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Tooltips')    
        self.show()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

```

在此示例中,我们显示了两个 PyQt5 小部件的工具提示。

W
wizardforcel 已提交
262
```py
W
init  
wizardforcel 已提交
263 264 265 266 267 268
QToolTip.setFont(QFont('SansSerif', 10))

```

此静态方法设置用于呈现工具提示的字体。 我们使用 10pt SansSerif 字体。

W
wizardforcel 已提交
269
```py
W
init  
wizardforcel 已提交
270 271 272 273 274 275
self.setToolTip('This is a <b>QWidget</b> widget')

```

要创建工具提示,我们调用`setTooltip()`方法。 我们可以使用富文本格式。

W
wizardforcel 已提交
276
```py
W
init  
wizardforcel 已提交
277 278 279 280 281 282 283
btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')

```

我们创建一个按钮小部件并为其设置工具提示。

W
wizardforcel 已提交
284
```py
W
init  
wizardforcel 已提交
285 286 287 288 289
btn.resize(btn.sizeHint())
btn.move(50, 50)       

```

W
wizardforcel 已提交
290
调整按钮的大小并在窗口上移动。 `sizeHint()`方法为按钮提供了建议的大小。
W
init  
wizardforcel 已提交
291 292 293

![Tooltips](img/f35a00e3fce080f01b141b313e41900b.jpg)

W
wizardforcel 已提交
294
图:工具提示 s
W
init  
wizardforcel 已提交
295

W
wizardforcel 已提交
296
## 关闭窗口
W
init  
wizardforcel 已提交
297

W
wizardforcel 已提交
298
关闭窗口的明显方法是单击标题栏上的 X 标记。 在下一个示例中,我们展示了如何以编程方式关闭窗口。 我们将简要介绍信号和槽。
W
init  
wizardforcel 已提交
299 300 301

以下是我们在示例中使用的`QPushButton`小部件的构造函数。

W
wizardforcel 已提交
302
```py
W
init  
wizardforcel 已提交
303 304 305 306
QPushButton(string text, QWidget parent = None)

```

W
wizardforcel 已提交
307
`text`参数是将在按钮上显示的文本。 `parent`是一个小部件,我们在其上放置了按钮。 在我们的情况下,它将是`QWidget`。 应用的小部件形成层次结构。 在此层次结构中,大多数小部件都有其父级。 没有父级的小部件是顶层窗口。
W
init  
wizardforcel 已提交
308 309 310

`quitbutton.py`

W
wizardforcel 已提交
311
```py
W
init  
wizardforcel 已提交
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

This program creates a quit
button. When we press the button,
the application terminates. 

Author: Jan Bodnar
Website: zetcode.com 
Last edited: January 2018
"""

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication

class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):               

        qbtn = QPushButton('Quit', self)
        qbtn.clicked.connect(QApplication.instance().quit)
        qbtn.resize(qbtn.sizeHint())
        qbtn.move(50, 50)       

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Quit button')    
        self.show()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

```

W
wizardforcel 已提交
356
在此示例中,我们创建一个退出按钮。 单击按钮后,应用终止。
W
init  
wizardforcel 已提交
357

W
wizardforcel 已提交
358
```py
W
init  
wizardforcel 已提交
359 360 361 362 363 364
qbtn = QPushButton('Quit', self)

```

我们创建一个按钮。 该按钮是`QPushButton`类的实例。 构造函数的第一个参数是按钮的标签。 第二个参数是父窗口小部件。 父窗口小部件是`Example`小部件,通过继承它是`QWidget`

W
wizardforcel 已提交
365
```py
W
init  
wizardforcel 已提交
366 367 368 369
qbtn.clicked.connect(QApplication.instance().quit)

```

W
wizardforcel 已提交
370
PyQt5 中的事件处理系统是通过信号和槽机制构建的。 如果单击按钮,将发出信号`clicked`。 该槽可以是 Qt 槽或任何可调用的 Python。
W
init  
wizardforcel 已提交
371

W
wizardforcel 已提交
372
`QApplication.instance()`检索的`QCoreApplication`包含主事件循环-它处理并调度所有事件。 单击的信号连接到`quit()`方法,该方法终止应用。 通信是在两个对象之间进行的:发送者和接收者。 发送者是按钮,接收者是应用对象。
W
init  
wizardforcel 已提交
373 374 375

![Quit button](img/1aace4fa77667a78135228a42f1d48e3.jpg)

W
wizardforcel 已提交
376
图:退出按钮
W
init  
wizardforcel 已提交
377

W
wizardforcel 已提交
378
## `MessageDialog`
W
init  
wizardforcel 已提交
379

W
wizardforcel 已提交
380
默认情况下,如果单击标题栏上的 X 按钮,则`QWidget`将关闭。 有时我们想要修改此默认行为。 例如,如果我们在编辑器中打开了一个文件,对此我们做了一些更改。 我们显示一个消息框以确认操作。
W
init  
wizardforcel 已提交
381 382 383

`messagebox.py`

W
wizardforcel 已提交
384
```py
W
init  
wizardforcel 已提交
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

This program shows a confirmation 
message box when we click on the close
button of the application window. 

Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""

import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication

class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):               

        self.setGeometry(300, 300, 250, 150)        
        self.setWindowTitle('Message box')    
        self.show()

    def closeEvent(self, event):

        reply = QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QMessageBox.Yes | 
            QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()        

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

```

W
wizardforcel 已提交
435
如果我们关闭`QWidget`,则会生成`QCloseEvent`。 要修改小部件的行为,我们需要重新实现`closeEvent()`事件处理器。
W
init  
wizardforcel 已提交
436

W
wizardforcel 已提交
437
```py
W
init  
wizardforcel 已提交
438 439 440 441 442 443 444 445
reply = QMessageBox.question(self, 'Message',
    "Are you sure to quit?", QMessageBox.Yes | 
    QMessageBox.No, QMessageBox.No)

```

我们显示一个带有两个按钮的消息框:是和否。第一个字符串出现在标题栏上。 第二个字符串是对话框显示的消息文本。 第三个参数指定出现在对话框中的按钮的组合。 最后一个参数是默认按钮。 该按钮最初具有键盘焦点。 返回值存储在`reply`变量中。

W
wizardforcel 已提交
446
```py
W
init  
wizardforcel 已提交
447 448 449 450 451 452 453
if reply == QtGui.QMessageBox.Yes:
    event.accept()
else:
    event.ignore()  

```

W
wizardforcel 已提交
454
在这里,我们测试返回值。 如果单击“是”按钮,我们将接受导致小部件关闭和应用终止的事件。 否则,我们将忽略关闭事件。
W
init  
wizardforcel 已提交
455 456 457

![Message box](img/2103dacd426f497b2bc5075009127ef9.jpg)

W
wizardforcel 已提交
458
图:消息框
W
init  
wizardforcel 已提交
459 460 461 462 463 464 465

## 屏幕上的居中窗口

以下脚本显示了如何在桌面屏幕上居中放置窗口。

`center.py`

W
wizardforcel 已提交
466
```py
W
init  
wizardforcel 已提交
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

This program centers a window 
on the screen. 

Author: Jan Bodnar
Website: zetcode.com 
Last edited: August 2017
"""

import sys
from PyQt5.QtWidgets import QWidget, QDesktopWidget, QApplication

class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):               

        self.resize(250, 150)
        self.center()

        self.setWindowTitle('Center')    
        self.show()

    def center(self):

        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

```

W
wizardforcel 已提交
514
`QDesktopWidget`类提供有关用户桌面的信息,包括屏幕大小。
W
init  
wizardforcel 已提交
515

W
wizardforcel 已提交
516
```py
W
init  
wizardforcel 已提交
517 518 519 520 521 522
self.center()

```

将使窗口居中的代码位于自定义`center()`方法中。

W
wizardforcel 已提交
523
```py
W
init  
wizardforcel 已提交
524 525 526 527 528 529
qr = self.frameGeometry()

```

我们得到一个指定主窗口几何形状的矩形。 这包括任何窗框。

W
wizardforcel 已提交
530
```py
W
init  
wizardforcel 已提交
531 532 533 534 535 536
cp = QDesktopWidget().availableGeometry().center()

```

我们计算出显示器的屏幕分辨率。 从这个分辨率,我们得到了中心点。

W
wizardforcel 已提交
537
```py
W
init  
wizardforcel 已提交
538 539 540 541 542 543
qr.moveCenter(cp)

```

我们的矩形已经具有宽度和高度。 现在,我们将矩形的中心设置为屏幕的中心。 矩形的大小不变。

W
wizardforcel 已提交
544
```py
W
init  
wizardforcel 已提交
545 546 547 548
self.move(qr.topLeft())

```

W
wizardforcel 已提交
549
我们将应用窗口的左上角移动到`qr`矩形的左上角,从而将窗口居中放置在屏幕上。
W
init  
wizardforcel 已提交
550 551

在 PyQt5 教程的这一部分中,我们在 PyQt5 中创建了简单的代码示例。