Qt学习—qt上下文菜单显示

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GDUTLYP/article/details/50432773

Qt学习—qt上下文菜单显示

 

Qwidget类及其子类都具有右键菜单响应功能,QWidget类提供了以下两个与右键菜单有关的函数:

1、 Qt::ContextMenuPolicy contextMenuPolicy()const

该函数用来获取控件上下文菜单项的显示策略。其返回值Qt::ContextMenuPolicy是枚举类型。

2、 void setContextMenuPolicy(Qt::ContextMenuPolicy policy )

该函数用来设置控件上下文菜单项的显示策略。其参数Qt::ContextMenuPolicy是枚举类型。

 

Qt::ContextMenuPolicy枚举类型定义的上下文菜单的显示策略如下:

① Qt::NoContextMenu(当前控件不支持上下文菜单功能,但具有请求路由功能)           

该策略表示,当前控件没有上下文菜单显示功能,但是具有上下文菜单显示请求路由功能。即当用户在该控件上请求上下文菜单时(如单击鼠标右键),虽然当前控件没有显示上下文菜单的功能,但是可以将该请求路由给其父类处理。如果其父类的上下文菜单显示策略支持,则显示父类的上下文菜单,如果不支持,则不显示任何菜单。

② Qt::PreventContextMenu(当前控件不支持上下文菜单功能,也不具备请求路由功能)   

该策略表示,当前控件没有上下文菜单显示功能,同时也不具备上下文菜单显示请求路由功能。即如果当前控件的上下文菜单显示策略被设置为该策略时,则上下文菜单显示请求仅由该控件处理,不会将显示请求路由给其他任何父类,则最终效果为,忽略用户的上下文菜单显示请求,不显示任何菜单。

 

③ Qt::DefaultContextMenu(当前控件支持上下文菜单功能,由上下文菜单事件函数响应用户请求)

该策略为默认的上下文菜单显示策略。当没有显式设定控件的上下文菜单显示策略时,默认为该策略。当用户在控件上请求上下文菜单时,显示请求会交由QWidget::contextMenuEvent( QContextMenuEvent  *event)函数处理。(上下文菜单事件函数)

QWidget::contextMenuEvent( QContextMenuEvent  *event)

该函数是一个虚函数,在子类中重写该函数,以实现子控件显示上下文菜单的功能。该函数是虚函数,所以只是提供了响应用户请求的接口,上下文菜单的具体实现需要自己编写。

构造函数中设置上下文菜单的显示策略

MainWindow::MainWindow(QWidget*parent):   QMainWindow(parent),   ui(newUi::MainWindow)

{

   ui->setupUi(this);

   QObject::connect(ui->saveScreenButton,SIGNAL(clicked()),this,SLOT(savepicture()));

   QObject::connect(ui->exitButton,SIGNAL(clicked()),this,SLOT(exit()));

   //设置上下文菜单项的显示策略

   ui->label_picture->setContextMenuPolicy(Qt::DefaultContextMenu);

}

上下文菜单响应事件函数中,构造菜单并显示菜单

voidMainWindow::contextMenuEvent(QContextMenuEvent*event)

{

   //判断鼠标右键点击的位置是否在ui->label_picture控件的范围内

   //通过ui->label_picture控件的左上角点和右下角点的坐标判定

   if(ui->label_picture->mapFromGlobal(QCursor::pos()).x()>=

      ui->label_picture->rect().topLeft().x()&&

      ui->label_picture->mapFromGlobal(QCursor::pos()).y()>=

      ui->label_picture->rect().topLeft().y()&&

      ui->label_picture->mapFromGlobal(QCursor::pos()).x()<=

      ui->label_picture->rect().bottomRight().x()&&

      ui->label_picture->mapFromGlobal(QCursor::pos()).y()<=

      ui->label_picture->rect().bottomRight().y()

     )

   {

       QMenu*menu=newQMenu(this);             //创建上下文菜单

       QAction*Act_Saveas=newQAction(this);   //新建菜单项

       QAction*Act_Process=newQAction(this);  //新建菜单项

       Act_Saveas->setText("另存为");              //设置菜单项文本

       Act_Process->setText("启动记事本");          //设置菜单项文本

       //设定菜单项的信号与槽

       QObject::connect(Act_Saveas,SIGNAL(triggered()),this,SLOT(savepicture()));

       QObject::connect(Act_Process,SIGNAL(triggered()),this,SLOT(startprocess()));

       menu->addAction(Act_Saveas);   //添加菜单项

       menu->addSeparator();          //添加菜单项分隔线

       menu->addAction(Act_Process);  //添加菜单项

       menu->exec(QCursor::pos());    //在鼠标右键单击位置处创建并执行上下文菜单

   }

}

注意:当上下文菜单的显示策略为Qt::DefaultContextMenu时,菜单项(action)是加载到菜单(menu)中,借助菜单显示出来的。


