Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
This is another stylesheet for PySide6, PySide2, PyQt5 and PyQt6, which looks like Material Design (close enough).
There is some custom dark themes: And light:
pip install qt-material
import sys
from PySide6 import QtWidgets
# from PySide2 import QtWidgets
# from PyQt5 import QtWidgets
from qt_material import apply_stylesheet
# create the application and the main window
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
# setup stylesheet
apply_stylesheet(app, theme='dark_teal.xml')
# run
window.show()
app.exec_()
from qt_material import list_themes
list_themes()
WARNING:root:qt_material must be imported after PySide or PyQt!
['dark_amber.xml',
'dark_blue.xml',
'dark_cyan.xml',
'dark_lightgreen.xml',
'dark_pink.xml',
'dark_purple.xml',
'dark_red.xml',
'dark_teal.xml',
'dark_yellow.xml',
'light_amber.xml',
'light_blue.xml',
'light_cyan.xml',
'light_cyan_500.xml',
'light_lightgreen.xml',
'light_pink.xml',
'light_purple.xml',
'light_red.xml',
'light_teal.xml',
'light_yellow.xml']
Color Tool is the best way to generate new themes, just choose colors and export as Android XML
, the theme file must look like:
<!--?xml version="1.0" encoding="UTF-8"?-->
<resources>
<color name="primaryColor">#00e5ff</color>
<color name="primaryLightColor">#6effff</color>
<color name="secondaryColor">#f5f5f5</color>
<color name="secondaryLightColor">#ffffff</color>
<color name="secondaryDarkColor">#e6e6e6</color>
<color name="primaryTextColor">#000000</color>
<color name="secondaryTextColor">#000000</color>
</resources>
Save it as my_theme.xml
or similar and apply the style sheet from Python.
apply_stylesheet(app, theme='dark_teal.xml')
Light themes will need to add invert_secondary
argument as True
.
apply_stylesheet(app, theme='light_red.xml', invert_secondary=True)
There is a environ variables related to the current theme used, these variables are for consult purpose only.
Environ variable | Description | Example |
---|---|---|
QTMATERIAL_PRIMARYCOLOR | Primary color | #2979ff |
QTMATERIAL_PRIMARYLIGHTCOLOR | A bright version of the primary color | #75a7ff |
QTMATERIAL_SECONDARYCOLOR | Secondary color | #f5f5f5 |
QTMATERIAL_SECONDARYLIGHTCOLOR | A bright version of the secondary color | #ffffff |
QTMATERIAL_SECONDARYDARKCOLOR | A dark version of the primary color | #e6e6e6 |
QTMATERIAL_PRIMARYTEXTCOLOR | Color for text over primary background | #000000 |
QTMATERIAL_SECONDARYTEXTCOLOR | Color for text over secondary background | #000000 |
QTMATERIAL_THEME | Name of theme used | light_blue.xml |
There is an extra
argument for accent colors and custom fonts.
extra = {
# Button colors
'danger': '#dc3545',
'warning': '#ffc107',
'success': '#17a2b8',
# Font
'font_family': 'Roboto',
}
apply_stylesheet(app, 'light_cyan.xml', invert_secondary=True, extra=extra)
The accent colors are applied to QPushButton
with the corresponding class
property:
pushButton_danger.setProperty('class', 'danger')
pushButton_warning.setProperty('class', 'warning')
pushButton_success.setProperty('class', 'success')
Custom changes can be performed by overwriting the stylesheets, for example:
QPushButton {{
color: {QTMATERIAL_SECONDARYCOLOR};
text-transform: none;
background-color: {QTMATERIAL_PRIMARYCOLOR};
}}
.big_button {{
height: 64px;
}}
Then, the current stylesheet can be extended just with:
apply_stylesheet(app, theme='light_blue.xml', css_file='custom.css')
The stylesheet can also be changed on runtime by:
stylesheet = app.styleSheet()
with open('custom.css') as file:
app.setStyleSheet(stylesheet + file.read().format(**os.environ))
And the class style can be applied with the setProperty
method:
self.main.pushButton.setProperty('class', 'big_button')
A window with almost all widgets (see the previous screenshots) are available to test all themes and create new ones.
git clone https://github.com/UN-GCPDS/qt-material.git
cd qt-material
python setup.py install
cd examples/full_features
python main.py --pyside6
Do you have a custom theme? it looks good? create a pull request in themes folder and share it with all users.
There is a qt_material.QtStyleTools
class that must be inherited along to QMainWindow
for change themes in runtime using the apply_stylesheet()
method.
class RuntimeStylesheets(QMainWindow, QtStyleTools):
def __init__(self):
super().__init__()
self.main = QUiLoader().load('main_window.ui', self)
self.apply_stylesheet(self.main, 'dark_teal.xml')
# self.apply_stylesheet(self.main, 'light_red.xml')
# self.apply_stylesheet(self.main, 'light_blue.xml')
A custom stylesheets menu can be added to a project for switching across all default available themes.
class RuntimeStylesheets(QMainWindow, QtStyleTools):
def __init__(self):
super().__init__()
self.main = QUiLoader().load('main_window.ui', self)
self.add_menu_theme(self.main, self.main.menuStyles)
A simple interface is available to modify a theme in runtime, this feature can be used to create a new theme, the theme file is created in the main directory as my_theme.xml
class RuntimeStylesheets(QMainWindow, QtStyleTools):
def __init__(self):
super().__init__()
self.main = QUiLoader().load('main_window.ui', self)
self.show_dock_theme(self.main)
A full set of examples are available in the exmaples directory
This feature able to use qt-material
themes into Qt
implementations using only local files.
from qt_material import export_theme
extra = {
# Button colors
'danger': '#dc3545',
'warning': '#ffc107',
'success': '#17a2b8',
# Font
'font_family': 'monoespace',
'font_size': '13px',
'line_height': '13px',
# Density Scale
'density_scale': '0',
# environ
'pyside6': True,
'linux': True,
}
export_theme(theme='dark_teal.xml',
qss='dark_teal.qss',
rcc='resources.rcc',
output='theme',
prefix='icon:/',
invert_secondary=False,
extra=extra,
)
This script will generate both dark_teal.qss
and resources.rcc
and a folder with all theme icons called theme
.
The files generated can be integrated into a PySide6
application just with:
import sys
from PySide6 import QtWidgets
from PySide6.QtCore import QDir
from __feature__ import snake_case, true_property
# Create application
app = QtWidgets.QApplication(sys.argv)
# Load styles
with open('dark_teal.qss', 'r') as file:
app.style_sheet = file.read()
# Load icons
QDir.add_search_path('icon', 'theme')
# App
window = QtWidgets.QMainWindow()
checkbox = QtWidgets.QCheckBox(window)
checkbox.text = 'CheckBox'
window.show()
app.exec()
This files can also be used into non Python
environs like C++
.
The extra
arguments also include an option to set the density scale, by default is 0
.
extra = {
# Density Scale
'density_scale': '-2',
}
apply_stylesheet(app, 'default', invert_secondary=False, extra=extra)
QMenu
has multiple rendering for each Qt backend, and for each operating system. Even can be related with the style, like fusion. Then, the extra
argument also supportsQMenu
parameters to configure this widgest for specific combinations. This options are not affected by density scale.
extra['QMenu'] = {
'height': 50,
'padding': '50px 50px 50px 50px', # top, right, bottom, left
}
FAQs
Material inspired stylesheet for PySide2, PySide6, PyQt5 and PyQt6.
We found that qt-material demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.