Создаём окружение для pyqt5 в linux mint (ubuntu)

pyuic5¶

The pyuic5 utility is a command line interface to the
module. The command has the following syntax:

pyuic5 options .ui-file

The full set of command line options is:

A help message is written to .

The version number is written to .

The Python code is generated using an indentation of spaces. If
is 0 then a tab is used. The default is 4.

The Python code generated is written to the file .

The GUI is created dynamically and displayed. No Python code is generated.

The generated Python code includes a small amount of additional code that
creates and displays the GUI when it is executes as a standalone
application.

New in version 5.6.

Resource modules are imported using rather
than a simple .

This is the equivalent of specifying .

The suffix is appended to the basename of any resource file
specified in the file to create the name of the Python module
generated from the resource file by pyrcc5. The default is
. For example if the file specified a resource file called
then the corresponding Python module is .

Load .ui VS convert .ui to .py

In this tutorial, we will use the PyQt5 designer, but before we dig deeper, let’s see how we will use the generated design from the PyQt5 designer.

Open PyQt5 designer, and choose Main Window template and click create button.

Then from the file menu, click save; PyQt5 designer will export your form into an XML file with .ui extension. Now, to use this design, you have two ways:

  • Loading the .ui file in your Python code.
  • Converting the .ui file to a .py file using pyuic5.

Loading the .ui file in your Python code

To load the .ui file in your Python code, you can use the loadUI() function from uic like this:

from PyQt5 import QtWidgets, uic

import sys

app = QtWidgets.QApplication([])

win = uic.loadUi("mydesign.ui") #specify the location of your .ui file

win.show()

sys.exit(app.exec())

If you run your code, you should see a window with nothing but a label.

That means the ui file loaded successfully!

We used sys.exit(app.exec()) instead of using app.exec() directly to send the correct status code to the or the calling process.

If you used app.exec() directly, the application would send zero, which means success, and this will happen even if the application crashed.

Converting the .ui file to a .py file using pyuic5

Now, let’s try the second way by converting the .ui file to a Python code:

$ pyuic5 mydesign.ui -o mydesign.py

Yes! That creates a new file with the name mydesign.py. Now, let’s import that file to show our window.

The pyuic5 stands for Python user interface converter version 5.

from PyQt5 import QtWidgets

from mydesign import Ui_MainWindow  # importing our generated file

import sys

class mywindow(QtWidgets.QMainWindow):

def __init__(self):

    super(mywindow, self).__init__()

    self.ui = Ui_MainWindow()
    
    self.ui.setupUi(self)

app = QtWidgets.QApplication([])

application = mywindow()

application.show()

sys.exit(app.exec())

If you run this code, you should see the same window again as we did in the first method.

The benefit of using the second method is the auto-completion that the IDE will provide since all of your widgets are imported, while the first method you just load the .ui file, and you need to be aware of your widgets names.

Another benefit of using the second method is the speed since you don’t need XML parsing to load the UI.

Now, let’s get our hands dirty and play with the PyQt5 widgets.

Hello World

А теперь напишем небольшую программу на PyQt5, которая будет запускать окно приложения с надписью и иметь один пункт меню в панели меню. По клику на данный пункт будем закрывать приложение.

Полный текст программы

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget, qApp, QAction
from PyQt5.QtCore import QSize


