QT 自动伸缩的工具栏和自定义配置的工具栏 QToolBar更多按钮的样式设置
1.实现目标
如下图所示,播放窗口的工具栏,有很多按钮,当窗口的宽度不够时,能够自动生成更多按钮,点击更过按钮就会出现多余按钮的menu菜单;
2。实现方法
一开始我还想着加个按钮控件,在播放窗口resize函数中判断工具栏的宽度能容纳几个按钮,判断宽度是否够,如果不够的话,则要显示更多按钮,点击更多按钮,在弹出个QMenu菜单,显示更多的工具按钮;后来发现是我想复杂了,其实QToolBar已经支持了这个自动缩放自动跳整的功能;只要全部加到QToolBar中,它会自己根据宽度来判断显示几个,是否要显示更多按钮,点击按钮自动弹出Qmenu菜单;而且还可以是QToolBar中只有图标,更多菜单是图标加汉字说明;
2.1点击更多按钮后默认图标会很小,通过下面定义,可以改变图标大小;
#pragma once #include <QProxyStyle> class CustomStyle : public QProxyStyle { Q_OBJECT public: virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { if (metric == QStyle::PM_SmallIconSize|| metric==QStyle::PM_ButtonIconSize) { return 24; } return QProxyStyle::pixelMetric(metric, option, widget); } };
2.2工具栏按钮头文件
#ifndef PLAYWNDTOOLBAR_H #define PLAYWNDTOOLBAR_H #include <QWidget> #include "ui_PlayWndToolBar.h" #include <QToolBar> #include "MenuBar/Menu.h" class PlayWndToolBar : public QWidget { Q_OBJECT public: PlayWndToolBar(QWidget *parent = 0); ~PlayWndToolBar(); int UpdateToolBar(QList<int> tools); int setToolVisiable(int id, bool visible); bool GetToolCheckState(int id); void SetToolCheckState(int id, bool checked=false); int ClickTool(int id); signals: void SignalToolBtnClicked(int id, bool checked); private: Ui::PlayWndToolBar ui; QToolBar* ptr_toolbar_{ nullptr }; QAction* CreateActionById(int id); void InitToolBarExtendedMenu(QToolBar* ptr_toolbar); QMap<int, QAction*> m_mapAction; }; #endif // PLAYWNDTOOLBAR_H
2.3工具栏按钮cpp文件
#include "PlayWndToolBar.h" #include <QMenu> #include "VideoConfig/ToolActionBaseDef.h" #include "VideoConfig/Controller/LocalSystemConfigManager.h" #pragma execution_character_set("utf-8") #include"CustomStyle.h" #include <QToolButton> PlayWndToolBar::PlayWndToolBar(QWidget *parent) : QWidget(parent) { ui.setupUi(this); //设置为无边框,自定义关闭,放大,缩小按钮 this->setWindowFlags(Qt::FramelessWindowHint); ptr_toolbar_ = new QToolBar(ui.widgetToolBar); ptr_toolbar_->setObjectName("ptr_playwnd_toolbar_"); ptr_toolbar_->setFixedHeight(32); ptr_toolbar_->setIconSize(QSize(32, 32)); ptr_toolbar_->setToolButtonStyle(Qt::ToolButtonIconOnly);//设置只有图标 ptr_toolbar_->setContextMenuPolicy(Qt::PreventContextMenu); ptr_toolbar_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);//横向设置为preferred,会自动根据长度调整,否则不会 CustomStyle* pCustomStytle = new CustomStyle();//更多菜单菜单按钮的图标默认会很小,这个作用是让菜单图标变大 ptr_toolbar_->setStyle(pCustomStytle); ui.horizontalLayToolbar->addWidget(ptr_toolbar_); /*QAction* paction = new QAction(); QIcon favorite_icon_image; favorite_icon_image.addPixmap(QPixmap(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_record_nor.svg"), QIcon::Normal); favorite_icon_image.addPixmap(QPixmap(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_record_sel.svg"), QIcon::Active); paction->setIcon(favorite_icon_image); paction->setIconText("录像");*/ //ptr_toolbar_->addAction(paction); //设置样式:弹出菜单,文字距离图标30 ptr_toolbar_->setStyleSheet("QToolBar{background:#3D3D3D;} QMenu::item{ height:34px;width:120px; padding-left:30px;} QMenu::item:pressed { background-color: rgb(32,128,247);color:#FFFFFF }"); InitToolBarExtendedMenu(ptr_toolbar_); //connect(ui.pBMore, &QPushButton::clicked, this, [=]() { // /*ptr_toolbar_->removeAction(paction); // ptr_extral_menu->addAction(paction);*/ // ptr_extral_menu->exec(QCursor::pos()); //}); //ui.pBMore->hide(); } PlayWndToolBar::~PlayWndToolBar() { } int PlayWndToolBar::UpdateToolBar(QList<int> tools) { QList<QAction*> listaction=ptr_toolbar_->actions(); for (int i = 0; i < listaction.size(); i++) { ptr_toolbar_->removeAction(listaction.at(i)); } for (int i=0;i<tools.size();i++) { if (m_mapAction.find(tools.at(i))!=m_mapAction.end())//已有 { ptr_toolbar_->addAction(m_mapAction[tools.at(i)]); } else { QAction* pAction = CreateActionById(tools.at(i)); if (pAction!=NULL) { ptr_toolbar_->addAction(pAction); m_mapAction.insert(tools.at(i), pAction); } } } //listaction = ptr_extral_menu->actions(); //ptr_toolbar_->setMaximumWidth(width); //ptr_toolbar_->resize(width, 32); //for (int i = 0; i < listaction.size(); i++) //{ // ptr_extral_menu->removeAction(listaction.at(i)); //} //for (int i=shownum;i<tools.size();i++) //{ // if (m_mapAction.find(tools.at(i)) != m_mapAction.end())//已有 // { // ptr_extral_menu->addAction(m_mapAction[tools.at(i)]); // } // else // { // QAction* pAction = CreateActionById(tools.at(i)); // if (pAction != NULL) // { // ptr_extral_menu->addAction(pAction); // } // } //} /*if (shownum<tools.size()) { ui.pBMore->show(); } else { ui.pBMore->hide(); }*/ return 0; } int PlayWndToolBar::setToolVisiable(int id, bool visible) { int ret = -1; if (m_mapAction.find(id)!=m_mapAction.end()) { m_mapAction[id]->setVisible(visible); ret = 0; } return ret; } bool PlayWndToolBar::GetToolCheckState(int id) { bool ret = false; if (m_mapAction.find(id) != m_mapAction.end()) { ret=m_mapAction[id]->isChecked(); } return ret; } void PlayWndToolBar::SetToolCheckState(int id,bool checked) { if (m_mapAction.find(id) != m_mapAction.end()) { m_mapAction[id]->setChecked(checked); } } int PlayWndToolBar::ClickTool(int id) { int ret = -1; if (m_mapAction.find(id) != m_mapAction.end()) { m_mapAction[id]->trigger(); ret = 0; } return ret; } QAction* PlayWndToolBar::CreateActionById(int id) { QString strType = ""; QAction* pAction=NULL; pAction = new QAction(); ToolActionBaseDef::ToolActionId toolid = (ToolActionBaseDef::ToolActionId)id; switch (toolid) { case ToolActionBaseDef::ActSnapShot://抓图 strType=("snapshot"); pAction->setText("抓图"); break; case ToolActionBaseDef::ActRecord://录像 strType=("record"); pAction->setCheckable(true); pAction->setText("开始录像"); pAction->setToolTip("开始录像"); connect(pAction, &QAction::triggered, [=](bool checked) { if (checked) { pAction->setText("停止录像"); pAction->setToolTip("停止录像"); } else { pAction->setText("开始录像"); pAction->setToolTip("开始录像"); } }); break; case ToolActionBaseDef::ActClip: strType=("clip"); // 剪裁 pAction->setCheckable(true); pAction->setText("开始剪辑"); pAction->setToolTip("开始剪辑"); connect(pAction, &QAction::triggered, [=](bool checked) { if (checked) { pAction->setText("停止录像"); pAction->setToolTip("停止录像"); } else { pAction->setText("开始剪辑"); pAction->setToolTip("开始剪辑"); } }); break; case ToolActionBaseDef::ActVoice: strType=("voice"); pAction->setCheckable(true); pAction->setText("打开声音"); pAction->setToolTip("打开声音"); connect(pAction, &QAction::triggered, [=](bool checked) { if (checked) { pAction->setText("关闭声音"); pAction->setToolTip("关闭声音"); } else { pAction->setText("打开声音"); pAction->setToolTip("打开声音"); } }); break; /*case ToolActionBaseDef::ActDigitZoom: strType=("DigitalZoom"); break; case ToolActionBaseDef::ActStreamInfo: strType=("CodeFlowInformation"); break; case ToolActionBaseDef::ActVideoEnhance: strType=("VideoEnhancementKxymFxkcRb"); break; case ToolActionBaseDef::ActSwitchStream: strType=("SwitchStreamTypeMEByrOKBEBPh"); break; case ToolActionBaseDef::ActFisheyeExpand: strType=("FisheyeExpansion"); break; case ToolActionBaseDef::ActProjectOnWall: strType=("OnTheWallYMQjuSKWuxlcYt"); break; case ToolActionBaseDef::ActCreateDigitZoomRect: strType=("LzinJeCFDfFNWAdAyv"); break; case ToolActionBaseDef::ActCreateFisheyeExpandRect: strType=("SYsBmbMVVddcQbHIps"); break;*/ case ToolActionBaseDef::ActWndPTZ: strType=("ptz"); pAction->setCheckable(true); pAction->setText("打开云台"); pAction->setToolTip("打开云台"); connect(pAction, &QAction::triggered, [=](bool checked) { if (checked) { pAction->setText("关闭云台"); pAction->setToolTip("关闭云台"); } else { pAction->setText("打开云台"); pAction->setToolTip("打开云台"); } }); break; /*case ToolActionBaseDef::ActInstantPlayback: strType=("InstantReplayHHnDasyk"); break; case ToolActionBaseDef::ActJumpPlayBack: strType=("playback"); break; case ToolActionBaseDef::ActPictureView: strType=("ImagePreview"); break; case ToolActionBaseDef::ActIoControl: strType=("AlarmOutput"); break;*/ case ToolActionBaseDef::ActVoiceTalk: strType=("talk"); pAction->setCheckable(true); pAction->setText("开始对讲"); pAction->setToolTip("开始对讲"); connect(pAction, &QAction::triggered, [=](bool checked) { if (checked) { pAction->setText("停止对讲"); pAction->setToolTip("停止对讲"); } else { pAction->setText("开始对讲"); pAction->setToolTip("开始对讲"); } }); break; /*case ToolActionBaseDef::ActGunBallLinkage: strType=("ManualLinkageXKcVVbWi"); break; case ToolActionBaseDef::ActCrowdSituation: strType=("PersonnelSituationMoHMjjCdPl"); break;*/ case ToolActionBaseDef::ActDownload: strType=("download"); pAction->setText("下载"); pAction->setToolTip("下载"); break; //case ToolActionBaseDef::ActTag: // strType=("AddTagsJEJawyEj"); // break; //case ToolActionBaseDef::ActLock: // strType=("LockTheVideowbhEyJZAZRxYMHzd"); // break; //case ToolActionBaseDef::ActDrawFrame: // strType=("SmokeFramePlaybackQEdJCzZWG"); // break; //case ToolActionBaseDef::ActAdvanceSeconds: // strType=("ForwardForSecondscqlcqpzgfN"); // break; //case ToolActionBaseDef::ActSegmentPlayback: // strType=("SegmentedPlaybackMlCaRlzC"); // break; //case ToolActionBaseDef::ActSynPlayback: // strType=("SynPlayback"); // break; case ToolActionBaseDef::ActInstantReplay://快速回放 strType=("instantreplay"); pAction->setCheckable(true); pAction->setText("快速回放"); pAction->setToolTip("快速回放"); connect(pAction, &QAction::triggered, [=](bool checked) { if (checked) { pAction->setText("返回"); pAction->setToolTip("返回"); } else { pAction->setText("快速回放"); pAction->setToolTip("快速回放"); } }); break; //case ToolActionBaseDef::ActDisplayRotate://画面旋转 // strType=("HCP-ControlClient.01bbc3a41711441caa2b154043b153a7.button"); // break; //case ToolActionBaseDef::ActOneTouchPark://云台守望 // strType=("YuntaiWatchman"); // break; //case 302: // 抓图打印 // strType=("Print"); //case 303: // 可视追踪 // strType=("VisualTrackingksjvBhjq"); // break; //case 304: // ActSearchByImage // strType=("SearchByPicture"); // break; //case ToolActionBaseDef::ActHealthStatus: // 监控点状态 // strType=("CameraStatus"); // break; //case 306: // 布撤防 // strType=("ClothRemovalIhetFufd"); //case 307: // ActGoToVCA // strType=("VCARetrievalbyXHuolipNGDNDcV"); // break; // //case 308: // 枪球联动 // // strType=("ManualLinkageXKcVVbWi"); //case 309: // 广播 // strType=("Broadcast"); // break; //case 310: // 目标属性叠加 // strType=("HCP-ControlClient.ef621b1899474895b0378a2c891fab1a.name"); // break; //case ToolActionBaseDef::ActCloseSingle: // strType=("Close"); // break; //case ToolActionBaseDef::ActCloseAllWindows: // strType=("CloseAll"); // break; //case ToolActionBaseDef::ActLocateToTree: // strType=("LocateToTree"); // break; //case ToolActionBaseDef::ActReturn: // strType=("Return"); // break; //case ToolActionBaseDef::ActProblemCreate: // strType=("ProblemCreate"); // break; //case ToolActionBaseDef::ActAddFavorite: // strType=("AddFavorite"); // break; //case ToolActionBaseDef::ActFullScreen: // strType=("SwitchFullScreen"); // break; default: break; } if (strType!="") { QIcon button_icon; button_icon.addPixmap(QPixmap(QString(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_%1_nor.svg").arg(strType)), QIcon::Normal); button_icon.addPixmap(QPixmap(QString(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_%1_dis.svg").arg(strType)), QIcon::Disabled); button_icon.addPixmap(QPixmap(QString(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_%1_hover.svg").arg(strType)), QIcon::Active); button_icon.addPixmap(QPixmap(QString(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_%1_nor.svg").arg(strType)), QIcon::Selected); if (pAction->isCheckable()) { button_icon.addPixmap(QPixmap(QString(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_%1_sel.svg").arg(strType)), QIcon::Normal, QIcon::On); button_icon.addPixmap(QPixmap(QString(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_%1_dis.svg").arg(strType)), QIcon::Disabled, QIcon::On); button_icon.addPixmap(QPixmap(QString(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_%1_sel.svg").arg(strType)), QIcon::Active, QIcon::On); button_icon.addPixmap(QPixmap(QString(":/preview/Resources/pic/Preview/ToolIcon/icon_tool_%1_sel.svg").arg(strType)), QIcon::Selected, QIcon::On); } pAction->setIcon(button_icon); pAction->setData(toolid); connect(pAction, &QAction::triggered, [=](bool checked) { emit SignalToolBtnClicked(toolid, checked); }); } else { if (pAction != NULL) { delete pAction; pAction = NULL; } } return pAction; } void PlayWndToolBar::InitToolBarExtendedMenu(QToolBar* ptr_toolbar) { // QToolBar更多按钮样式图标设置 auto* ptr_ext_btn = ptr_toolbar->findChild<QToolButton*>("qt_toolbar_ext_button"); ptr_ext_btn->setToolTip(QObject::tr("更多")); // tip:更多 // 更多按钮显示样式, 自测过程发现写在qss中不生效,使用QIcon代替 QIcon extbutton_icon; extbutton_icon.addPixmap(QPixmap(":/playback/Resources/pic/Playback/ToolIcon/icon_tool_more_nor.svg"), QIcon::Normal); extbutton_icon.addPixmap(QPixmap(":/playback/Resources/pic/Playback/ToolIcon/icon_tool_more_horver.svg"), QIcon::Active); extbutton_icon.addPixmap(QPixmap(":/playback/Resources/pic/Playback/ToolIcon/icon_tool_more_horver.svg"), QIcon::Selected); extbutton_icon.addPixmap(QPixmap(":/playback/Resources/pic/Playback/ToolIcon/icon_tool_more_disr.svg"), QIcon::Disabled); extbutton_icon.addPixmap(QPixmap(":/playback/Resources/pic/Playback/ToolIcon/icon_tool_more_nor.svg"), QIcon::Normal, QIcon::On); extbutton_icon.addPixmap(QPixmap(":/playback/Resources/pic/Playback/ToolIcon/icon_tool_more_horver.svg"), QIcon::Active, QIcon::On); extbutton_icon.addPixmap(QPixmap(":/playback/Resources/pic/Playback/ToolIcon/icon_tool_more_horver.svg"), QIcon::Selected, QIcon::On); extbutton_icon.addPixmap(QPixmap(":/playback/Resources/pic/Playback/ToolIcon/icon_tool_more_dis.svg"), QIcon::Disabled, QIcon::On); ptr_ext_btn->setIcon(extbutton_icon); //// 取出先前的扩展菜单,并创建新的菜单,准备替换 //auto* old_ext_menu = ptr_ext_btn->menu(); //HUIControl::CMenu* ptr_new_menu = new HUIControl::CMenu(ptr_ext_btn); ////ptr_new_menu->setStyle(old_ext_menu->style()); //ptr_new_menu->setWindowFlag(Qt::NoDropShadowWindowHint); ////ptr_new_menu->setObjectName(menu_obj_name); //// 并设置新的菜单 //ptr_ext_btn->setMenu(ptr_new_menu); //// 针对从右向左布局的语种通过右侧留间隙的方式,保证右侧图标可见 //// if(QGuiApplication::layoutDirection() == Qt::RightToLeft) //// ptr_new_menu->setStyleSheet("QMenu::item{ padding-right: 42; }"); //if (init_width) // ptr_new_menu->setMinimumWidth(213); //// 断开QToolButton内部的信号槽关联,接管弹出菜单处理,避免因如下槽函数执行偏晚, //// action未填入,菜单宽度为0,导致阿语(从右向左布局)出现弹出菜单的方向不对问题 //ptr_ext_btn->disconnect(ptr_ext_btn); //QObject::connect(ptr_ext_btn, &QToolButton::pressed, ptr_toolbar, [old_ext_menu, ptr_new_menu, ptr_ext_btn]() //{ // ptr_new_menu->clear(); // ptr_new_menu->addActions(old_ext_menu->actions()); // //ptr_new_menu->setStyle(new CPlayIconStyle); // ptr_ext_btn->showMenu(); //}); }
自己开发了一个股票智能分析软件,功能很强大,需要的关注微信公众号:QStockView