我正在嘗試在 ListView 上實作類似滑動手勢。listView 是stackedWidget 的一部分,如果事件被觸發,它應該更改頁面。
如果 eventFilter 的回傳值為 True,它就可以作業。但如果是這樣,ListView 就會消失。如果值為 False,ListView 會重新出現,但會觸發不同的事件。
我添加了一個最小的示例,這使我面臨的問題更加清晰。
我知道回傳值決定了事件是否應該被過濾(真)或不(假),但我不明白這里發生了什么。
我感謝每一個提示、提示或其他方法。最好有一個最小的作業示例。
主檔案
import sys
from PyQt6 import QtCore, QtWidgets
from PyQt6.QtGui import QIcon, QStandardItem
from PyQt6.QtWidgets import QVBoxLayout, QPushButton
from listView_minimal_example import ListView_Categories
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1190, 870)
MainWindow.setStyleSheet(
"QWidget{\n"
" background-color: rgb(61, 121, 60);\n"
"}\n"
"\n"
)
MainWindow.Wrapper_Kategories = QtWidgets.QStackedWidget(MainWindow)
MainWindow.Wrapper_Kategories.setGeometry(QtCore.QRect(9, 179, 1200, 621))
MainWindow.Wrapper_Kategories.setObjectName("Wrapper_Kategories")
self.page_1 = ListView_Categories(MainWindow)
self.page_1.setGeometry(QtCore.QRect(150, 110, 1200, 80))
self.page_1.setObjectName("view 1")
self.page_2 = ListView_Categories(MainWindow)
self.page_2.setGeometry(QtCore.QRect(150, 110, 1200, 80))
self.page_2.setObjectName("view 2")
MainWindow.Wrapper_Kategories.addWidget(self.page_1)
MainWindow.Wrapper_Kategories.addWidget(self.page_2)
item = QStandardItem()
item.setIcon(QIcon("000_Ordnerstruktur/003_Test/1.ico"))
self.page_1.m_model.appendRow(item)
item = QStandardItem()
item.setIcon(QIcon("000_Ordnerstruktur/003_Test/1.ico"))
self.page_2.m_model.appendRow(item)
self.btn = QPushButton()
self.btn.setText("Switch View")
layout = QVBoxLayout()
layout.addWidget(self.btn)
layout.addWidget(MainWindow.Wrapper_Kategories)
self.btn.mousePressEvent = self.switch_view
MainWindow.setLayout(layout)
def switch_view(self,data):
MainWindow.Wrapper_Kategories.setCurrentIndex(1)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QWidget()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec())
listView_minimal_example.py
from PyQt6.QtWidgets import QListView, QAbstractItemView
from PyQt6.QtCore import QSize, QEvent
from PyQt6.QtGui import QStandardItemModel
class ListView_Categories(QListView):
def __init__(self, parent:None):
super().__init__(parent)
self.parent = parent
self.m_model = QStandardItemModel(self)
self.setModel(self.m_model)
self.setAcceptDrops(False)
self.setIconSize(QSize(150,150))
self.setDragDropMode(QAbstractItemView.DragDropMode.NoDragDrop)
self.setResizeMode(QListView.ResizeMode.Adjust)
self.setViewMode(QListView.ViewMode.IconMode)
# Catch the event
self.installEventFilter(self)
self.setStyleSheet(
"QListView{\n"
" background-color:rgb(92, 52, 19)\n"
"}"
)
# True if the event should be filtered
# else Flase
def eventFilter(self, widget, event):
print("event ", event.type())
if(event.type() == QEvent.Type.MouseButtonPress):
print("event")
print(event.type())
print(event.spontaneous())
pos = event.pos()
self.position_1 = pos.x()
print("Entered at:", pos.x(), pos.y())
return True
elif(event.type() == QEvent.Type.MouseButtonRelease):
pos_2 = event.pos()
self.position_2 = pos_2.x()
if(self.position_1 < self.position_2 and abs(self.position_1-self.position_2) >= 100):
print("left swipe")
self.parent.Wrapper_Kategories.setCurrentIndex(self.parent.Wrapper_Kategories.currentIndex() 1)
return True
elif(abs(self.position_1-self.position_2) >= 100):
print("right swipe")
self.parent.Wrapper_Kategories.setCurrentIndex(self.parent.Wrapper_Kategories.currentIndex() - 1)
return True
#return super().eventFilter(widget,event)
#if True listView disappears if False diffrent Event Types occur
return True
我不確定問題是否變得清晰或保持不變而不向 listView(s) 添加圖示
uj5u.com熱心網友回復:
你的嘗試有很多問題。
您所指的問題是由于您總是True從事件過濾器回傳的事實引起的。這完全阻止了目標小部件處理任何事件(包括繪畫本身)。
此外,在同一個物件上安裝事件過濾器是沒有意義的,因為你可以覆寫它的event().
但這不起作用,因為在滾動區域中接收滑鼠按鈕的實際小部件是它的視口(在視圖中滾動的“內容”)。
對于子類,您將需要覆寫viewportEvent(),但對于滑鼠事件,您可以只覆寫基本處理程式:mousePressEvent()和mouseReleaseEvent(); 這是因為從 QAbstractScrollArea 繼承的所有類總是將視口的大多數用戶事件重新映射到小部件本身(請參閱檔案的最后幾段)。
然后,您不應嘗試直接訪問父小部件[1],而是發出自定義信號;然后,您將來自包含視圖(和堆疊的小部件)的實體的信號連接到實際交換頁面的函式。
最后,您永遠不要嘗試編輯 pyuic 檔案,因為這被認為是一種不好的做法(出于無數原因,我不會在這里解釋)。相反,請遵循有關使用 Designer的官方指南。
在下面的代碼中,我假設您已經使用原始 UI 重建了主視窗的 python 腳本,并在wrapper_Kategories那里添加了堆疊的小部件(默認為兩個頁面)。這也意味著您需要在每個頁面的適當布局中添加串列視圖(默認情況下為空)。
雖然您可以直接從 Designer 執行此操作,但您使用的是子類,因此從代碼中添加視圖更容易。
另一種方法是在 Designer 中添加視圖,在這種情況下,您有兩種選擇:
- 在視口( )上安裝一個事件過濾器
self.someView.viewport().installEventFilter(self),然后只檢查滑鼠事件(但總是回傳基本實作:)return super().eventFilter(obj, event); - 使用帶有自定義子類的提升小部件(對該主題進行一些研究,因為即使在 SO 中也有很多答案);
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
# Might have a different name, depending on the object name used in
# Designer; by default, basic "form widgets" are called `Form`, so it
# would be `Ui_Form`. The module name depends on the arguments of pyuic.
from ui_mainWindow import Ui_MainWindow
class ListView_Categories(QListView):
swap = pyqtSignal(int)
def __init__(self, parent:None):
super().__init__(parent)
self.parent = parent
self.m_model = QStandardItemModel(self)
self.setModel(self.m_model)
self.setAcceptDrops(False)
self.setIconSize(QSize(150,150))
self.setDragDropMode(QAbstractItemView.DragDropMode.NoDragDrop)
self.setResizeMode(QListView.ResizeMode.Adjust)
self.setViewMode(QListView.ViewMode.IconMode)
self.setMovement(QListView.Movement.Static)
self.setStyleSheet("""
QListView {
background-color: rgb(92, 52, 19);
}
""")
def mousePressEvent(self, event):
super().mousePressEvent(event)
if event.button() == Qt.MouseButton.LeftButton:
self.pressPos = event.pos().x()
def mouseReleaseEvent(self, event):
super().mousePressEvent(event)
if event.button() == Qt.MouseButton.LeftButton:
delta = event.pos().x() - self.pressPos
if abs(delta) >= 100:
# emit 1 or -1 depending on the value
self.swap.emit(abs(delta) // delta)
class MainWindow(QWidget, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
for i, page in enumerate((self.page_1, self.page_2)):
layout = page.layout()
if layout is None:
layout = QVBoxLayout(page)
listView = ListView_Categories()
layout.addWidget(listView)
listView.swap.connect(self.swap)
item = QStandardItem(str(i 1))
item.setIcon(QIcon("000_Ordnerstruktur/003_Test/1.ico"))
listView.m_model.appendRow(item)
self.btn.clicked.connect(self.goToSecond)
def swap(self, delta):
newIndex = self.wrapper_Kategories.currentIndex() delta
self.wrapper_Kategories.setCurrentIndex(newIndex)
def goToSecond(self):
self.wrapper_Kategories.setCurrentIndex(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec())
[1] 關于物件層次結構以及它們應該(或不應該)如何與父級互動,請閱讀此相關文章
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/508550.html
上一篇:顯示解析度更改后的表單重繪問題