# Наследуемся от QMainWindow
class MainWindow(QMainWindow):
    # Переопределяем конструктор класса
    def __init__(self):
        # Обязательно нужно вызвать метод супер класса
        QMainWindow.__init__(self)

        self.setMinimumSize(QSize(480, 320))    # Устанавливаем размеры
        self.setWindowTitle("Hello world!!!")   # Устанавливаем заголовок окна
        central_widget = QWidget(self)          # Создаём центральный виджет
        self.setCentralWidget(central_widget)   # Устанавливаем центральный виджет

        grid_layout = QGridLayout(self)         # Создаём QGridLayout
        central_widget.setLayout(grid_layout)   # Устанавливаем данное размещение в центральный виджет

        title = QLabel("Hello World on the PyQt5", self)    # Создаём лейбл
        title.setAlignment(QtCore.Qt.AlignCenter)   # Устанавливаем позиционирование текста
        grid_layout.addWidget(title, 0, 0)          # и добавляем его в размещение

        exit_action = QAction("&Exit", self)    # Создаём Action с помощью которого будем выходить из приложения
        exit_action.setShortcut('Ctrl+Q')       # Задаём для него хоткей
        # Подключаем сигнал triggered к слоту quit у qApp.
        # синтаксис сигналов и слотов в PyQt5 заметно отличается от того,
        # который используется Qt5 C++
        exit_action.triggered.connect(qApp.quit)
        # Устанавливаем в панель меню данный Action.
        # Отдельного меню создавать пока не будем.
        file_menu = self.menuBar()
        file_menu.addAction(exit_action)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec())

1. if __name__ == «__main__»:

В приложениях на Python часто можно встретить следующую конструкцию:

С помощью данной конструкции можно указать Python-скрипту, какой программный код исполнять в том случае, если он запускается как самостоятельное приложение. В случае же, если данный скрипт будет импортирован в другой скрипт, то программный код, который будет следовать за данной конструкцией, не будет вызван.

2. Синтаксис сигналов и слотов

В PyQt5 используется следующий синтаксис сигналов и слотов, который показан на примере использования QAction.

exit_action = QAction("&Exit", self)    # Создаём Action с помощью которого будем выходить из приложения
exit_action.triggered.connect(qApp.quit)

Тогда как в Qt C++ тоже самое выглядело бы следующим образом:

QAction *exit = new QAction("&Exit", this);
connect(exit, &QAction::triggered, qApp, &QApplication::quit);

Знак равно

Основа калькулятора – это обработчик, который действительно выполняет кое-какую математику. Все операции (за исключением процентов) обрабатываются обработчиком знака равно, который вызывается нажатием на клавишу знака равно, Enter или другой операционной клавиши.

Обработчик equals берет current_op и добавляет его к значениям в стеке (2 значения, распакованные при помощи *self.stack) для получения результата. Результат отправляется обратно в стек в качестве единственного значения, и мы переходим к состоянию READY. Ошибки (исключения, например, деление на ноль) учитываются, и уведомление об ошибке может быть отображено при необходимости.

Python

def equals(self):
# Поддержка, позволяющая «=» повторять предыдущую операцию
# если новые данные небыли введены.
if self.state == READY and self.last_operation:
s, self.current_op = self.last_operation
self.stack.append(s)

if self.current_op:
self.last_operation = self.stack, self.current_op

try:
self.stack =
except Exception:
self.lcdNumber.display(‘Err’)
self.stack =
else:
self.current_op = None
self.state = READY
self.display()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

defequals(self)

# Поддержка, позволяющая «=» повторять предыдущую операцию

# если новые данные небыли введены.

ifself.state==READY andself.last_operation

s,self.current_op=self.last_operation

self.stack.append(s)

ifself.current_op

self.last_operation=self.stack-1,self.current_op

try

self.stack=self.current_op(*self.stack)

exceptException

self.lcdNumber.display(‘Err’)

self.stack=

else

self.current_op=None

self.state=READY

self.display()

Была также добавлена поддержка для повторяемых предыдущих операций при повторном нажатии знака равно. Это может быть реализовано при сохранении значения и оператора, когда задействуется знак равно. Повторное использование возможно при условии, что знак равно введен еще раз без выхода из режима READY (без пользовательского введения).

What is PyQt5?

PyQt is a Python binding of Qt, a cross-platform GUI toolkit. This is a free software by Riverbank Computing and implements over 440 classes and more than 6000 functions and methods. Some of these are-

