时间:2023-01-05 11:08:42 | 栏目:C代码 | 点击:次
QMenu和QMenuBar是Qt中的菜单类和菜单栏类,其中,菜单QMenu挂载在菜单栏QMenuBar上。本文主要总结QMenu的三种常用用法,分别为常规用法、继承QWidgetAction自定义菜单项用法、将QMenu当QWidget挂载一个布局用法。
下面对每种用法进行原理讲解和代码总结。
QMenuBar是菜单栏,QMenu是菜单,菜单QMenu是挂载在菜单栏QMenuBar上的,相当于菜单栏QMenuBar是一个容器,菜单QMenu是容器中的其中一项,或者说QMenuBar内的子集全部是菜单QMenu,如下图所示:
#include <QMenu> #include <QAction> #include <QMenuBar> #include <QVBoxLayout> void Widget::on_pushButton_clicked() { QMenu *menu=new QMenu("菜单:常规"); QAction *action1=new QAction(QIcon(":/resource/image/向右箭头.jpg"),"action1"); QAction *action2=new QAction(QIcon(":/resource/image/向右箭头.jpg"),"action2"); QList<QAction*> list; list.append(action1); list.append(action2); menu->addActions(list); QMenuBar *menuBar=new QMenuBar; menuBar->addMenu(menu); menuBar->addSeparator(); //分隔栏 ui->verticalLayout->addWidget(menuBar); }
当我们需要自定义菜单里面的每一项时,也就是需要自定义的菜单项内容。菜单项就是菜单里面的子集,如下图所示:
此时我们希望添加的action最好是一个QWidget,那样就可以任意布局了。Qt提供了这样的一个类QWidgetAction。该类继承于QAction,因此对于任何挂载QAction希望自定义界面的需求,都可以用QWidgetAction替代QAction,进行自定义界面定制。
调用QWidgetAction的方法有两种,一个中直接当成QAction用,只是在创建对象的时候,一定要关联父控件为QMenu或者this;调用完后,设置函数void QWidgetAction::setDefaultWidget(QWidget *w);设置自定义的QWidget界面,然后用菜单像添加QAction一样添加QWidgetAction对象即可。另一种方式是继承QWidgetAction,在继承子类构造函数中设计要定义的QWidget布局,下面的代码也是用继承QWidgetAction的方法。
分别添加两个类QMyMenu和QMyWidgetAction,其中QMyMenu继承QMenu,QMyWidgetAction继承QWidgetAction。
qmywidgetaction.h
#ifndef QMYWIDGETACTION_H #define QMYWIDGETACTION_H #include <QWidgetAction> class QMyWidgetAction : public QWidgetAction { public: explicit QMyWidgetAction(QWidget *parent=0); protected: virtual QWidget *createWidget(QWidget *parent); }; #endif // QMYWIDGETACTION_H
qmywidgetaction.cpp
#include "qmywidgetaction.h" #include <QPushButton> #include <QSplitter> #include <QLabel> #include <QLineEdit> #include <QPixmap> #include <QMouseEvent> #include <QHBoxLayout> #include <QDebug> QMyWidgetAction::QMyWidgetAction(QWidget *parent):QWidgetAction(parent) { } QWidget *QMyWidgetAction::createWidget(QWidget *parent) { QLabel* lab = new QLabel("label1"); QPushButton *button1=new QPushButton("button1"); QHBoxLayout *hlayout=new QHBoxLayout; hlayout->setMargin(0); hlayout->setSpacing(0); hlayout->addWidget(lab); hlayout->addWidget(button1); QWidget* widget = new QWidget(parent); //如果写成 QSplitter* sp = new QSplitter; 就无法显示!!! widget->setLayout(hlayout); connect(button1,&QPushButton::clicked,[this](bool){qDebug()<<"单击按钮!";}); return widget; }
qmymenu.h
#ifndef QMYMENU_H #define QMYMENU_H #include <QMenu> #include <QMouseEvent> class QMyMenu : public QMenu { public: explicit QMyMenu(const QString &title, QWidget *parent = Q_NULLPTR); protected: }; #endif // QMYMENU_H
qmymenu.cpp
#include "qmymenu.h" #include <QAction> QMyMenu::QMyMenu(const QString &title, QWidget *parent):QMenu(title,parent) //初始化子类构造函数 { }
在按钮槽函数调用如下代码即可
#include "qmywidgetaction.h" #include "qmymenu.h" #include <QAction> #include <QMenuBar> #include <QVBoxLayout> void Widget::on_pushButton_3_clicked() { QMyMenu *menu= new QMyMenu("菜单:继承QWidgetAction用法"); QAction *action1=new QAction(QIcon(":/resource/image/向右箭头.jpg"),"1"); //设置图标和内容 menu->addAction(action1); QMyWidgetAction *myWidgetAction=new QMyWidgetAction(menu); menu->addSeparator(); //添加分割线 menu->addAction(myWidgetAction); QMenuBar *menuBar=new QMenuBar(this); menuBar->setStyleSheet("QMenuBar{background-color:red}" "QMenuBar:hover{background-color:blue}"); menuBar->addMenu(menu); ui->verticalLayout->addWidget(menuBar); ui->verticalLayout->addStretch(); }
结果如下图所示
QMenu是继承QWidget的,故我们可以当成QWidget一样进行布局调用,在布局上添加我们自定义的界面。
class Q_WIDGETS_EXPORT QMenu : public QWidget {}
void Widget::on_pushButton_2_clicked() { QMenu *menu=new QMenu("菜单:当Widget用,添加一个布局"); QAction *action1=new QAction(QIcon(":/resource/image/向右箭头.jpg"),"action1"); QAction *action2=new QAction(QIcon(":/resource/image/向右箭头.jpg"),"action2"); QList<QAction*> list; list.append(action1); list.append(action2); QVBoxLayout *vlayout=new QVBoxLayout; vlayout->setContentsMargins(10,0,10,0); QPushButton *button1=new QPushButton("11"); vlayout->addWidget(button1); menu->setLayout(vlayout); QMenuBar *menuBar=new QMenuBar; menuBar->addMenu(menu); menuBar->addSeparator(); ui->verticalLayout->addWidget(menuBar); }
结果如下图所示:
总结:具体的需要哪种用法,业务需求来定。但是,要是自定义菜单项的话,我倾向使用第三种,当QMenu当成一个QWidget来用最简单省事,而且很容易做出各种QSS样式表效果。
https://blog.csdn.net/naibozhuan3744/article/details/80855818(参考:QMenu用法)
https://blog.csdn.net/lengyuezuixue/article/details/81123516(参考:QWidgetAction直接用法)
https://blog.csdn.net/lengyuezuixue/article/details/81123516(参考:QWidgetAction继承用法)
https://blog.csdn.net/HYNzhl/article/details/77542421(参考:QWidgetAction重写虚函数createWidget)
https://blog.csdn.net/ly305750665/article/details/53558935(参考:自定义QMenu)
https://www.cnblogs.com/newstart/p/4478689.html(参考:设置QMenuBar属性)
https://bbs.csdn.net/topics/390276550(参考:主动隐藏菜单和主动显示菜单)
https://www.cnblogs.com/swarmbees/p/5634650.html(参考:QWidgetAction用法)
https://blog.csdn.net/peppereggfriedrice/article/details/78861115(参考:QMenu样式表QSS)
https://bbs.csdn.net/topics/391821575(参考:QMenu样式表QSS)
https://www.bbsmax.com/A/kvJ3OWeXJg/(参考:Qt所有样式表,翻译版)