【问题标题】:How can I align a right-click context menu properly in PyQt?如何在 PyQt 中正确对齐右键单击上下文菜单?
【发布时间】:2011-12-08 14:01:49
【问题描述】:

对于下面的示例代码(受here 的严重影响),右键单击上下文菜单并没有真正正确对齐。

从屏幕截图中可以看出,结果菜单位于鼠标光标上方相当多的位置。我希望菜单的左上角与鼠标指针完全对齐。

有什么办法可以调整吗?

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()

【问题讨论】:

    标签: pyqt contextmenu alignment


    【解决方案1】:

    位置在视口坐标中,所以如果您使用的是

    self.tableView.setContextMenuPolicy(Qt.CustomContextMenu)

    所以您没有将event 传递给popup,您可以执行以下操作

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

    改为。

    【讨论】:

    • 经过几个小时的搜索,这个对 PyQT5 有效
    【解决方案2】:

    这有点棘手,但遵循 this wiki 示例中的子类化示例并替换

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

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

    将使弹出菜单的左上角与鼠标点击完全匹配。

    【讨论】:

      【解决方案3】:

      这适用于最大化/缩小的窗口。 鼠标右下角会生成菜单。

      menu.exec_(self.mapToGlobal(self.mapFromGlobal(QtGui.QCursor.pos())))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多