我有多個帶有 QTableViews 的 PyQt5 應用程式,這些應用程式繼承自 QTableView 的子類“MyTable”。這樣做,我能夠在一個地方(gen_context_menu)維護背景關系選單的代碼,這對所有使用 MyTable 的應用程式都很有用。
但是今天我遇到了對一個新應用程式的需求,它既可以從 MyTable 中現有的背景關系選單中受益,又可以獲得我不希望授予舊版/通用應用程式訪問權限的新/附加背景關系選單選項。
在下面的 MRE 中,我撰寫了幾個虛擬函式來顯示我腦海中模糊的實作這一目標的方法——我想我會封裝“標準選單”的獲取(使用 get_standard_menu),MyTable 會在 legacy/通用情況,然后對于新應用程式,可能通過引數或 MyTable 的小子類呼叫“新”選單功能(get_sending_menu)。當我開始撰寫代碼時,我意識到由于“操作”與選單定義相結合,它并不像我想象的那樣簡單,然后我立即想到“一定有更好的方法”.. .
有沒有?
import logging
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.Qt import QAbstractTableModel, QVariant, Qt, QMainWindow
__log__ = logging.getLogger()
def get_sending_menu():
menu = get_standard_menu()
action_send = menu.addAction("Send!")
return menu
def get_standard_menu():
menu = QtWidgets.QMenu()
action_get_ticks = menu.addAction("Get Ticks")
action_get_events = menu.addAction("Get Events")
action_get_overview = menu.addAction("Get Overview")
return menu
class MyModel(QAbstractTableModel):
rows = [('X'), ('Y'), ('Z')]
columns = ['Letter']
def rowCount(self, parent):
return len(MyModel.rows)
def columnCount(self, parent):
return len(MyModel.columns)
def data(self, index, role):
if role != Qt.DisplayRole:
return QVariant()
return MyModel.rows[index.row()][index.column()]
class MyTable(QtWidgets.QTableView):
def __init__(self, parent=None, ):
super().__init__()
self.tick_windows = []
self.events_windows = []
self.overview_windows = []
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.gen_context_menu)
mre_model = MyModel()
self.setModel(mre_model)
def gen_context_menu(self, pos):
index = self.indexAt(pos)
if not index.isValid() or index.column() != 0:
return
input_value = index.sibling(index.row(), index.column()).data()
menu = QtWidgets.QMenu()
action_get_ticks = menu.addAction("Get Ticks")
action_get_events = menu.addAction("Get Events")
action_get_overview = menu.addAction("Get Overview")
action = menu.exec_(self.viewport().mapToGlobal(pos))
if action == action_get_ticks:
model_window = QMainWindow()
__log__.info(input_value)
model_window.show()
self.tick_windows.append(model_window)
elif action == action_get_events:
model_window = QMainWindow()
__log__.info(input_value)
model_window.show()
self.events_windows.append(model_window)
elif action == action_get_overview:
model_window = QMainWindow()
__log__.info(input_value)
model_window.show()
self.overview_windows.append(model_window)
class App(QtWidgets.QApplication):
def __init__(self, sys_argv):
super(App, self).__init__(sys_argv)
self.main_view = MyTable()
self.main_view.show()
if __name__ == '__main__':
logging.basicConfig()
app = App(sys.argv)
try:
sys.exit(app.exec_())
except Exception as e:
__log__.error('%s', e)```
uj5u.com熱心網友回復:
@musicamante 我認為這個答案需要你的建議——主要是。我不確定您是否建議我使用 MySpecialTable 子類化 MyTable。如果你是,我不確定我是否有效地多載了 gen_context_menu。最后,我也不確定我是否有效地實施了 pos/event 的東西。但是,這似乎確實有效,并聽取了您的建議standardContextMenu,triggered和contextMenuEvent。如果這是對最佳實踐/良好習慣的努力,請隨時進一步完善它。謝謝你。
import logging
import sys
from PyQt5 import QtWidgets
from PyQt5.Qt import QAbstractTableModel, QVariant, Qt, QMainWindow
__log__ = logging.getLogger()
class MyModel(QAbstractTableModel):
rows = [('X'), ('Y'), ('Z')]
columns = ['Letter']
def rowCount(self, parent):
return len(MyModel.rows)
def columnCount(self, parent):
return len(MyModel.columns)
def data(self, index, role):
if role != Qt.DisplayRole:
return QVariant()
return MyModel.rows[index.row()][index.column()]
class MyTable(QtWidgets.QTableView):
def __init__(self, parent=None):
super().__init__()
self.tick_windows = []
self.events_windows = []
self.overview_windows = []
mre_model = MyModel()
self.setModel(mre_model)
def get_input_value(self, pos):
index = self.indexAt(pos)
if not index.isValid() or index.column() != 0:
return None
input_value = index.sibling(index.row(), index.column()).data()
return input_value
def contextMenuEvent(self, event):
pos = event.globalPos()
input_value = self.get_input_value(self.viewport().mapFromGlobal(pos))
if not input_value:
return
menu = self.gen_context_menu(input_value)
menu.exec(event.globalPos())
def get_ticks_triggered(self, input_value):
model_window = QMainWindow()
__log__.info(input_value)
model_window.show()
self.tick_windows.append(model_window)
def get_events_triggered(self, input_value):
model_window = QMainWindow()
__log__.info(input_value)
model_window.show()
self.tick_windows.append(model_window)
def get_overview_triggered(self, input_value):
model_window = QMainWindow()
__log__.info(input_value)
model_window.show()
self.tick_windows.append(model_window)
def gen_context_menu(self, input_value):
menu = QtWidgets.QMenu()
menu = self.get_standard_menu(menu, input_value)
return menu
def get_standard_menu(self, menu, input_value):
action_get_ticks = menu.addAction("Get Ticks")
action_get_ticks.triggered.connect(lambda: self.get_ticks_triggered(input_value))
action_get_events = menu.addAction("Get Events")
action_get_events.triggered.connect(lambda: self.get_events_triggered(input_value))
action_get_overview = menu.addAction("Get Overview")
action_get_overview.triggered.connect(lambda: self.get_overview_triggered(input_value))
return menu
class MyTableSpecial(MyTable):
def get_special_menu(self, menu, input_value):
action_send = menu.addAction("Send!")
action_send.triggered.connect(lambda: self.send_triggered(input_value))
return menu
def send_triggered(self, input_value):
__log__.info(input_value)
def gen_context_menu(self, input_value):
menu = QtWidgets.QMenu()
menu = super().get_standard_menu(menu, input_value)
menu = self.get_special_menu(menu, input_value)
return menu
class App(QtWidgets.QApplication):
def __init__(self, sys_argv):
super(App, self).__init__(sys_argv)
self.main_view = MyTableSpecial()
self.main_view.show()
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
app = App(sys.argv)
try:
sys.exit(app.exec_())
except Exception as e:
__log__.error('%s', e)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/428617.html
上一篇:在連續運行中更改方法行為