PyQt5 Tutorial – What is PyQt5

  • A set of GUI widgets.
  • An XML parser.
  • QScintilla, a rich-text editor widget based on Scintilla.
  • SVG support.
  • Data-aware widgets.
  • Classes to access SQL databases.
  • Classes to embed ActiveX controls on Windows.

a. Modules in PyQt5

We have the following modules available in PyQt5:

  • QtQml
  • QtQtuick
  • QtCore
  • QtGui
  • QtPrintSupport
  • GUI toolkitQtWidgets
  • QGLContext
  • QGLFormat
  • QGLWidget
  • QtWidget
  • QtWebKit
  • QtWebKitWidgets

b. PyQt5 Installation

For this, you need to install PyQt5. You can use pip for this-

pip install pyqt5

To import it in the IDLE, you can do the following-

>>> import PyQt5

Layouts

Like the example above, your GUI will most likely consist of
multiple widgets. In this case, you need to tell Qt how to
position them. For instance, you can use

QVBoxLayout
to stack widgets vertically:

The code for this screenshot is:

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
layout.addWidget(QPushButton('Top'))
layout.addWidget(QPushButton('Bottom'))
window.setLayout(layout)
window.show()
app.exec_()

As before, we instantiate a . Then,
we create a . We use the most basic type
for it because it merely acts as a
container and we don’t want it to have any special behavior.
Next, we create the and add two
s to it. Finally, we tell the window
to use this layout (and thus its contents). As in our first
application, we end with calls to and
.

There are of course many other kinds of layouts (eg.

QHBoxLayout to lay out items in a row). See

Qt’s documentation

for an overview.

Про PyQt5

PyQt5www.riverbankcomputing.co.uk/news

PyQt5 реализован как комплект Python-модулей. Он включает в себя около 620 классов и 6000 функций и методов. Это мульти-платформенный инструментарий, который запускается на большинстве операционных систем, среди которых Unix, Windows и MacOS. PyQt5 реализован под двумя лицензиями. Разработчики могут выбрать между GPL и коммерческой лицензией.

Установка PyQt5

Windows

— http://www.riverbankcomputing.com/software/pyqt/download5

Для пользователей Linux дистрибутивов (Ubuntu, Debian, LinuxMint…) прописать команду в терминал.

sudo apt-get install python3-pyqt5 pyqt5-dev-tools

Блочный макет

Управление макетом классами макета является более гибким и практичным. Это предпочтительный путь размещения виджетов в окне. QHBoxLayout и QVBoxLayout – это основные классы макета, которые выстраивают виджеты горизонтально или вертикально.

Представьте, что мы хотим разместить две кнопки в правом нижнем углу. Чтобы создать такой макет, мы будем использовать один горизонтальный и один вертикальный блок. Чтобы создать необходимое свободное пространство, мы добавим показатель растяжения.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
    QHBoxLayout, QVBoxLayout, QApplication)


class Example(QWidget):

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

        self.initUI()


    def initUI(self):

        okButton = QPushButton("OK")
        cancelButton = QPushButton("Cancel")

        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(okButton)
        hbox.addWidget(cancelButton)

        vbox = QVBoxLayout()
        vbox.addStretch(1)
        vbox.addLayout(hbox)

        self.setLayout(vbox)

        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Buttons')
        self.show()


if __name__ == '__main__'

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

В этом примере мы размещаем две кнопки в нижнем правом углу окна. Они остаются там, когда мы изменяем размер окна приложения. Мы можем использовать и QHBoxLayout, и QVBoxLayout.

okButton = QPushButton("OK")
cancelButton = QPushButton("Cancel")

Здесь мы создаём две кнопки.

hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)

Мы создаём макет горизонтального блока, добавляем показатель растяжения и обе кнопки. Растяжение добавляет растянутое свободное пространство перед двумя кнопками. Это прижмёт их к правому краю окна.

vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)