Qt::ActionsContextMenu(当前控件支持上下文菜单功能,菜单项的显示不依托菜单)

该策略表示,将该控件上所支持的所有菜单项(action)作为一个上下文菜单显示出来。为了理解更清楚,和典型的上下文菜单做一下对比。

对于典型的上下文菜单来说,一般是新建一个菜单(menu),然后在新建一个活多个菜单项(action),之后将所有的菜单项(action)加载到菜单(menu)中,最后通过执行菜单的QMenu::exec()函数来显示整个上下文菜单。即,菜单是菜单项的载体,所有的菜单项(action)通过菜单(menu)得以显示。

如果某一控件的上下文菜单显示策略设置为Qt::ActionsContextMenu的话,则可以省略菜单(menu)这一载体。因为所有的控件都是由QWidget类继承而来,QWidget类提供了QWidget::addAction(QAction *action)函数来加载菜单项(action)。所以,使用该策略时,首先新建若干菜单项(action),之后通过控件(QWidget的子类)addAction(QAction *action)函数来加载所有的菜单项到控件上,最后设置显示策略为Qt::ActionsContextMenu。当用户请求显示上下文菜单时,所有菜单项就会作为一个菜单(menu)显示出来。

构造函数中设置上下文菜单的显示策略

MainWindow::MainWindow(QWidget*parent):   QMainWindow(parent),   ui(newUi::MainWindow)

{

   ui->setupUi(this);

   QObject::connect(ui->saveScreenButton,SIGNAL(clicked()),this,SLOT(savepicture()));

   QObject::connect(ui->exitButton,SIGNAL(clicked()),this,SLOT(exit()));

   //设置上下文菜单项的显示策略

   ui->label_picture->setContextMenuPolicy(Qt::ActionsContextMenu);

}

上下文菜单响应事件函数中,构造菜单并显示菜单

voidMainWindow::contextMenuEvent(QContextMenuEvent*event)

{

   //判断鼠标右键点击的位置是否在ui->label_picture控件的范围内

   //通过ui->label_picture控件的左上角点和右下角点的坐标判定

   if(ui->label_picture->mapFromGlobal(QCursor::pos()).x()>=

      ui->label_picture->rect().topLeft().x()&&

      ui->label_picture->mapFromGlobal(QCursor::pos()).y()>=

      ui->label_picture->rect().topLeft().y()&&

      ui->label_picture->mapFromGlobal(QCursor::pos()).x()<=

      ui->label_picture->rect().bottomRight().x()&&

      ui->label_picture->mapFromGlobal(QCursor::pos()).y()<=

      ui->label_picture->rect().bottomRight().y()

     )

   {

       QAction*Act_Saveas=newQAction(this);   //新建菜单项

       QAction*Act_Process=newQAction(this);  //新建菜单项

       Act_Saveas->setText("另存为");             //设置菜单项文本

       Act_Process->setText("启动记事本");        //设置菜单项文本

       //设定菜单项的信号与槽

       QObject::connect(Act_Saveas,SIGNAL(triggered()),this,SLOT(savepicture()));

       QObject::connect(Act_Process,SIGNAL(triggered()),this,SLOT(startprocess()));

        //直接将菜单项加载到控件上

       ui->label_picture->addAction(Act_Saveas);

       ui->label_picture->addAction(Act_Process);

   }

}

注意:当上下文菜单的显示策略为Qt::ActionsContextMenu时,菜单项(action)是直接加载到控件上,以列表的形式显示出来的。当然也可以借助菜单显示出来的。

 

⑤ Qt::CustomContextMenu

该策略表示,当前控件可以支持上下文菜单。和其他显示策略不同的是,该策略完全由用户自己定制,即应用程序没有提供默认的接口函数,仅仅只提供了信号函数,注意仅仅只是发信号,意味着要自己写显示右键菜单的SLOT槽函数。该信号的发出条件是:用户请求contextMenu(常规就是鼠标右击)且同时被击的widget其上下文菜单显示策略contextMenuPolicy被设置为Qt::CustomContextMenu。

void QWidget::customContextMenuRequested (const QPoint pos )[signal]

这个信号是QWidget唯一与右键菜单有关的信号(也是自有的唯一信号),同时也是很容易被忽略的signal。

注意:pos是该widget接收右键菜单事件的位置,一般是在该控件的坐标系中。但是对于QAbstratScrollArea及其子类例外,是对应着其视口viewport()的坐标系。如常用的QTableView、QHeaderView就是QAbstratScrollArea的子类。

构造函数中设置上下文菜单的显示策略

MainWindow::MainWindow(QWidget*parent):   QMainWindow(parent),   ui(newUi::MainWindow)

