2 回答

TA貢獻2019條經驗 獲得超9個贊
感謝這里的另一個答案,我有一個完整的解決方案來解決我原來的問題。
看起來 Qt 只是簡單地硬編碼這些圖標而不考慮主題,但這很容易修復。
首先,我們使用相對亮度來決定顏色是否明亮,
def is_dark(qt_colour):
r, g, b = qt_colour.red(), qt_colour.green(), qt_colour.blue()
luminance = (0.2126*r + 0.7152*g + 0.0722*b)/256
return luminance < 0.5
在其源代碼樹中找到。我們將這些圖標放在img/子目錄/子文件夾中。
然后,我們獲取小部件的背景顏色,
bg_colour = self.items.palette().color(QtGui.QPalette.Background)
根據該顏色,我們將 CSS 設置為使用淺色或深色圖標集:
if is_dark(bg_colour):
self.items.setStyleSheet(
"""
QDockWidget
{
titlebar-close-icon: url(img/widget-close-light.svg);
titlebar-normal-icon: url(img/widget-undock-light.svg);
}
"""
)
else:
self.items.setStyleSheet(
"""
QDockWidget
{
titlebar-close-icon: url(img/widget-close.svg);
titlebar-normal-icon: url(img/widget-undock.svg);
}
"""
)
這會在淺色和深色主題中產生正確的圖標!
現在完整的代碼如下所示:
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
def is_dark(qt_colour):
r, g, b = qt_colour.red(), qt_colour.green(), qt_colour.blue()
luminance = (0.2126*r + 0.7152*g + 0.0722*b)/256
return luminance < 0.5
class dockdemo(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(dockdemo, self).__init__(parent)
self.items = QtWidgets.QDockWidget("Dockable", self)
self.listWidget = QtWidgets.QListWidget()
self.listWidget.addItem("item1")
self.listWidget.addItem("item2")
self.listWidget.addItem("item3")
self.items.setWidget(self.listWidget)
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.items)
bg_colour = self.items.palette().color(QtGui.QPalette.Background)
if is_dark(bg_colour):
self.items.setStyleSheet(
"""
QDockWidget
{
titlebar-close-icon: url(img/widget-close-light.svg);
titlebar-normal-icon: url(img/widget-undock-light.svg);
}
"""
)
else:
self.items.setStyleSheet(
"""
QDockWidget
{
titlebar-close-icon: url(img/widget-close.svg);
titlebar-normal-icon: url(img/widget-undock.svg);
}
"""
)
self.setWindowTitle("Dock demo")
def main():
app = QtWidgets.QApplication(sys.argv)
ex = dockdemo()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

TA貢獻1719條經驗 獲得超6個贊
不幸的是,Linux 默認的 Qt Fusion 樣式停靠圖標被硬編碼為 XPM 格式的圖像QFusionStyle(也是QCommonStyle其中的后備)。而且它們從不著色以匹配主題。許多“標準”圖標都是這樣,但許多是彩色/不透明的,因此背景并沒有太大的區別。
要覆蓋它們,您需要使用 CSS 或自定義QProxyStyle.
您可以從鏈接到的示例中看到它是如何在 CSS 中完成的。
QDockWidget
{
titlebar-close-icon: url(close.svg);
titlebar-normal-icon: url(restore.svg);
}
自定義 QStyle 涉及更多...
class AppStyle : public QProxyStyle
{
public:
using QProxyStyle::QProxyStyle;
QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const override
{
switch (standardIcon) {
case SP_TitleBarNormalButton:
return QIcon("restore.svg");
case SP_TitleBarCloseButton:
case SP_DockWidgetCloseButton:
return QIcon("close.svg");
default:
return baseStyle()->standardIcon(standardIcon, option, widget);
}
}
QPixmap standardPixmap(StandardPixmap stdPixmap, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const override
{
switch (stdPixmap) {
case SP_TitleBarNormalButton:
case SP_TitleBarCloseButton:
case SP_DockWidgetCloseButton:
return standardIcon(stdPixmap, option, widget).pixmap(option->rect.size());
default:
return baseStyle()->standardPixmap(stdPixmap, option, widget);
}
}
};
在這兩種情況下,您都需要知道以某種方式使用的主題(例如,它是黑暗的)。您將為每個主題使用不同的(或動態的)CSS,或者您的自定義QProxyStyle將返回正確的基本顏色圖標。例如,在 C++ 中,您甚至可以確定當前的調色板背景是否為暗(低顏色值),然后基于此返回不同的圖標。
PS 是的,它可能被認為是一個“錯誤”或缺陷,Qt 沒有為黑暗系統主題“自動”處理這個問題——無論桌面主題如何,嘗試將應用程序皮膚設置為黑暗時也很煩人。但是c'est la vie。
PPS 哎呀,剛剛意識到我為 Python 問題提供了一個 C++ 示例......我不使用 Python 和 Qt,所以恐怕這是我能做的最好的。
添加回答
舉報