Чтобы создать необходимый макет, мы поставим горизонтальный макет в вертикальный. Показатель растяжения в вертикальном блоке прижмёт горизонтальный блок с кнопками к нижней части окна.

self.setLayout(vbox)

Наконец, мы устанавливаем главный макет окна.

PyQt5 Tutorial – Adding Buttons

Using the QPushButton class, we can add buttons to our screen.

>>> from PyQt5.QtWidgets import QApplication,QWidget,QPushButton
>>> from PyQt5.QtCore import pyqtSlot
>>> import sys
>>> class App(QWidget):
       def __init__(self):
               super().__init__()
               self.title='Hello, world!'
               self.left=10
               self.top=10
               self.width=640
               self.height=480
               self.initUI()
       def initUI(self):
               self.setWindowTitle(self.title)
               self.setGeometry(self.left,self.top,self.width,self.height)
               button=QPushButton('Click me',self)
               button.setToolTip('Thank you for thinking about me')
               button.move(100,70)
               self.show()
>>> if __name__=='__main__':
       app=QApplication(sys.argv)
       ex=App()

Adding Buttons

Create a GUI

Time to write our very first GUI app! With the virtual
environment still active, start Python. We will execute the
following commands:

First, we tell Python to load PyQt via the import statement:

from PyQt5.QtWidgets import QApplication, QLabel

Next, we create a

with the command:

app = QApplication([])

This is a requirement of Qt: Every GUI app must have exactly
one instance of . Many parts of Qt
don’t work until you have executed the above line. You will
therefore need it in virtually every (Py)Qt app you write.

The brackets in the above line represent the
command line arguments passed to the application. Because
our app doesn’t use any parameters, we leave the brackets
empty.

Now, to actually see something, we create a simple label:

label = QLabel('Hello World!')

Then, we tell Qt to show the label on the screen:

label.show()

Depending on your operating system, this already opens a
tiny little window:

The last step is to hand control over to Qt and ask it to
«run the application until the user closes it». This is done
via the command:

app.exec_()

If all this worked as expected then well done! You’ve just
built your first GUI app with Python and Qt.

Install PyQt5 designer

There are two ways to build GUI apps using PyQt5:

  • Design widgets by code.
  • Using PyQt5 designer.

In this PyQt5 tutorial, we will use the PyQt5 designer, which makes it so easy to finish a lot of work in a matter of seconds.

PyQt5 designer comes with PyQt5 tools. To install it, you need to install PyQt5 tools.

$ pip3 install PyQt5-tools

Where is PyQt5 designer?

After successful installation, you can find the PyQt5 designer on this location:

C:\Program Files\Python36\Lib\site-packages\pyqt5-tools\

Also, If you installed Python for your current user only, you will find the PyQt5 designer on this location:

C:\Users\LikeGeeks\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\ pyqt5-tools\

You can make a shortcut for it instead of going into this location every time you want to run the PyQt5 designer.

PyQt5 Tutorial – Setting Absolute Position

You can put your widgets anywhere you want on the screen.Let’s discuss Python Collections module

>>> import sys
>>> from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QLabel
>>> from PyQt5.QtGui import QIcon
>>> class App(QMainWindow):
       def __init__(self):
               super().__init__()
               self.title = 'Hello, world!'
               self.left = 10
               self.top = 10
               self.width = 440
               self.height = 280
               self.initUI()
       def initUI(self):
               self.setWindowTitle(self.title)
               self.setGeometry(self.left, self.top, self.width, self.height)
               label = QLabel('Pink',self)
               label.move(50,50)
               label2 = QLabel('Blue',self)
               label2.move(100,100)
               label3 = QLabel('Green',self)
               label3.move(150,150)
               label4 = QLabel('Lavender',self)
               label4.move(200,200)
self.show()
>>> if __name__=='__main__':
       app=QApplication(sys.argv)
       ex=App()

Setting Absolute Position

Виджет записи дисков

