我正在尝试在仅包含QListWidgets的QTabWidget(列表(上生成一个右键单击菜单。我在下面得到一个菜单,我在其中单击选项卡栏的高度距离,这是意料之中的,因为上下文菜单应用于 QTabWidget。
void onCustomContextMenuRequested(const QPoint& pos) {
QListWidgetItem * item = ((QListWidget*)(lists->currentWidget()))->itemAt(pos);
if (item) showContextMenu(item, QListWidget(lists->currentWidget()).viewport()->mapToGlobal(pos));
}
void showContextMenu(QListWidgetItem* item, const QPoint& globalPos) {
QMenu menu;
menu.addAction(item->text());
menu.exec(globalPos);
}
我可以让菜单出现在鼠标上,同时仍然引用它下方大约 100px 的项目,通过更改
QListWidget(lists->currentWidget()).viewport()->mapToGlobal(pos));
自
QListWidget(lists->currentWidget()).viewport()->mapToParent(mapToGlobal(pos)));
但是我无法让菜单引用我正在单击的项目。我尝试在父坐标之间转换,但没有效果。
QPoint pos_temp = ((QListWidget*)(lists->currentWidget()))->viewport()->mapFromParent(pos);
if (item) showContextMenu(item, QListWidget(lists->currentWidget()).viewport()->mapToGlobal(pos_temp));
我也试图从全局坐标,以及全局和父级的组合,产生不良效果。
那么我怎样才能获得右键单击菜单来引用我正在点击的项目呢?
customContextMenuRequested
信号发送的位置是相对于建立连接的小部件的,在这种情况下,我假设它是主小部件,因此当使用QListWidget
itemAt()
时,它会抛出不足的值,因为此方法等待相对于viewport()
的位置。在这些情况下,方法是将该局部位置转换为全局位置,然后将该全局位置映射到最终小部件的局部位置。
在下一部分中,我将展示一个示例。
#include <QApplication>
#include <QTabWidget>
#include <QListWidget>
#include <QVBoxLayout>
#include <QMenu>
class Widget: public QWidget{
Q_OBJECT
QTabWidget *lists;
public:
Widget(QWidget *parent=Q_NULLPTR):QWidget(parent){
lists = new QTabWidget;
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &Widget::customContextMenuRequested, this, &Widget::onCustomContextMenuRequested);
auto layout = new QVBoxLayout(this);
layout->addWidget(lists);
for(int i=0; i<4; i++){
auto list = new QListWidget;
lists->addTab(list, QString("tab-%1").arg(i));
for(int j=0; j<10; j++){
list->addItem(QString("item %1-%2").arg(i).arg(j));
}
}
}
private slots:
void onCustomContextMenuRequested(const QPoint& pos){
QPoint globalPos = mapToGlobal(pos);
QListWidget *list = static_cast<QListWidget *>(lists->currentWidget());
if(list){
QPoint p = list->viewport()->mapFromGlobal(globalPos);
QListWidgetItem *item = list->itemAt(p);
if(item)
showContextMenu(item, globalPos);
}
}
void showContextMenu(QListWidgetItem* item, const QPoint& globalPos) {
QMenu menu;
menu.addAction(item->text());
menu.exec(globalPos);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
以下链接是完整示例。