{

   ui->setupUi(this);

   QObject::connect(ui->saveScreenButton,SIGNAL(clicked()),this,SLOT(savepicture()));

QObject::connect(ui->exitButton,SIGNAL(clicked()),this,SLOT(exit()));

QObject::connect(ui->label_picture,SIGNAL(customContextMenuRequested(constQPoint&)),

               this,SLOT(slot_contextmenu(constQPoint&)));

   //设置上下文菜单项的显示策略

   ui->label_picture->setContextMenuPolicy(Qt::CustomContextMenu);

}

自定义上下文菜单响应事件函数中,构造菜单并显示菜单

voidMainWindow::slot_contextmenu(constQPoint&pos)

{

   QPointpoint=ui->label_picture->mapTo(ui->label_picture,pos);

   //判断鼠标右键点击的位置是否在ui->label_picture控件的范围内

   //通过ui->label_picture控件的左上角点和右下角点的坐标判定

   if(point.x()>=ui->label_picture->rect().topLeft().x()&&

      point.y()>=ui->label_picture->rect().topLeft().y()&&

      point.x()<=ui->label_picture->rect().bottomRight().x()&&

      point.y()<=ui->label_picture->rect().bottomRight().y()

     )

   {

       QMenu*menu=newQMenu(this);             //创建上下文菜单

       QAction*Act_Saveas=newQAction(this);   //新建菜单项

       QAction*Act_Process=newQAction(this);  //新建菜单项

       Act_Saveas->setText("另存为");             //设置菜单项文本

       Act_Process->setText("启动记事本");        //设置菜单项文本

       //设定菜单项的信号与槽

       QObject::connect(Act_Saveas,SIGNAL(triggered()),this,SLOT(savepicture()));

       QObject::connect(Act_Process,SIGNAL(triggered()),this,SLOT(startprocess()));

       menu->addAction(Act_Saveas);   //添加菜单项

       menu->addSeparator();          //添加菜单项分隔线

       menu->addAction(Act_Process);  //添加菜单项

       menu->exec(QCursor::pos());    //在鼠标右键单击位置处创建并执行上下文菜单

        //menu->exec(pos);//是在viewport显示

   }

}

注意:当上下文菜单的显示策略为Qt:: CustomContextMenu时,默认的上下文菜单响应函数已经不在起作用了,需要编程人员重新编写响应函数,并在构造函数中指定响应的信号和槽的连接。

 

坐标变换函数

1、全局坐标系

从屏幕的左上角起,向右为X轴正向,向下为Y轴正向。屏幕坐标系是绝对坐标系。点的位置在屏幕上发生变化时,点的坐标值会发生相应的变化。坐标点的值是相对于屏幕左上角的绝对坐标值。

2、控件坐标系

从控件的左上角起,向右为X轴正向,向下为Y轴正向。控件坐标系是相对坐标系。控件的位置相对屏幕发生变化时,只要保持点相对于控件的位置不发生变化,则虽然点的位置在屏幕坐标系中发生了变化,但是点的坐标值不会改变。点的坐标值是相对于控件左上角的绝对坐标值。

 

① QPoint QWidget::mapFrom QWidget parent, const QPoint pos) const

将点posparent控件上的坐标值转换为当前控件坐标系的坐标值。例如:

ui->label_picture->mapFrom(ui->newScreenButton,pos);

pos表示点在ui->newScreenButton控件上的坐标值,ui->label_picture控件调用mapFrom()函数将pos的坐标值转换为点在ui->label_picture

 

 QPoint QWidget::mapFromGlobal (const QPoint pos ) const

将点pos在全局坐标系上的坐标值转换为当前控件坐标系的坐标值。例如:

ui->label_picture->mapFromGlobal(QCursor::pos());

QCursor::pos()      函数用来获得鼠标单击点的全局位置

 

 QPoint QWidget::mapFromParent (const QPoint pos ) const

pos在父控件坐标系上的坐标值转换为当前控件坐标系的坐标值。例如:

ui->label_picture->mapFromParent(pos);

 

 QPoint QWidget::mapTo QWidget parent, const QPoint pos ) const

将点pos在当前控件坐标系的坐标值转换为parent控件上的坐标值。

ui->label_picture->mapTo(ui->newScreenButton,pos);   //此时pos的为label_picture下的坐标值

 

 QPoint QWidget::mapToGlobal (const QPoint pos ) const

将点pos在当前控件坐标系的坐标值转换为全局坐标系上的坐标值。

ui->label_picture->mapToParent(pos);                //此时pos的为label_picture下的坐标值

 

 QPoint QWidget::mapToParent (const QPoint pos ) const

pos在当前控件坐标系的坐标值转换为父控件坐标系上的坐标值。

ui->label_picture->mapToParent(pos);                //此时pos的为label_picture下的坐标值

 

 

 

猜你喜欢

转载自blog.csdn.net/GDUTLYP/article/details/50432773