PyQt5 Linux Mint Cinnamon 原生 'delete'、'apply' 按钮
PyQt5 Linux Mint Cinnamon native 'delete', 'apply' buttons
我正在尝试在 Linux mint 19(肉桂色)上创建一个 pyqt5 应用程序。
我有一个 'delete' 和 'apply' 按钮,但我想给它们更相关的外观。喜欢这张照片:
原生 Linux 薄荷纽扣
更多
它是 linux mint 上具有应用或删除角色的按钮的原生外观,我想在我的应用程序中创建这样的按钮,但我还没有找到这样做的方法。
似乎 windows 和 mac 有 qtmacextras
和 qtwinextras
模块来处理这些东西。 Linux 有某种 qtx11extras
,但该模块不提供此类功能。
您可以根据自己的喜好使用样式sheet进行设计。
这是一个独立的例子。当然,您必须根据您喜欢的颜色和尺寸对其进行调整。但这应该已经提供了一个起点。
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
GREEN_BUTTON_STYLE = """
QPushButton {
border: 4px solid black;
border-radius: 4px;
color: #ffffff;
background-color: #6db442;
font-size: 28px;
min-height: 40px;
min-width: 128px;
}
QPushButton:pressed {
background-color: #646464;
}
QPushButton:flat {
border: none;
}
"""
RED_BUTTON_STYLE = """
QPushButton {
border: 4px solid black;
border-radius: 4px;
color: #ffffff;
background-color: #f04a50;
font-size: 26px;
min-height: 40px;
min-width: 128px;
}
QPushButton:pressed {
background-color: #646464;
}
QPushButton:flat {
border: none;
}
"""
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'button styles'
self.init_ui()
def init_ui(self):
self.setWindowTitle(self.title)
self.setGeometry(256, 128, 384, 256)
button1 = QPushButton('Launch')
button1.setStyleSheet(GREEN_BUTTON_STYLE)
button1.setFlat(True)
button1.clicked.connect(self.on_click)
button2 = QPushButton('Remove')
button2.setStyleSheet(RED_BUTTON_STYLE)
button2.setFlat(True)
button2.clicked.connect(self.on_click)
layout = QHBoxLayout()
layout.addWidget(button1, alignment=Qt.AlignHCenter)
layout.addWidget(button2, alignment=Qt.AlignHCenter)
self.setLayout(layout)
self.setStyleSheet("background-color:#333333;")
self.show()
def on_click(self):
print('clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
输出
看起来像这样:
虽然已经提供的解决方案工作得很好,但并不是完全适用于应用程序,尤其是当您想要控制对话框按钮的外观时。
即使您将样式表应用于应用程序,您也需要确保在父项中正确设置选择器:在另一个答案中,例如,设置没有选择器的背景 属性 将清除子项的应用样式表继承。
假设样式表设置为应用程序并且所有其他样式表设置都经过仔细编写,问题来自对话框 windows。
如果对话框是手动创建的,则可以通过为每个需要备用颜色的按钮指定样式表来设置备用颜色,但这对于使用静态函数创建的按钮是不可能的。
在那种情况下,唯一的可能就是使用QProxyStyle。以下是一个可能的实现,它还允许设置自定义颜色和字体,并自动为对话框按钮框的 "negative" 角色(取消、忽略等)设置替代颜色。
在此示例中,我只是将样式应用于应用程序,但消息框是使用 information()
静态函数创建的。 "Alternate" 按钮使用自定义 属性 手动设置:button.setProperty('alternateColor', True)
.
class ColorButtonStyle(QtWidgets.QProxyStyle):
def __init__(self, *args, **kwargs):
if isinstance(kwargs.get('buttonFont'), QtGui.QFont):
self._buttonFont = kwargs.pop('buttonFont')
else:
self._buttonFont = QtWidgets.QApplication.font()
self._buttonFont.setPointSize(20)
super().__init__(*args, **kwargs)
self._buttonFontMetrics = QtGui.QFontMetrics(self._buttonFont)
self._defaultButtonColor = QtGui.QColor(109, 180, 66)
self._defaultTextColor = QtGui.QColor(QtCore.Qt.white)
self._alternateButtonColor = QtGui.QColor(240, 74, 80)
self._alternateTextColor = None
self._alternateRoles = set((
QtWidgets.QDialogButtonBox.RejectRole,
QtWidgets.QDialogButtonBox.DestructiveRole,
QtWidgets.QDialogButtonBox.NoRole,
))
def _polishApp(self):
self.polish(QtWidgets.QApplication.instance())
def buttonFont(self):
return QtGui.QFont(self._buttonFont)
@QtCore.pyqtSlot(QtGui.QFont)
def setButtonFont(self, font):
if not isinstance(font, QtGui.QFont) or font == self._buttonFont:
return
self._buttonFont = font
self._buttonFontMetrics = QtGui.QFontMetrics(self._buttonFont)
self._polishApp()
def defaultButtonColor(self):
return QtGui.QColor(self._defaultButtonColor)
@QtCore.pyqtSlot(QtCore.Qt.GlobalColor)
@QtCore.pyqtSlot(QtGui.QColor)
def setDefaultButtonColor(self, color):
if isinstance(color, QtCore.Qt.GlobalColor):
color = QtGui.QColor(color)
elif not isinstance(color, QtGui.QColor):
return
self._defaultButtonColor = color
self._polishApp()
def alternateButtonColor(self):
return QtGui.QColor(self._alternateButtonColor)
@QtCore.pyqtSlot(QtCore.Qt.GlobalColor)
@QtCore.pyqtSlot(QtGui.QColor)
def setAlternateButtonColor(self, color):
if isinstance(color, QtCore.Qt.GlobalColor):
color = QtGui.QColor(color)
elif not isinstance(color, QtGui.QColor):
return
self._alternateButtonColor = color
self._polishApp()
def alternateRoles(self):
return self._alternateRoles
def setAlternateRoles(self, roles):
newRoles = set()
for role in roles:
if isinstance(role, QtWidgets.QDialogButtonBox.ButtonRole):
newRoles.add(role)
if newRoles != self._alternateRoles:
self._alternateRoles = newRoles
self._polishApp()
def setAlternateRole(self, role, activate=True):
if isinstance(role, QtWidgets.QDialogButtonBox.ButtonRole):
if activate and role in self._alternateRoles:
self._alternateRoles.add(role)
self._polishApp()
elif not activate and role not in self._alternateRoles:
self._alternateRoles.remove(role)
self._polishApp()
def defaultTextColor(self):
return QtGui.QColor(self._defaultTextColor)
@QtCore.pyqtSlot(QtCore.Qt.GlobalColor)
@QtCore.pyqtSlot(QtGui.QColor)
def setDefaultTextColor(self, color):
if isinstance(color, QtCore.Qt.GlobalColor):
color = QtGui.QColor(color)
elif not isinstance(color, QtGui.QColor):
return
self._defaultTextColor = color
self._polishApp()
def alternateTextColor(self):
return QtGui.QColor(self._alternateTextColor or self._defaultTextColor)
@QtCore.pyqtSlot(QtCore.Qt.GlobalColor)
@QtCore.pyqtSlot(QtGui.QColor)
def setAlternateTextColor(self, color):
if isinstance(color, QtCore.Qt.GlobalColor):
color = QtGui.QColor(color)
elif not isinstance(color, QtGui.QColor):
return
self._alternateTextColor = color
self._polishApp()
def drawControl(self, element, option, painter, widget):
if element == self.CE_PushButton:
isAlternate = False
if widget and isinstance(widget.parent(), QtWidgets.QDialogButtonBox):
role = widget.parent().buttonRole(widget)
if role in self._alternateRoles:
isAlternate = True
elif widget.property('alternateColor'):
isAlternate = True
if isAlternate:
color = self.alternateButtonColor()
textColor = self.alternateTextColor()
else:
color = self.defaultButtonColor()
textColor = self.defaultTextColor()
if not option.state & self.State_Enabled:
color.setAlpha(color.alpha() * .75)
textColor.setAlpha(textColor.alpha() * .75)
# switch the existing palette with a new one created from it;
# this shouldn't be necessary, but better safe than sorry
oldPalette = option.palette
palette = QtGui.QPalette(oldPalette)
palette.setColor(palette.ButtonText, textColor)
# some styles use WindowText for flat buttons
palette.setColor(palette.WindowText, textColor)
option.palette = palette
# colors that are almost black are not very affected by "lighter"
if color.value() < 32:
lightColor = QtGui.QColor(48, 48, 48, color.alpha())
else:
lightColor = color.lighter(115)
darkColor = color.darker()
if option.state & self.State_MouseOver:
# colors that are almost black are not very affected by "lighter"
bgColor = lightColor
lighterColor = lightColor.lighter(115)
darkerColor = darkColor.darker(115)
else:
bgColor = color
lighterColor = lightColor
darkerColor = darkColor
if option.state & self.State_Raised and not option.state & self.State_On:
topLeftPen = QtGui.QPen(lighterColor)
bottomRightPen = QtGui.QPen(darkerColor)
elif option.state & (self.State_On | self.State_Sunken):
if option.state & self.State_On:
bgColor = bgColor.darker()
else:
bgColor = bgColor.darker(125)
topLeftPen = QtGui.QPen(darkColor)
bottomRightPen = QtGui.QPen(lighterColor)
else:
topLeftPen = bottomRightPen = QtGui.QPen(bgColor)
painter.save()
painter.setRenderHints(painter.Antialiasing)
painter.translate(.5, .5)
rect = option.rect.adjusted(0, 0, -1, -1)
painter.setBrush(bgColor)
painter.setPen(QtCore.Qt.NoPen)
painter.drawRoundedRect(rect, 2, 2)
if topLeftPen != bottomRightPen:
roundRect = QtCore.QRectF(0, 0, 4, 4)
painter.setBrush(QtCore.Qt.NoBrush)
# the top and left borders
tlPath = QtGui.QPainterPath()
tlPath.arcMoveTo(roundRect.translated(0, rect.height() - 4), 225)
tlPath.arcTo(roundRect.translated(0, rect.height() - 4), 225, -45)
tlPath.arcTo(roundRect, 180, -90)
tlPath.arcTo(roundRect.translated(rect.width() - 4, 0), 90, -45)
painter.setPen(topLeftPen)
painter.drawPath(tlPath)
# the bottom and right borders
brPath = QtGui.QPainterPath(tlPath.currentPosition())
brPath.arcTo(roundRect.translated(rect.width() - 4, 0), 45, -45)
brPath.arcTo(
roundRect.translated(rect.width() - 4, rect.height() - 4), 0, -90)
brPath.arcTo(
roundRect.translated(0, rect.height() - 4), 270, -45)
painter.setPen(bottomRightPen)
painter.drawPath(brPath)
if option.state & self.State_HasFocus:
focusColor = QtGui.QColor(textColor).darker()
focusColor.setAlpha(focusColor.alpha() * .75)
painter.setPen(focusColor)
painter.setBrush(QtCore.Qt.NoBrush)
painter.drawRoundedRect(rect.adjusted(2, 2, -2, -2), 2, 2)
painter.setFont(self._buttonFont)
oldMetrics = option.fontMetrics
option.fontMetrics = self._buttonFontMetrics
self.drawControl(self.CE_PushButtonLabel, option, painter, widget)
painter.restore()
# restore the original font metrics and palette
option.fontMetrics = oldMetrics
option.palette = oldPalette
return
super().drawControl(element, option, painter, widget)
def sizeFromContents(self, contentsType, option, size, widget=None):
if contentsType == self.CT_PushButton:
if option.text:
textSize = option.fontMetrics.size(
QtCore.Qt.TextShowMnemonic, option.text)
baseWidth = size.width() - textSize.width()
baseHeight = size.height() - textSize.height()
text = option.text
else:
baseWidth = size.width()
baseHeight = size.height()
text = 'XXXX' if not option.icon else ''
buttonTextSize = self._buttonFontMetrics.size(
QtCore.Qt.TextShowMnemonic, text)
if not widget or widget.font() != QtWidgets.QApplication.font():
buttonTextSize = buttonTextSize.expandedTo(
QtWidgets.QApplication.fontMetrics().size(
QtCore.Qt.TextShowMnemonic, text))
margin = self.pixelMetric(self.PM_ButtonMargin, option, widget)
newSize = QtCore.QSize(
buttonTextSize.width() + baseWidth + margin * 2,
buttonTextSize.height() + baseHeight + margin)
return newSize.expandedTo(
super().sizeFromContents(contentsType, option, size, widget))
return super().sizeFromContents(contentsType, option, size, widget)
app = QtWidgets.QApplication(sys.argv)
app.setStyle(ColorButtonStyle())
# ...
从这里开始,您还可以添加其他属性以更好地控制样式,例如圆角矩形的半径(只需将边框绘图中的每个“4”替换为您的变量,并使用一半绘制背景它):
painter.drawRoundedRect(rect, self._radius / 2, self._radius / 2)
if topLeftPen != bottomRightPen:
roundRect = QtCore.QRectF(0, 0, self._radius, self._radius)
painter.setBrush(QtCore.Qt.NoBrush)
# the top and left borders
tlPath = QtGui.QPainterPath()
tlPath.arcMoveTo(roundRect.translated(
0, rect.height() - self._radius), 225)
tlPath.arcTo(roundRect.translated(
0, rect.height() - self._radius), 225, -45)
我正在尝试在 Linux mint 19(肉桂色)上创建一个 pyqt5 应用程序。 我有一个 'delete' 和 'apply' 按钮,但我想给它们更相关的外观。喜欢这张照片:
原生 Linux 薄荷纽扣
更多
它是 linux mint 上具有应用或删除角色的按钮的原生外观,我想在我的应用程序中创建这样的按钮,但我还没有找到这样做的方法。
似乎 windows 和 mac 有 qtmacextras
和 qtwinextras
模块来处理这些东西。 Linux 有某种 qtx11extras
,但该模块不提供此类功能。
您可以根据自己的喜好使用样式sheet进行设计。
这是一个独立的例子。当然,您必须根据您喜欢的颜色和尺寸对其进行调整。但这应该已经提供了一个起点。
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
GREEN_BUTTON_STYLE = """
QPushButton {
border: 4px solid black;
border-radius: 4px;
color: #ffffff;
background-color: #6db442;
font-size: 28px;
min-height: 40px;
min-width: 128px;
}
QPushButton:pressed {
background-color: #646464;
}
QPushButton:flat {
border: none;
}
"""
RED_BUTTON_STYLE = """
QPushButton {
border: 4px solid black;
border-radius: 4px;
color: #ffffff;
background-color: #f04a50;
font-size: 26px;
min-height: 40px;
min-width: 128px;
}
QPushButton:pressed {
background-color: #646464;
}
QPushButton:flat {
border: none;
}
"""
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'button styles'
self.init_ui()
def init_ui(self):
self.setWindowTitle(self.title)
self.setGeometry(256, 128, 384, 256)
button1 = QPushButton('Launch')
button1.setStyleSheet(GREEN_BUTTON_STYLE)
button1.setFlat(True)
button1.clicked.connect(self.on_click)
button2 = QPushButton('Remove')
button2.setStyleSheet(RED_BUTTON_STYLE)
button2.setFlat(True)
button2.clicked.connect(self.on_click)
layout = QHBoxLayout()
layout.addWidget(button1, alignment=Qt.AlignHCenter)
layout.addWidget(button2, alignment=Qt.AlignHCenter)
self.setLayout(layout)
self.setStyleSheet("background-color:#333333;")
self.show()
def on_click(self):
print('clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
输出
看起来像这样:
虽然已经提供的解决方案工作得很好,但并不是完全适用于应用程序,尤其是当您想要控制对话框按钮的外观时。
即使您将样式表应用于应用程序,您也需要确保在父项中正确设置选择器:在另一个答案中,例如,设置没有选择器的背景 属性 将清除子项的应用样式表继承。
假设样式表设置为应用程序并且所有其他样式表设置都经过仔细编写,问题来自对话框 windows。
如果对话框是手动创建的,则可以通过为每个需要备用颜色的按钮指定样式表来设置备用颜色,但这对于使用静态函数创建的按钮是不可能的。
在那种情况下,唯一的可能就是使用QProxyStyle。以下是一个可能的实现,它还允许设置自定义颜色和字体,并自动为对话框按钮框的 "negative" 角色(取消、忽略等)设置替代颜色。
在此示例中,我只是将样式应用于应用程序,但消息框是使用 information()
静态函数创建的。 "Alternate" 按钮使用自定义 属性 手动设置:button.setProperty('alternateColor', True)
.
class ColorButtonStyle(QtWidgets.QProxyStyle):
def __init__(self, *args, **kwargs):
if isinstance(kwargs.get('buttonFont'), QtGui.QFont):
self._buttonFont = kwargs.pop('buttonFont')
else:
self._buttonFont = QtWidgets.QApplication.font()
self._buttonFont.setPointSize(20)
super().__init__(*args, **kwargs)
self._buttonFontMetrics = QtGui.QFontMetrics(self._buttonFont)
self._defaultButtonColor = QtGui.QColor(109, 180, 66)
self._defaultTextColor = QtGui.QColor(QtCore.Qt.white)
self._alternateButtonColor = QtGui.QColor(240, 74, 80)
self._alternateTextColor = None
self._alternateRoles = set((
QtWidgets.QDialogButtonBox.RejectRole,
QtWidgets.QDialogButtonBox.DestructiveRole,
QtWidgets.QDialogButtonBox.NoRole,
))
def _polishApp(self):
self.polish(QtWidgets.QApplication.instance())
def buttonFont(self):
return QtGui.QFont(self._buttonFont)
@QtCore.pyqtSlot(QtGui.QFont)
def setButtonFont(self, font):
if not isinstance(font, QtGui.QFont) or font == self._buttonFont:
return
self._buttonFont = font
self._buttonFontMetrics = QtGui.QFontMetrics(self._buttonFont)
self._polishApp()
def defaultButtonColor(self):
return QtGui.QColor(self._defaultButtonColor)
@QtCore.pyqtSlot(QtCore.Qt.GlobalColor)
@QtCore.pyqtSlot(QtGui.QColor)
def setDefaultButtonColor(self, color):
if isinstance(color, QtCore.Qt.GlobalColor):
color = QtGui.QColor(color)
elif not isinstance(color, QtGui.QColor):
return
self._defaultButtonColor = color
self._polishApp()
def alternateButtonColor(self):
return QtGui.QColor(self._alternateButtonColor)
@QtCore.pyqtSlot(QtCore.Qt.GlobalColor)
@QtCore.pyqtSlot(QtGui.QColor)
def setAlternateButtonColor(self, color):
if isinstance(color, QtCore.Qt.GlobalColor):
color = QtGui.QColor(color)
elif not isinstance(color, QtGui.QColor):
return
self._alternateButtonColor = color
self._polishApp()
def alternateRoles(self):
return self._alternateRoles
def setAlternateRoles(self, roles):
newRoles = set()
for role in roles:
if isinstance(role, QtWidgets.QDialogButtonBox.ButtonRole):
newRoles.add(role)
if newRoles != self._alternateRoles:
self._alternateRoles = newRoles
self._polishApp()
def setAlternateRole(self, role, activate=True):
if isinstance(role, QtWidgets.QDialogButtonBox.ButtonRole):
if activate and role in self._alternateRoles:
self._alternateRoles.add(role)
self._polishApp()
elif not activate and role not in self._alternateRoles:
self._alternateRoles.remove(role)
self._polishApp()
def defaultTextColor(self):
return QtGui.QColor(self._defaultTextColor)
@QtCore.pyqtSlot(QtCore.Qt.GlobalColor)
@QtCore.pyqtSlot(QtGui.QColor)
def setDefaultTextColor(self, color):
if isinstance(color, QtCore.Qt.GlobalColor):
color = QtGui.QColor(color)
elif not isinstance(color, QtGui.QColor):
return
self._defaultTextColor = color
self._polishApp()
def alternateTextColor(self):
return QtGui.QColor(self._alternateTextColor or self._defaultTextColor)
@QtCore.pyqtSlot(QtCore.Qt.GlobalColor)
@QtCore.pyqtSlot(QtGui.QColor)
def setAlternateTextColor(self, color):
if isinstance(color, QtCore.Qt.GlobalColor):
color = QtGui.QColor(color)
elif not isinstance(color, QtGui.QColor):
return
self._alternateTextColor = color
self._polishApp()
def drawControl(self, element, option, painter, widget):
if element == self.CE_PushButton:
isAlternate = False
if widget and isinstance(widget.parent(), QtWidgets.QDialogButtonBox):
role = widget.parent().buttonRole(widget)
if role in self._alternateRoles:
isAlternate = True
elif widget.property('alternateColor'):
isAlternate = True
if isAlternate:
color = self.alternateButtonColor()
textColor = self.alternateTextColor()
else:
color = self.defaultButtonColor()
textColor = self.defaultTextColor()
if not option.state & self.State_Enabled:
color.setAlpha(color.alpha() * .75)
textColor.setAlpha(textColor.alpha() * .75)
# switch the existing palette with a new one created from it;
# this shouldn't be necessary, but better safe than sorry
oldPalette = option.palette
palette = QtGui.QPalette(oldPalette)
palette.setColor(palette.ButtonText, textColor)
# some styles use WindowText for flat buttons
palette.setColor(palette.WindowText, textColor)
option.palette = palette
# colors that are almost black are not very affected by "lighter"
if color.value() < 32:
lightColor = QtGui.QColor(48, 48, 48, color.alpha())
else:
lightColor = color.lighter(115)
darkColor = color.darker()
if option.state & self.State_MouseOver:
# colors that are almost black are not very affected by "lighter"
bgColor = lightColor
lighterColor = lightColor.lighter(115)
darkerColor = darkColor.darker(115)
else:
bgColor = color
lighterColor = lightColor
darkerColor = darkColor
if option.state & self.State_Raised and not option.state & self.State_On:
topLeftPen = QtGui.QPen(lighterColor)
bottomRightPen = QtGui.QPen(darkerColor)
elif option.state & (self.State_On | self.State_Sunken):
if option.state & self.State_On:
bgColor = bgColor.darker()
else:
bgColor = bgColor.darker(125)
topLeftPen = QtGui.QPen(darkColor)
bottomRightPen = QtGui.QPen(lighterColor)
else:
topLeftPen = bottomRightPen = QtGui.QPen(bgColor)
painter.save()
painter.setRenderHints(painter.Antialiasing)
painter.translate(.5, .5)
rect = option.rect.adjusted(0, 0, -1, -1)
painter.setBrush(bgColor)
painter.setPen(QtCore.Qt.NoPen)
painter.drawRoundedRect(rect, 2, 2)
if topLeftPen != bottomRightPen:
roundRect = QtCore.QRectF(0, 0, 4, 4)
painter.setBrush(QtCore.Qt.NoBrush)
# the top and left borders
tlPath = QtGui.QPainterPath()
tlPath.arcMoveTo(roundRect.translated(0, rect.height() - 4), 225)
tlPath.arcTo(roundRect.translated(0, rect.height() - 4), 225, -45)
tlPath.arcTo(roundRect, 180, -90)
tlPath.arcTo(roundRect.translated(rect.width() - 4, 0), 90, -45)
painter.setPen(topLeftPen)
painter.drawPath(tlPath)
# the bottom and right borders
brPath = QtGui.QPainterPath(tlPath.currentPosition())
brPath.arcTo(roundRect.translated(rect.width() - 4, 0), 45, -45)
brPath.arcTo(
roundRect.translated(rect.width() - 4, rect.height() - 4), 0, -90)
brPath.arcTo(
roundRect.translated(0, rect.height() - 4), 270, -45)
painter.setPen(bottomRightPen)
painter.drawPath(brPath)
if option.state & self.State_HasFocus:
focusColor = QtGui.QColor(textColor).darker()
focusColor.setAlpha(focusColor.alpha() * .75)
painter.setPen(focusColor)
painter.setBrush(QtCore.Qt.NoBrush)
painter.drawRoundedRect(rect.adjusted(2, 2, -2, -2), 2, 2)
painter.setFont(self._buttonFont)
oldMetrics = option.fontMetrics
option.fontMetrics = self._buttonFontMetrics
self.drawControl(self.CE_PushButtonLabel, option, painter, widget)
painter.restore()
# restore the original font metrics and palette
option.fontMetrics = oldMetrics
option.palette = oldPalette
return
super().drawControl(element, option, painter, widget)
def sizeFromContents(self, contentsType, option, size, widget=None):
if contentsType == self.CT_PushButton:
if option.text:
textSize = option.fontMetrics.size(
QtCore.Qt.TextShowMnemonic, option.text)
baseWidth = size.width() - textSize.width()
baseHeight = size.height() - textSize.height()
text = option.text
else:
baseWidth = size.width()
baseHeight = size.height()
text = 'XXXX' if not option.icon else ''
buttonTextSize = self._buttonFontMetrics.size(
QtCore.Qt.TextShowMnemonic, text)
if not widget or widget.font() != QtWidgets.QApplication.font():
buttonTextSize = buttonTextSize.expandedTo(
QtWidgets.QApplication.fontMetrics().size(
QtCore.Qt.TextShowMnemonic, text))
margin = self.pixelMetric(self.PM_ButtonMargin, option, widget)
newSize = QtCore.QSize(
buttonTextSize.width() + baseWidth + margin * 2,
buttonTextSize.height() + baseHeight + margin)
return newSize.expandedTo(
super().sizeFromContents(contentsType, option, size, widget))
return super().sizeFromContents(contentsType, option, size, widget)
app = QtWidgets.QApplication(sys.argv)
app.setStyle(ColorButtonStyle())
# ...
从这里开始,您还可以添加其他属性以更好地控制样式,例如圆角矩形的半径(只需将边框绘图中的每个“4”替换为您的变量,并使用一半绘制背景它):
painter.drawRoundedRect(rect, self._radius / 2, self._radius / 2)
if topLeftPen != bottomRightPen:
roundRect = QtCore.QRectF(0, 0, self._radius, self._radius)
painter.setBrush(QtCore.Qt.NoBrush)
# the top and left borders
tlPath = QtGui.QPainterPath()
tlPath.arcMoveTo(roundRect.translated(
0, rect.height() - self._radius), 225)
tlPath.arcTo(roundRect.translated(
0, rect.height() - self._radius), 225, -45)