Кастомные шрифты и PyQt5

Рейтинг: 2Ответов: 1Опубликовано: 21.03.2023

Пишу проект на PyQt5, применяя при этом кастомный шрифт (Comfortaa из Google Fonts).
Естественно, чтобы всё хорошо работало на других компьютерах, решил зашить шрифт в программу.

Первоначальный вариант выглядел так:

QFontDatabase.addApplicationFont('Fonts/Comfortaa-VariableFont_wght.ttf')

Это прописано в методе инициализации основного окна (других не имеется).
Была только одна проблема - на втором компьютере ничего не работало.


Другой вариант - добавить шрифт в файл ресурсов и после на него сослаться в основной программе.
Файл ресурсов (его я после сконвертировал в файл.py):

<RCC>
  <qresource prefix="icons">
    <file>keyboard_backspace_FILL0_wght500_GRAD-25_opsz48.png</file>
    <file>settings_FILL1_wght300_GRAD0_opsz48.png</file>
  </qresource>
  <qresource prefix="font">
    <file>Comfortaa-VariableFont_wght.ttf</file>
  </qresource>
</RCC>

Код из метода инициализации:

QFontDatabase.addApplicationFont(':/font/Comfortaa-VariableFont_wght.ttf')

И код из самого конца программы (отображение окна):

app = QApplication(sys.argv)
app.setFont(QFont('Comfortaa', 8))

Итог просто шедевральный - шрифт после преобразования в .exe отображается только в тексте, прописанном в одном из табвиджетов, но при этом не отображается ни в комбо боксе, ни на кнопках - короче говоря, больше нигде.

Что я делаю не так? Как это исправить?


P.S.
Пример кода (здесь даже в табвиджете ничего не работает)

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QFontDatabase
import resources_rc

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(942, 600)
        MainWindow.setStyleSheet("QMainWindow {\n"
"    font-family: Comfortaa;\n"
"}")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("Comfortaa")
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("Comfortaa")
        self.comboBox.setFont(font)
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.horizontalLayout.addWidget(self.comboBox)
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.gridLayout = QtWidgets.QGridLayout(self.tab)
        self.gridLayout.setObjectName("gridLayout")
        self.label = QtWidgets.QLabel(self.tab)
        font = QtGui.QFont()
        font.setFamily("Comfortaa")
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
        self.tabWidget.addTab(self.tab, "")
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.tabWidget.addTab(self.tab_2, "")
        self.horizontalLayout.addWidget(self.tabWidget)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        QFontDatabase.addApplicationFont(':/font/Comfortaa-VariableFont_wght.ttf')

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "кнопка"))
        self.comboBox.setItemText(0, _translate("MainWindow", "раз"))
        self.comboBox.setItemText(1, _translate("MainWindow", "два"))
        self.label.setText(_translate("MainWindow", "Оперативная информация, которая представляет политический, социальный или экономический\n"
"интерес для аудитории в своей свежести, то есть сообщения о событиях, произошедших недавно\n"
"или происходящих в данный момент. Также новостями называют программы на телевидении и\n"
"радио, а в печатной прессе или на веб-сайтах - сводки новостей, в специальной рубрике в газете."))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

main.exe создавал с помощью pyinstaller

Ответы

▲ 2Принят

Создал каталоги icons и font. Поместил туда изображения и шрифты.

введите сюда описание изображения

Создал файл ресурсов q1506816.qrc:

<RCC>
  <qresource prefix="Images">
    <file>icons/back.png</file>
    <file>icons/exit.png</file>
  </qresource>
  <qresource prefix="Fonts">
    <file>font/fontawesome-webfont.ttf</file>
    <file>font/Roboto-Regular.ttf</file>
    <file>font/Roboto-Thin.ttf</file>
    <file>font/segoeui.ttf</file>
    <file>font/segoeuib.ttf</file>
  </qresource>
</RCC>

Сконвертировал q1506816.qrc в q1506816_rc.py:

pyrcc5 q1506816.qrc -o q1506816_rc.py 

Создал файл q1506816.py:

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

import q1506816_rc                                      # !!! +++ q1506816_rc.py


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(700, 600)

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.horizontalLayout.addWidget(self.comboBox)
        
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.gridLayout = QtWidgets.QGridLayout(self.tab)
        self.gridLayout.setObjectName("gridLayout")
        
        self.label = QtWidgets.QLabel(self.tab)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
        
        self.tabWidget.addTab(self.tab, "")
        
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.tabWidget.addTab(self.tab_2, "")
        
        self.horizontalLayout.addWidget(self.tabWidget)

        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Кнопка"))
        self.comboBox.setItemText(0, _translate("MainWindow", "Раз"))
        self.comboBox.setItemText(1, _translate("MainWindow", "Два"))
#       
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), 
            _translate("MainWindow", "Tab 1"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), 
            _translate("MainWindow", "Tab 2"))


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        
        self.tab_2.setStyleSheet(
# -------------------------------> vvvvvvvvvvvvvvvvvvvvvvv <--------------
            "background-image: url(:/Images/icons/back.png);")
# ----------------------------------------> ^^^^^ <-----------------------            
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/Images/icons/exit.png"))
# -------------------------------------------> ^^^^^ <--------------------
        self.pushButton.setIcon(icon)

        self.label.setText('Stack Overflow Tab 1 , Tab 2 Раз Два')  
        font = QFont()
        font.setFamily("Roboto Thin")                    # !!! +++ Roboto Thin
        font.setPointSize(27)
        self.label.setFont(font)
        self.label.setWordWrap(True)
        
        self.label_2 = QtWidgets.QLabel(self.tab)
        self.label_2.setWordWrap(True)
        self.label_2.setText('Stack Overflow Tab 1 , Tab 2 Раз Два')
        font_2 = QFont()
        font_2.setFamily("Roboto Regular")               # !!! +++ Roboto Regular
        font_2.setPointSize(27)
        self.label_2.setFont(font_2)
        self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)

        font = QtGui.QFont(fontName)                     # !!! + FontAwesome
        font.setPointSize(32)
        self.pushButton.setFont(font)  
        self.pushButton.setText(chr(0xf101))             # !!! + chr(0xf101)
        
        self.comboBox.setFont(font_2)                    # !!! +++ Roboto Regular
        
        self.tabWidget.setFont(font_2)                   # !!! +++ Roboto Regular

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
# !!! +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv    
    QtGui.QFontDatabase.addApplicationFont(':/Fonts/font/segoeui.ttf')
    
    fontId = QtGui.QFontDatabase.addApplicationFont(
        ':/Fonts/font/fontawesome-webfont.ttf')                               # !!!
    #print(f'\nfontId = {fontId} \n') 
    fontName = QFontDatabase.applicationFontFamilies(fontId)[0]
    print(f'fontName = {fontName} \n') 
    
    QtGui.QFontDatabase.addApplicationFont(':/Fonts/font/segoeuib.ttf')
    QtGui.QFontDatabase.addApplicationFont(':/Fonts/font/Roboto-Regular.ttf') # !!!
    QtGui.QFontDatabase.addApplicationFont(':/Fonts/font/Roboto-Thin.ttf')    # !!!  
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

Преобразовал q1506816.py в q1506816.exe:

pyinstaller -F -w q1506816.py

Запустил q1506816.exe

введите сюда описание изображения

введите сюда описание изображения

Все работает.