Redrawing QMenu
-
First question:
When I redrew QMenu, I used QStyleOptionMenuItem to redraw the menu item and reset the icon in option, but the icon size in the menu item did not change. How should I deal with this? -
Hi and welcome to devnet,
Which version of Qt ?
On which platform ?
You should also share a minimal compilable example that shows this behavior. -
Hi .
I am using qt version 5.15.2 on windows platform.
I am a newbie and this is my first attempt to draw a control using QStyleOption.
This is a reimplement of paintEvent fuciton for my menu.void myMenu::paintEvent(QPaintEvent* event) { QMenu::paintEvent(event); QPainter p(this); QRegion emptyArea = QRegion(rect()); QStyleOptionMenuItem menuOpt; menuOpt.initFrom(this); menuOpt.state = QStyle::State_None; menuOpt.checkType = QStyleOptionMenuItem::NotCheckable; menuOpt.maxIconWidth = 0; menuOpt.tabWidth = 0; style()->drawPrimitive(QStyle::PE_FrameMenu, &menuOpt, &p, this); QList<QAction*> actionList = actions(); for (int i = 0; i < actionList.count(); ++i) { QAction* action = actionList.at(i); QRect adjustedActionRect = actionGeometry(action); if (!event->rect().intersects(adjustedActionRect)) continue; QStyleOptionMenuItem opt; initStyleOption(&opt, action); opt.rect = adjustedActionRect; style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this); } }
This is the initStyleOption function used in the PaintEvent function above.
void myMenu::initStyleOption(QStyleOptionMenuItem* option, QAction* action) const { QMenu::initStyleOption(option, action); int mergin = 0; int iconWithTextDistance = 6; QIcon icon = option->icon; const int widgetHeight = option->rect.width() - mergin * 2; option->maxIconWidth = widgetHeight; if (!icon.isNull()) { QSize iconSize = icon.actualSize(QSize(widgetHeight, widgetHeight), (option->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled, (option->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off); auto icona = icon.pixmap(iconSize); option->icon = icona; } }
This is the drawing code, if there is anything else I need to provide, please leave a message to me directly, I am very much looking forward to your reply.
-
Hi .
I am using qt version 5.15.2 on windows platform.
I am a newbie and this is my first attempt to draw a control using QStyleOption.
This is a reimplement of paintEvent fuciton for my menu.void myMenu::paintEvent(QPaintEvent* event) { QMenu::paintEvent(event); QPainter p(this); QRegion emptyArea = QRegion(rect()); QStyleOptionMenuItem menuOpt; menuOpt.initFrom(this); menuOpt.state = QStyle::State_None; menuOpt.checkType = QStyleOptionMenuItem::NotCheckable; menuOpt.maxIconWidth = 0; menuOpt.tabWidth = 0; style()->drawPrimitive(QStyle::PE_FrameMenu, &menuOpt, &p, this); QList<QAction*> actionList = actions(); for (int i = 0; i < actionList.count(); ++i) { QAction* action = actionList.at(i); QRect adjustedActionRect = actionGeometry(action); if (!event->rect().intersects(adjustedActionRect)) continue; QStyleOptionMenuItem opt; initStyleOption(&opt, action); opt.rect = adjustedActionRect; style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this); } }
This is the initStyleOption function used in the PaintEvent function above.
void myMenu::initStyleOption(QStyleOptionMenuItem* option, QAction* action) const { QMenu::initStyleOption(option, action); int mergin = 0; int iconWithTextDistance = 6; QIcon icon = option->icon; const int widgetHeight = option->rect.width() - mergin * 2; option->maxIconWidth = widgetHeight; if (!icon.isNull()) { QSize iconSize = icon.actualSize(QSize(widgetHeight, widgetHeight), (option->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled, (option->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off); auto icona = icon.pixmap(iconSize); option->icon = icona; } }
This is the drawing code, if there is anything else I need to provide, please leave a message to me directly, I am very much looking forward to your reply.
@Zack-Zheng why are you calling the base class implementation since you are repainting everything anyway ?
Depending on the final goal, a QProxyStyle might be simpler.
-
@Zack-Zheng why are you calling the base class implementation since you are repainting everything anyway ?
Depending on the final goal, a QProxyStyle might be simpler.
@SGaist Since I am not familiar with the process of control redrawing, after calling the redrawing operation of the base class, that is, making a setting to StyleOption, I want to make some changes based on the StyleOption after setting.
I think I understand that the purpose of the InitStyleOption function is to get various information about the control to be drawn, but my purpose is to modify the style of the menu item element, and using customStyle is more suitable for my purpose.
I'm not sure I'm understanding this correctly. If there is anything wrong, I hope you can correct me. Thank you for your reply.Looking forward to your reply. -
@Zack-Zheng why are you calling the base class implementation since you are repainting everything anyway ?
Depending on the final goal, a QProxyStyle might be simpler.
@SGaist Hi SGaist, This is my problem.
void RibbonPopMenu::paintEvent(QPaintEvent* event) { QPainter p(this); QRegion emptyArea = QRegion(rect()); QStyleOptionMenuItem menuOpt; menuOpt.initFrom(this); menuOpt.state = QStyle::State_None; menuOpt.checkType = QStyleOptionMenuItem::NotCheckable; menuOpt.maxIconWidth = 0; menuOpt.tabWidth = 0; style()->drawPrimitive(QStyle::PE_FrameMenu, &menuOpt, &p, this); QList<QAction> actionList = actions(); for (int i = 0; i < actionList.count(); ++i) { QAction action = actionList.at(i); QRect adjustedActionRect = actionGeometry(action); if (!event->rect().intersects(adjustedActionRect)) continue; QStyleOptionMenuItem opt; opt.initFrom(this); initStyleOption(&opt, action); opt.rect = adjustedActionRect; style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this); } }
This is the PaintEvent event for my custom control, and I've also created a CustomStyle that I've already set when I enable it.
m_AppButtonMenu->setStyle(new CustomStyle());
Here, m_AppButtonMenu is of type RibbonPopMenu.
But inside the PaintEvent function, style()->drawPrimitive(QStyle::PE_FrameMenu, &menuOpt, &p, this); this function and style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this); Normally, the overloaded function in my CustomStyle should be called, but I only called the first one during debugging, but not the second one. Why? -
@SGaist Hi SGaist, This is my problem.
void RibbonPopMenu::paintEvent(QPaintEvent* event) { QPainter p(this); QRegion emptyArea = QRegion(rect()); QStyleOptionMenuItem menuOpt; menuOpt.initFrom(this); menuOpt.state = QStyle::State_None; menuOpt.checkType = QStyleOptionMenuItem::NotCheckable; menuOpt.maxIconWidth = 0; menuOpt.tabWidth = 0; style()->drawPrimitive(QStyle::PE_FrameMenu, &menuOpt, &p, this); QList<QAction> actionList = actions(); for (int i = 0; i < actionList.count(); ++i) { QAction action = actionList.at(i); QRect adjustedActionRect = actionGeometry(action); if (!event->rect().intersects(adjustedActionRect)) continue; QStyleOptionMenuItem opt; opt.initFrom(this); initStyleOption(&opt, action); opt.rect = adjustedActionRect; style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this); } }
This is the PaintEvent event for my custom control, and I've also created a CustomStyle that I've already set when I enable it.
m_AppButtonMenu->setStyle(new CustomStyle());
Here, m_AppButtonMenu is of type RibbonPopMenu.
But inside the PaintEvent function, style()->drawPrimitive(QStyle::PE_FrameMenu, &menuOpt, &p, this); this function and style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this); Normally, the overloaded function in my CustomStyle should be called, but I only called the first one during debugging, but not the second one. Why?@Zack-Zheng Can you provide a minimal complete code sample ? That way we can test it on our side rather that having to put pieces together.