我的目標是制作一個組合框,僅當滑鼠懸停在其上方時才顯示向下箭頭。為此,我將 QComboBox 子類化并重新實作了 enterEvent 和 leaveEvent ,這將相應地更改其樣式表。它按預期作業,何時顯示視窗,隱藏向下箭頭,當滑鼠懸停在組合框上方時,顯示向下箭頭。然后,當滑鼠單擊組合框文本時,下拉串列顯示并且向下箭頭再次變為不可見(我可以處理,但如果有人有解決方案,我會全力以赴)。主要問題是當滑鼠單擊下拉箭頭時,它不僅隱藏了下拉箭頭,就像滑鼠單擊文本時那樣,它還隱藏了文本以及下拉箭頭。我做了一些測驗以找出什么' s 導致問題,似乎在 QApplication 上呼叫 setEffectEnabled(Qt.UIEffect.UI_AnimateCombo, False) 是問題所在,盡管我不知道禁用下拉影片與單擊下拉箭頭時使文本消失有何關系。另外,如果有人有更優雅的方式來做我想做的事,我再次全神貫注:)。這是示例代碼:
import sys
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtGui import QEnterEvent
from PyQt5.QtWidgets import QApplication, QMainWindow, QComboBox, QWidget
class TestComboBox(QComboBox):
def __init__(self, parent=None):
super().__init__(parent)
self.default_stylesheet = '''
QComboBox {
background-color: rgba(0, 0, 0, 0);
}
QComboBox QAbstractItemView {
background-color: white;
min-width: 150px;
}'''
self.hide_down_arrow_stylesheet = '''QComboBox::down-arrow { \
background-color: rgba(0, 0, 0, 0);}'''
self.setStyleSheet(self.default_stylesheet self.hide_down_arrow_stylesheet)
def enterEvent(self, event: QEnterEvent) -> None:
self.setStyleSheet(self.default_stylesheet)
super().enterEvent(event)
def leaveEvent(self, event: QEvent) -> None:
self.setStyleSheet(self.default_stylesheet self.hide_down_arrow_stylesheet)
super().leaveEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.widget = QWidget(self)
self.setCentralWidget(self.widget)
self.combobox = TestComboBox(self.widget)
self.combobox.resize(180, 30)
self.combobox.insertItem(0, "item 1")
self.combobox.insertItem(0, "item 2")
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setEffectEnabled(Qt.UIEffect.UI_AnimateCombo, False)
window = MainWindow()
sys.exit(app.exec())
uj5u.com熱心網友回復:
可能有一些內部和復雜的錯誤與您只設定了一個子控制元件屬性這一事實有關,但檔案專門解決了這方面的問題:
注意:對于 QComboBox 和 QScrollBar 等復雜的小部件,如果自定義了一個屬性或子控制元件,則必須同時自定義所有其他屬性或子控制元件。
請注意,在大多數情況下,這也與未設定布局管理器這一事實有關,并且在我的大多數測驗中,只要使用正確的布局,問題就會自動消失(您總是應該這樣做,即使您是僅使用一個子小部件)。
class MainWindow(QMainWindow):
def __init__(self):
# ...
layout = QVBoxLayout(self.widget)
layout.addWidget(self.combobox)
現在,即使使用布局,我仍然能夠在某些條件下重現該問題。這是由于一開始的解釋:如果你設定一個復雜的小部件的屬性,你必須設定所有的;不這樣做可能會導致意外行為。
在這種特定情況下,我相信 QStyleSheetStyle (這是在受 QSS 影響的任何小部件上自動設定的私有樣式,包括繼承的小部件)無法恢復畫家的筆,并且它使用箭頭的顏色作為組合標簽,但它只在某些(可能是“隨機”)條件下這樣做。
重點仍然存在:有些屬性未設定,特別是drop-down偽元素。
這樣做的結果是,border為該偽元素設定 會導致將箭頭影像重置為空白影像,但我們可以將其用作實際優勢;因為我們知道設定邊框會導致無箭頭影像,我們可以相應地更新樣式表:
class TestComboBox(QComboBox):
default_stylesheet = '''
TestComboBox {
color: black;
selection-color: black;
}
TestComboBox QAbstractItemView {
background-color: white;
min-width: 150px;
}
'''
non_hover_stylesheet = '''
TestComboBox::drop-down {
border: none;
}
'''
def __init__(self, parent=None):
super().__init__(parent)
self.setHoverState(False)
def setHoverState(self, state):
qss = self.default_stylesheet
if not state:
qss = self.non_hover_stylesheet
self.setStyleSheet(qss)
def enterEvent(self, event):
super().enterEvent(event)
self.setHoverState(True)
def leaveEvent(self, event):
super().leaveEvent(event)
self.setHoverState(False)
進一步說明:
- I removed the
selection-background-colorandbackground-colorproperties, as they result in an inconsistent behavior with certain styles (specifically, the "Fusion" style, which is considered the reference one for QSS and should always be checked) because those properties are often used ignoring the alpha level; I cannot test it with the "WindowsVista" style, but the point remains: if you want a transparent background color, it must be consistent with the actual background; consider using the QApplication'spalette()to get the colors ofHighlightandHighlightedTextroles, and eventually use those colors (without the alpha level) to set the actual backgrounds; - I made the QSS "templates" as class attributes: since we can assume that the stylesheet is set as a class default, defining it as an instance attribute makes little sense;
- this obviously does not (nor can) consider inherited stylesheets; while I specifically used the
TestComboBoxclass selector instead ofQComboBox, but remember that if you set a stylesheet (that expands other QComboBox properties or pseudo elements/states) to any parent or the application, you may get inconsistent and unexpected behavior; - (unrelated, but still important) it's good practice to not call
self.show()(orself.setVisible(True)) within the__init__of a widget;
uj5u.com熱心網友回復:
我通過閱讀檔案https://doc.qt.io/qt-5/stylesheet-syntax.html#sub-controls設法解決了這個問題。這是解決方案:
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QComboBox, QWidget, QVBoxLayout
class TestComboBox(QComboBox):
def __init__(self, parent=None):
super().__init__(parent)
self.default_stylesheet = '''
QComboBox {
color: black;
selection-color: black;
selection-background-color: rgba(0, 0, 0, 0);
background-color: rgba(0, 0, 0, 0);
}
QComboBox QAbstractItemView {
background-color: white;
min-width: 150px;
}
QComboBox:!hover::down-arrow {
color: rgba(0, 0, 0, 0);
}
'''
self.setStyleSheet(self.default_stylesheet)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.widget = QWidget(self)
self.setCentralWidget(self.widget)
self.layout = QVBoxLayout(self.widget)
self.combobox = TestComboBox()
self.combobox.resize(180, 30)
self.combobox.insertItem(0, "item 1")
self.combobox.insertItem(0, "item 2")
self.combobox.insertItem(0, "item 3")
self.combobox.insertItem(0, "item 4")
self.combobox.insertItem(0, "item 5")
self.layout.addWidget(self.combobox)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setEffectEnabled(Qt.UIEffect.UI_AnimateCombo, False)
window = MainWindow()
window.show()
sys.exit(app.exec())
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/443986.html
標籤:python-3.x qt pyqt pyqt5 qt5
上一篇:如何創建不可見范圍,以便當用戶單擊點附近時,將選擇該點
下一篇:啟動服務后腳本拋出錯誤
