2011-10-16 78 views
2

下面的示例代碼(受here影響很大),右鍵單擊的上下文菜單並沒有真正對齊。如何在PyQt中正確對齊右鍵單擊上下文菜單?

從屏幕截圖中可以看出,生成的菜單位於鼠標光標的上方。我期望菜單的左上角與鼠標指針精確對齊。

有什麼辦法可以調整這個嗎?

Menu screenshot

import re 
import operator 
import os 
import sys 
import sqlite3 
import cookies 
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() 

回答

2

這是一個有點棘手,但按照這個維基例子的子類實例,並與

15   action = menu.exec_(event.globalPos()) 

更換

15   action = menu.exec_(self.mapToGlobal(event.pos())) 

會使彈出菜單的左上角匹配鼠標完全點擊。

5

位置在視口中的座標,因此,如果您正在使用

self.tableView.setContextMenuPolicy(Qt.CustomContextMenu)

所以你不必event傳遞給popup,你可以做以下

action = menu.exec_(self.tableView.viewport().mapToGlobal(pos))

代替。

相關問題