Как получить контекстные меню контекстного меню для кликов в заголовке QTableView?

Пример кода ниже (в значительной степени повлиял на здесь ) имеет контекстное меню правой кнопки мыши, которое будет отображаться, когда пользователь щелкает ячейки в таблице. Возможно ли иметь другое контекстное меню правой кнопки мыши для щелчков правой кнопкой мыши в заголовке таблицы? Если да, как я могу изменить код, чтобы включить это?

import re import operator import os import sys from PyQt4.QtCore import * from PyQt4.QtGui import * def main(): app = QApplication(sys.argv) w = MyWindow() w.show() sys.exit(app.exec_()) class MyWindow(QWidget): def __init__(self, *args): QWidget.__init__(self, *args) self.tabledata = [('apple', 'red', 'small'), ('apple', 'red', 'medium'), ('apple', 'green', 'small'), ('banana', 'yellow', 'large')] self.header = ['fruit', 'color', 'size'] # create table self.createTable() # layout layout = QVBoxLayout() layout.addWidget(self.tv) self.setLayout(layout) def popup(self, pos): for i in self.tv.selectionModel().selection().indexes(): print i.row(), i.column() menu = QMenu() quitAction = menu.addAction("Quit") action = menu.exec_(self.mapToGlobal(pos)) if action == quitAction: qApp.quit() def createTable(self): # create the view self.tv = QTableView() self.tv.setStyleSheet("gridline-color: rgb(191, 191, 191)") self.tv.setContextMenuPolicy(Qt.CustomContextMenu) self.tv.customContextMenuRequested.connect(self.popup) # set the table model tm = MyTableModel(self.tabledata, self.header, self) self.tv.setModel(tm) # set the minimum size self.tv.setMinimumSize(400, 300) # hide grid self.tv.setShowGrid(True) # set the font font = QFont("Calibri (Body)", 12) self.tv.setFont(font) # hide vertical header vh = self.tv.verticalHeader() vh.setVisible(False) # set horizontal header properties hh = self.tv.horizontalHeader() hh.setStretchLastSection(True) # set column width to fit contents self.tv.resizeColumnsToContents() # set row height nrows = len(self.tabledata) for row in xrange(nrows): self.tv.setRowHeight(row, 18) # enable sorting self.tv.setSortingEnabled(True) return self.tv class MyTableModel(QAbstractTableModel): def __init__(self, datain, headerdata, parent=None, *args): """ datain: a list of lists headerdata: a list of strings """ QAbstractTableModel.__init__(self, parent, *args) self.arraydata = datain self.headerdata = headerdata def rowCount(self, parent): return len(self.arraydata) def columnCount(self, parent): return len(self.arraydata[0]) def data(self, index, role): if not index.isValid(): return QVariant() elif role != Qt.DisplayRole: return QVariant() return QVariant(self.arraydata[index.row()][index.column()]) def headerData(self, col, orientation, role): if orientation == Qt.Horizontal and role == Qt.DisplayRole: return QVariant(self.headerdata[col]) return QVariant() def sort(self, Ncol, order): """Sort table by given column number. """ self.emit(SIGNAL("layoutAboutToBeChanged()")) self.arraydata = sorted(self.arraydata, key=operator.itemgetter(Ncol)) if order == Qt.DescendingOrder: self.arraydata.reverse() self.emit(SIGNAL("layoutChanged()")) if __name__ == "__main__": main() 

  • python посылает POST с заголовком
  • urllib2 несколько заголовков Set-Cookie в ответ
  • Как отправить настраиваемый заголовок с urllib2 в HTTP-запросе?
  • Чтение первых N строк файла в python
  • У меня Python на моей системе Ubuntu, но gcc не может найти Python.h
  • Как отправить настраиваемый заголовок с urllib2 в HTTP-запросе?
  • lambda in for loop принимает последнее значение
  • Контекстные меню проводника Windows с подменю с использованием pywin32
  • python посылает POST с заголовком
  • У меня Python на моей системе Ubuntu, но gcc не может найти Python.h
  • Чтение первых N строк файла в python
  • 2 Solutions collect form web for “Как получить контекстные меню контекстного меню для кликов в заголовке QTableView?”

    Оказалось, было проще, чем я думал. Так же, как я добавляю всплывающее меню для самого виджета QTableView, я могу просто получить заголовок из объекта таблицы, а затем прикрепить контекстное меню так же, как и в обычном контекстном меню.

     headers = self.tv.horizontalHeader() headers.setContextMenuPolicy(Qt.CustomContextMenu) headers.customContextMenuRequested.connect(self.header_popup) 

    Есть еще один потенциально более мощный способ сделать это, если вы сделаете шаг и наследуете представление, а не просто его составляете. Здесь работает пользовательское контекстное меню? Да, но почему что-то, кроме мнения, должно знать об этом? Это также поможет лучше сформировать ваш код для правильного решения других проблем. В настоящее время реализация не обеспечивает инкапсуляции, сплоченности или разделения ответственности. В итоге у вас будет одна большая блоба, которая является антитезой хорошего дизайна. Я упоминаю об этом, потому что вы, кажется, размещаете все GUI Logic в этой постоянно растущей основной функции, и по этой причине вы закончили тем, что поставили реализацию сортировки внутри вашей модели, что не имеет для меня никакого смысла. (Что, если у вас есть два представления модели, вы вынуждаете их сортироваться одинаково)

    Это больше кода? Да, но это дает вам больше силы, о которой, я думаю, стоит упомянуть. Ниже я демонстрирую, как обрабатывать заголовки, а также любую ячейку, которую вы хотите. Также обратите внимание, что в моей реализации, если существует какой-то другой виджет, который также определяет обработчик событий контекстного меню, он потенциально получит шанс получить трещины при обработке события после моего; так что, если кто-то добавляет обработчик только для определенных случаев, они могут сделать это, не усложняя мой код. Часть этого будет отмечена, если вы обработали событие или нет.

    Достаточно моего размытия и мыслей вот код:

      #Alteration : instead of self.tv = QTableView... self.tv = MyTableView() .... # somewhere in your TableView object's __init__ method # yeah IMHO you should be inheriting and thus extending TableView class MyTableView(QTableView): def __init__(self, parent = None): super(MyTableView, self).__init__() self.setContextMenuPolicy(Qt.DefaultContextMenu) ## uniform one for the horizontal headers. self.horizontalHeader().setContextMenuPolicy(Qt.ActionsContextMenu) ''' Build a header action list once instead of every time they click it''' doSomething = QAction("&DoSomething", self.verticalHeader(), statusTip = "Do something uniformly for headerss", triggered = SOME_FUNCTION self.verticalHeader().addAction(doSomething) ... return def contextMenuEvent(self, event) ''' The super function that can handle each cell as you want it''' handled = False index = self.indexAt(event.pos()) menu = QMenu() #an action for everyone every = QAction("I'm for everyone", menu, triggered = FOO) if index.column() == N: #treat the Nth column special row... action_1 = QAction("Something Awesome", menu, triggered = SOME_FUNCTION_TO_CALL ) action_2 = QAction("Something Else Awesome", menu, triggered = SOME_OTHER_FUNCTION ) menu.addActions([action_1, action_2]) handled = True pass elif index.column() == SOME_OTHER_SPECIAL_COLUMN: action_1 = QAction("Uh Oh", menu, triggered = YET_ANOTHER_FUNCTION) menu.addActions([action_1]) handled = True pass if handled: menu.addAction(every) menu.exec_(event.globalPos()) event.accept() #TELL QT IVE HANDLED THIS THING pass else: event.ignore() #GIVE SOMEONE ELSE A CHANCE TO HANDLE IT pass return pass #end of class 
    Python - лучший язык программирования в мире.