0

I started to learn and use PySide2 and Qt about 2 weeks ago. I am working on a personal project based on PySide2 and I am trying to add a change font feature.

I found that the frame of QPushButton looks different while I am using some fonts.

DejaVu Sans Mono for Powerline dark JetBrains Mono dark

DejaVu Sans Mono for Powerline light JetBrain Mono light

No matter it is dark mode or light mode, the buttons look different. When I using fonts like DejaVu Sans Mono for Powerline, it is the macOS default looking, but when I change it to fonts like JetBrains Mono, it becomes another style. Other controls do not have this problem. Both fonts are based on ttf files and I do not figure out the relationship between the looking and the font.

What could be the reason and how can I keep the macOS default looking no matter what font I use?

Some information about the system and environments:

  • macOS Big Sur 11.3.1
  • Python 3.9.4
  • PySide2==5.15.2

And here is the source could reproduce this problem.

import os
import sys

os.environ["QT_MAC_WANTS_LAYER"] = "1"  # https://stackoverflow.com/a/66204842/1166461

from PySide2 import QtGui
from PySide2 import QtWidgets

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    window = QtWidgets.QWidget()
    layout = QtWidgets.QVBoxLayout()

    fonts = QtWidgets.QComboBox(window)
    fonts.insertItems(0, QtGui.QFontDatabase().families(QtGui.QFontDatabase.Latin))

    fonts.currentIndexChanged.connect(lambda i: QtWidgets.QApplication.instance().setStyleSheet(f'''
    * {{
        font-family: "{fonts.itemText(i)}";
    }}
    '''))

    layout.addWidget(fonts)
    layout.addWidget(QtWidgets.QPushButton('I am a push button', parent=window))
    window.setLayout(layout)

    window.show()
    sys.exit(app.exec_())
Programus
  • 338
  • 2
  • 16

1 Answers1

1

Finally, I figured out the reason by myself. Leave this answer here for someone might be confused by the same problem.

The reason that the button frame changed is not the font but the size, or the height of the button. If the button's height is more than 30px, the frame will change.

In this document about QPushButton, it says:

Note

On macOS when a push button’s width becomes smaller than 50 or its height becomes smaller than 30, the button’s corners are changed from round to square. Use the setMinimumSize() function to prevent this behavior.

But actually, according to my experiments, the width does not affect the shape of the button, only when the height becomes bigger than 30, the button will change to square frame.

As a solution, I add this css to keep it to the round style.

QPushButton {
  max-height: 30px;
}

So the complete source become

import os
import sys

os.environ["QT_MAC_WANTS_LAYER"] = "1"  # https://stackoverflow.com/a/66204842/1166461

from PySide2 import QtGui
from PySide2 import QtWidgets

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    window = QtWidgets.QWidget()
    layout = QtWidgets.QVBoxLayout()
    window.setLayout(layout)

    fonts = QtWidgets.QComboBox(window)
    fonts.insertItems(0, QtGui.QFontDatabase().families(QtGui.QFontDatabase.Latin))

    fonts.currentIndexChanged.connect(lambda i: QtWidgets.QApplication.instance().setStyleSheet(f'''
    * {{
        font-family: "{fonts.itemText(i)}";
    }}
    QPushButton {{
        max-height: 30px;
    }}
    '''))

    layout.addWidget(fonts)
    layout.addWidget(QtWidgets.QPushButton('I am a push button', parent=window))

    window.show()
    sys.exit(app.exec_())
Programus
  • 338
  • 2
  • 16