Это виджет, который мы можем увидеть в Nero, K3B и в других программах записи CD/DVD.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import (QWidget, QSlider, QApplication,
    QHBoxLayout, QVBoxLayout)
from PyQt5.QtCore import QObject, Qt, pyqtSignal
from PyQt5.QtGui import QPainter, QFont, QColor, QPen


class Communicate(QObject):

    updateBW = pyqtSignal(int)


class BurningWidget(QWidget):

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

        self.initUI()


    def initUI(self):

        self.setMinimumSize(1, 30)
        self.value = 75
        self.num = 75, 150, 225, 300, 375, 450, 525, 600, 675


    def setValue(self, value):

        self.value = value


    def paintEvent(self, e):

        qp = QPainter()
        qp.begin(self)
        self.drawWidget(qp)
        qp.end()


    def drawWidget(self, qp):

        font = QFont('Serif', 7, QFont.Light)
        qp.setFont(font)

        size = self.size()
        w = size.width()
        h = size.height()

        step = int(round(w  10))


        till = int(((w  750) * self.value))
        full = int(((w  750) * 700))

        if self.value >= 700

            qp.setPen(QColor(255, 255, 255))
            qp.setBrush(QColor(255, 255, 184))
            qp.drawRect(, , full, h)
            qp.setPen(QColor(255, 175, 175))
            qp.setBrush(QColor(255, 175, 175))
            qp.drawRect(full, , till-full, h)

        else

            qp.setPen(QColor(255, 255, 255))
            qp.setBrush(QColor(255, 255, 184))
            qp.drawRect(, , till, h)


        pen = QPen(QColor(20, 20, 20), 1,
            Qt.SolidLine)

        qp.setPen(pen)
        qp.setBrush(Qt.NoBrush)
        qp.drawRect(, , w-1, h-1)

        j = 

        for i in range(step, 10*step, step):

            qp.drawLine(i, , i, 5)
            metrics = qp.fontMetrics()
            fw = metrics.width(str(self.numj]))
            qp.drawText(i-fw2, h2, str(self.numj]))
            j = j + 1


class Example(QWidget):

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

        self.initUI()


    def initUI(self):

        sld = QSlider(Qt.Horizontal, self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setRange(1, 750)
        sld.setValue(75)
        sld.setGeometry(30, 40, 150, 30)

        self.c = Communicate()
        self.wid = BurningWidget()
        self.c.updateBWint.connect(self.wid.setValue)

        sld.valueChangedint.connect(self.changeValue)
        hbox = QHBoxLayout()
        hbox.addWidget(self.wid)
        vbox = QVBoxLayout()
        vbox.addStretch(1)
        vbox.addLayout(hbox)
        self.setLayout(vbox)

        self.setGeometry(300, 300, 390, 210)
        self.setWindowTitle('Burning widget')
        self.show()


    def changeValue(self, value):

        self.c.updateBW.emit(value)
        self.wid.repaint()


if __name__ == '__main__'

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

В нашем примере, у нас есть QSlider и собственный виджет. Ползунок контролирует наш виджет. Этот виджет показывает графически общий объём носителя и свободное место, доступное для нас. Минимальное значение нашего виджета – 1, максимальное – 750. Если мы достигаем значения 700, мы начинаем рисование красным цветом. Это обычно означает переполнение. Виджет записи размещается внизу окна путём использования одного QHBoxLayout и одного QVBoxLayout.

class BurningWidget(QWidget):

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

Виджет записи основывается на виджете QWidget.

self.setMinimumSize(1, 30)

Мы меняем минимальный размер (высоту) виджета. Значение по умолчанию немного маловато для нас.

font = QFont('Serif', 7, QFont.Light)
qp.setFont(font)

Мы используем более мелкий шрифт, чем по умолчанию. Это лучше подходит для наших нужд.

size = self.size()
w = size.width()
h = size.height()

step = int(round(w  10))


till = int(((w  750) * self.value))
full = int(((w  750) * 700))

Мы рисуем виджет динамически. Чем больше окно, тем больше виджет записи, и наоборот. Вот почему мы должны вычислять размер виджета.

Параметр till — общий размер. Это значение известно нам из виджета ползунка. Это доля от полного пространства.

Параметр full определяет точку, где мы начинаем рисовать красным цветом.

Фактически рисование содержит три шага. Мы рисуем жёлтый или красный и жёлтый прямоугольник. Затем мы рисуем вертикальные линии, которые делят виджет на несколько частей. Наконец, мы рисуем числа, которые показывают ёмкость носителя.

metrics = qp.fontMetrics()
fw = metrics.width(str(self.numj]))
qp.drawText(i-fw2, h2, str(self.numj]))

