- QMenu和QMenuBar都是QWidget的派生类,按理说也没有什么特别的。只是真的想理清它,似乎还真的不是那么简单...
QMenuBar
在漫谈QWidget及其派生类(三)中,我们已经知道:QMenuBar和QStatusBar都是QWidget的派生类,所以我们可以像添加一个QPushButton一样将它们任意放置到另一个QWidget中。
继续看个别的例子:
#include <QtGui>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMenuBar menubar;
menubar.addAction("Action1");
menubar.addAction("Action1");
menubar.show();
return app.exec();
}
我们知道,QWidget本来就有一个成员函数:
void QWidget::addAction ( QAction * action )
而此处只不过是QMenuBar提供的重载版本:
QAction *QMenuBar::addAction(const QString &text)
{
QAction *ret = new QAction(text, this);
addAction(ret);
return ret;
}
可是同样的东西,到了QMenuBar中,就显示出一种菜单栏的效果了呢?
不同的Widget,为什么不一样?我们都会自定义控件,所以都熟悉:
void QMenuBar::paintEvent(QPaintEvent *e)
{
...
for (int i = 0; i < d->actions.count(); ++i) {
QAction *action = d->actions.at(i);
QRect adjustedActionRect = d->actionRect(action);
...
便利它自身的actions列表,然后依次将它们paint出来。
然后当触发快捷键,或者在某个区域点击鼠标时:
void QMenuBar::mousePressEvent(QMouseEvent *e)
{
...
QAction *action = d->actionAt(e->pos());
....
d->setCurrentAction(action, true);
...
addMenu()
在继续之前,我们需要简单了解一下addAction和addMenu
QMenu *QMenuBar::addMenu(const QString &title)
{
QMenu *menu = new QMenu(title, this);
addAction(menu->menuAction());
return menu;
}
看,无非是创建一个QMenu,然后将该菜单对应的QAction添加进来了。而这个QMenu,稍候可以通过对应的QAction的成员函数
QMenu * QAction::menu () const
来获得
先看看QMenu,稍候再回来
QMenu
QMenu 也是一个QWidget的派生类
- 一个规规矩矩的矩形窗口(窗口类别 Qt::Popup)
- 通过setVisible(true)或show()使其显示出来
但是,为什么QMenu长成这个样子呢,一条一条的?
其实看了前面的QMenuBar,我们对QMenu为什么长这个样子,应该不会感到任何惊奇了。
先添加一些QAction,然后在paintEvent中遍历Action列表,并画出一个一个矩形条。
void QMenu::paintEvent(QPaintEvent *e)
{
//draw the items that need updating..
for (int i = 0; i < d->actions.count(); ++i) {
QAction *action = d->actions.at(i);
...
当然,为了有点立体效果,或者说为了让QMenu和其他东西分开,还需要画边框。
上下文菜单
我们在一个Widget的某个位置上点击右键,或者通过键盘上某个键。会弹出上下文菜单。
这个菜单和我们在菜单栏看到的菜单其实没有区别,要说区别的话,就是需要我们自己:
考虑:一般我们是如何使用上下文菜单的?
void Widget::contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
menu.addAction("A1");
menu.addAction("A2");
filemenu->exec(this->mapToGlobal(event.pos()));
如何显示?
- 记得刚接触这个东西时,在这个地方都是犯糊涂。这儿为什么不能直接用event中的位置,而是要map到全局坐标。
还是要从QMenu是QWidget的派生类说起。在前面我们提到了这样的内容:
- QWidget分:窗口(Window)和部件(Widget)两类。前者的位置是全局的或者说相对屏幕的,后者坐标是相对父部件的
QMenu 是 Window,所以位置坐标是全局的。而event坐标是当前窗口部件的。
- 显示一个QWidget,我们必须调用setVisible(true)/show()才行!!这儿用的确实exec(),我们类比QDialog的话,很容易才到答案。
其内部肯定调用了show(),而且还使用QEventLoop开启了局部的事件循环。
popup()
既然直接调用show()就可以让菜单显示出来,这个popup()又有何用?
void QMenu::popup(const QPoint &p, QAction *atAction)
{
...
}
它做的工作:
- 确保样式和字体被正确设置
- 调整几何尺寸(位置和大小)
- 调用show() 显示
而我们刚提到的exec()就是在popup的基础上加了个事件循环
QAction *QMenu::exec(const QPoint &p, QAction *action)
{
QEventLoop eventLoop;
d->eventLoop = &eventLoop;
popup(p, action);
...
回到菜单栏
了解了上下文菜单,我们可以回头看看菜单栏是如何控制菜单显示的。
一开始说了,
- 菜单对应的action被加入到了菜单栏
- 菜单栏在paintEvent绘制我们熟悉的那一栏东西
- 当我们点击鼠标时,菜单栏mousePressEvent中判断位置对应哪个action
- 这样就到了...
void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
{
if(!action || !action->menu() || losePopupMode)
return;
activeMenu = action->menu();
....
activeMenu->popup(pos);
源码中,最长的一段就是在计算和调整菜单的位置(以确保菜单不会跑到屏幕外),即那个pos
分享到:
相关推荐
中心部件通常是一个继承自 `QWidget` 的自定义部件,但也可以是其他 `QWidget` 派生类的实例。以下是如何在 `QMainWindow` 中使用中心部件的说明和一个简单的实例讲解。 + **中心部件的使用说明:** 1. **创建中心...
QWidget 直接派生类的样式表不起作用的解决办法,相关教程链接如下: http://blog.csdn.net/tennysonsky/article/details/46653571
026 QWidget类分析显示和隐藏接口说明线程类QThread使用方法.7z
Qt编程基础 - 第六章-窗体 - 6.4、QWidget 自定义右键菜单
定制QWidget标题栏的示例,并含有qss配置QTabWidget样式的示例,以及展示如何显示一个不在状态栏出现的窗口
通过基本控件QPushButton,QWidget,实现下拉菜单,可以展开多级菜单。
QT插件实现了界面收缩栏效果 1、可以在收缩栏中添加界面 2、可以对添加的界面进行收起或展开 3、可以拖动界面变换界面的位置 用法链接:...
该代码总结了三种QMenu用法,有基本菜单用法,有两种自定义菜单,编译环境是Qt5.9.4+MinGW32+Creator4.5.0编译器,具体的原理讲解可以参考博主博客:...
自实现的一个翻转QWidget的demo;采用QPainter和QPropertyAnimation实现,是一个学习动画设计的高效demo
qwidge窗口嵌入qml窗口, qml调用qwidget方法 qwidget发送信号传递数据 qml信号处理以及注意事项
QWidget嵌入qml,实现QWidget与qml的交互、无标题栏、可拉伸、可拖动、可切换qml页面
QWidget,QMainWindow和QDialog的区别.
QT 2个QWidget UI 来回切换例子,并且ui界面可自行单独处理单独cpp和h文件,相互不影响。
支持图片的缩放、拖动、右键菜单等功能,直接提升窗口或者增加UI到指定layout即可使用
两个QWidget互相交换显示
Qt QWidget 互斥抽屉模型Qt QWidget 互斥抽屉模型 Qt5.0~Qt6..4均能编译通过
实现把QWidget嵌入到QML中,实现方案已经在博客中说明。
QWidget嵌入Qml界面的小Demo,比较简单的代码,可以提供大家参考!但是还是有一些问题需要大家解决,如果有一些BUG能告知最好
QT 框接的qwidget实现方法
本程序实现:单击qml页面,更新按钮的文本;单击按钮,更新qml页面的颜色;展示qml嵌入QWidget方法与通信