Мы используем метрики шрифтов, чтобы рисовать текст. Мы должны знать ширину текста, для того чтобы центрировать его рядом с вертикальной линией.

def changeValue(self, value):
    self.c.updateBW.emit(value)
    self.wid.repaint()

Когда мы двигаем ползунок, вызывается метод changeValue(). Внутри метода, мы отправляем пользовательский сигнал updateBW с параметром. Параметр – это текущее значение ползунка. Значение позднее используется, чтобы вычислить ёмкость рисуемого виджета записи. Затем, наш виджет перерисовывается.

В этой части руководства PyQt5, мы создали свой виджет.

Visual signal/slot editor

We saw how to connect the widget signal to a slot using the connect() method, but this is not the only way.

There are some predefined slots for each widget. You can connect a signal to any predefined slot without coding in the PyQt5 designer.

Drag a QPushButton and a QLineEdit on your form.

Press F4 and drag the mouse from the QPushButton and release it on the top of the QLineEdit.

The signal/slot editor will show up.

On the left, the predefined signals while on the right the predefined slots. Let’s say that we want to connect the clicked() signal with the clear slot.

Choose the clicked from the left and choose clear from the right and click OK.

After finishing your signal/slot connections, you can escape from this mode by pressing ESC or F3.

Now, if you run this form and click the QPushButton, any text on the QLineEdit will be cleared. You can edit or delete this connection from the signal/slot editor panel.

Compile your app

You now have the basic knowledge for creating a GUI that
responds to user input. Say you’ve written an app. It runs
on your computer. How do you give it to other people, so
they can run it as well?

You could ask the users of your app to install Python and
PyQt like we did above, then give them your source code. But
that is very tedious (and usually impractical). What we want
instead is a standalone version of your app. That
is, a binary executable that other people can run on their
systems without having to install anything.

In the Python world, the process of turning source code into
a self-contained executable is called freezing.
Although there are many libraries that address this issue
– such as PyInstaller, py2exe, cx_Freeze, bbfreze,
py2app, … – freezing PyQt apps has traditionally
been a surprisingly hard problem.

We will use a new library called
fbs that lets you
create standalone executables for PyQt apps. To install it,
enter the command:

pip install fbs

Then, execute the following:

fbs startproject

This prompts you for a few values:

When you type in the suggested command,
an empty window should open:

This is a PyQt5 app just like the ones we have seen before.
Its source code is in
in your current directory. But here’s the cool part: We can
use fbs to turn it into a standalone executable!

fbs freeze

This places a self-contained binary in the
folder of your current directory.
You can send it to your friends (with the same OS as yours)
and they will be able to run your app!

(Please note that fbs currently targets Python 3.5 or 3.6.
If you have a different version and the above does not work,
please

install Python 3.6

and try again. On macOS, you can also
.)

Bonus: Create an installer

fbs also lets you create an installer for your app via the
command :

(If you are on Windows, you first need to install
NSIS and
place it on your .)

For more information on how you can use fbs for your
existing application, please see

this article.
Or

fbs’s tutorial.

Оцените статью
Рейтинг автора
5
Материал подготовил
Андрей Измаилов
Наш эксперт
Написано статей
116
Добавить комментарий