QT分析之QPushButton的初始化
原文地址:http://blog.163.com/net_worm/blog/static/127702419201001003326522/
在简单的QT程序的第二行,声明了一个QPushButton的对象。先简单看看其初始化过程。
QPushButton的类继承关系为:
- QPushButton :public QAbstractButton :pubic QWidget :public QObject, public QPaintDevice
QPushButton的构造:
- QPushButton::QPushButton(const QString &text, QWidget *parent)
- : QAbstractButton(*new QPushButtonPrivate, parent)
- {
- Q_D(QPushButton); // 声明并获得QPushButtonPrivate函数指针d
- setText(text); // 设置按钮的名字
- d->init(); // 调用QPushButtonPrivate::init(),其实只是重新设定排布间隔
- }
新生成的QPushButtonPrivate对象传递给QAbstractButton之后,发生了什么事呢?
- QAbstractButton::QAbstractButton(QAbstractButtonPrivate &dd, QWidget *parent)
- : QWidget(dd, parent, )
- {
- Q_D(QAbstractButton); // 声明并获得QAbstractButtonPrivate函数指针d
- d->init(); // 调用QAbstractButtonPrivate::init()
- }
QAbstractButtonPrivate::init()做了什么呢?其实只是调用了QPushButton的几个设定函数。
继续看QWidget的初始化过程。
- QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
- : QObject(dd, ), QPaintDevice()
- {
- d_func()->init(parent, f);
- }
其中d_func()是宏定义Q_DECLARE_PRIVATE(QWidget)中定义的,获取QWidgetPrivate指针的函数。有点奇怪的是,这里怎么没有用Q_D宏定义,与之前的风格有点不同。
QWidgetPrivate::init()里做了什么动作呢?(关键语句用颜色标记)
- void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
- {
- Q_Q(QWidget);
- if (qApp->type() == QApplication::Tty)
- qFatal("QWidget: Cannot create a QWidget when no GUI is being used");
- Q_ASSERT(uncreatedWidgets);
- uncreatedWidgets->insert(q);
- QWidget *desktopWidget = ;
- if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
- desktopWidget = parentWidget;
- parentWidget = ;
- }
- q->data = &data;
- if (!q->parent()) {
- Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
- "Widgets must be created in the GUI thread.");
- }
- data.fstrut_dirty = true;
- data.winid = ;
- data.widget_attributes = ;
- data.window_flags = f;
- data.window_state = ;
- data.focus_policy = ;
- data.context_menu_policy = Qt::DefaultContextMenu;
- data.window_modality = Qt::NonModal;
- data.sizehint_forced = ;
- data.is_closing = ;
- data.in_show = ;
- data.in_set_window_state = ;
- data.in_destructor = false;
- // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
- if (f & Qt::MSWindowsOwnDC)
- q->setAttribute(Qt::WA_NativeWindow);
- q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
- adjustQuitOnCloseAttribute();
- q->setAttribute(Qt::WA_WState_Hidden);
- //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later
- data.crect = parentWidget ? QRect(,,,) : QRect(,,,);
- focus_next = focus_prev = q;
- if ((f & Qt::WindowType_Mask) == Qt::Desktop)
- q->create(); // 调用了QWidget::create()
- else if (parentWidget)
- q->setParent(parentWidget, data.window_flags);
- else {
- adjustFlags(data.window_flags, q);
- resolveLayoutDirection();
- // opaque system background?
- const QBrush &background = q->palette().brush(QPalette::Window);
- setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
- }
- data.fnt = QFont(data.fnt, q);
- q->setAttribute(Qt::WA_PendingMoveEvent);
- q->setAttribute(Qt::WA_PendingResizeEvent);
- if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
- QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
- if (QApplicationPrivate::app_compile_version < 0x040200
- || QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation))
- q->create();
- // 下面的三行,产生并发送了Create事件
- QEvent e(QEvent::Create);
- QApplication::sendEvent(q, &e);
- QApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
- extraPaintEngine = ;
- }
看看QWidget::create()的实现:
- void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
- {
- Q_D(QWidget);
- if (testAttribute(Qt::WA_WState_Created) && window == && internalWinId())
- return;
- if (d->data.in_destructor)
- return;
- Qt::WindowType type = windowType();
- Qt::WindowFlags &flags = data->window_flags;
- if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
- type = Qt::Window;
- flags |= Qt::Window;
- }
- if (QWidget *parent = parentWidget()) {
- if (type & Qt::Window) {
- if (!parent->testAttribute(Qt::WA_WState_Created))
- parent->createWinId();
- } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
- && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
- // We're about to create a native child widget that doesn't have a native parent;
- // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
- // attribute is set.
- d->createWinId(window);
- // Nothing more to do.
- Q_ASSERT(testAttribute(Qt::WA_WState_Created));
- Q_ASSERT(internalWinId());
- return;
- }
- }
- static int paintOnScreenEnv = -;
- if (paintOnScreenEnv == -)
- paintOnScreenEnv = qgetenv("QT_ONSCREEN_PAINT").toInt() > ? : ;
- if (paintOnScreenEnv == )
- setAttribute(Qt::WA_PaintOnScreen);
- if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
- setAttribute(Qt::WA_NativeWindow);
- #ifdef ALIEN_DEBUG
- qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
- << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
- #endif
- // Unregister the dropsite (if already registered) before we
- // re-create the widget with a native window.
- if (testAttribute(Qt::WA_WState_Created) && !internalWinId() && testAttribute(Qt::WA_NativeWindow)
- && d->extra && d->extra->dropTarget) {
- d->registerDropSite(false);
- }
- d->updateIsOpaque();
- setAttribute(Qt::WA_WState_Created); // set created flag
- d->create_sys(window, initializeWindow, destroyOldWindow);
- // a real toplevel window needs a backing store
- if (isWindow()) {
- delete d->topData()->backingStore;
- // QWidgetBackingStore will check this variable, hence it must be 0
- d->topData()->backingStore = ;
- if (hasBackingStoreSupport())
- d->topData()->backingStore = new QWidgetBackingStore(this);
- }
- d->setModal_sys();
- if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
- setAttribute(Qt::WA_DropSiteRegistered, true);
- // need to force the resting of the icon after changing parents
- if (testAttribute(Qt::WA_SetWindowIcon))
- d->setWindowIcon_sys(true);
- if (isWindow() && !d->topData()->iconText.isEmpty())
- d->setWindowIconText_helper(d->topData()->iconText);
- if (windowType() != Qt::Desktop) {
- d->updateSystemBackground();
- if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
- d->setWindowIcon_sys();
- }
- }
这里QWidgetPrivate::create_sys()定义在QWidget_win.cpp里。
- void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
- {
- Q_Q(QWidget);
- static int sw = -, sh = -;
- Qt::WindowType type = q->windowType();
- Qt::WindowFlags flags = data.window_flags;
- bool topLevel = (flags & Qt::Window);
- bool popup = (type == Qt::Popup);
- bool dialog = (type == Qt::Dialog
- || type == Qt::Sheet
- || (flags & Qt::MSWindowsFixedSizeDialogHint));
- bool desktop = (type == Qt::Desktop);
- bool tool = (type == Qt::Tool || type == Qt::Drawer);
- HINSTANCE appinst = qWinAppInst();
- HWND parentw, destroyw = ;
- WId id;
- QString windowClassName = qt_reg_winclass(q);
- if (!window) // always initialize
- initializeWindow = true;
- if (popup)
- flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
- if (sw < ) { // get the (primary) screen size
- sw = GetSystemMetrics(SM_CXSCREEN);
- sh = GetSystemMetrics(SM_CYSCREEN);
- }
- if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget
- popup = false; // force this flags off
- if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95)
- data.crect.setRect(GetSystemMetrics( /* SM_XVIRTUALSCREEN */), GetSystemMetrics( /* SM_YVIRTUALSCREEN */),
- GetSystemMetrics( /* SM_CXVIRTUALSCREEN */), GetSystemMetrics( /* SM_CYVIRTUALSCREEN */));
- else
- data.crect.setRect(, , GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
- }
- parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : ;
- #ifdef UNICODE
- QString title;
- const TCHAR *ttitle = ;
- #endif
- QByteArray title95;
- int style = WS_CHILD;
- int exsty = ;
- if (window) {
- style = GetWindowLongA(window, GWL_STYLE);
- if (!style)
- qErrnoWarning("QWidget::create: GetWindowLong failed");
- topLevel = false; // #### needed for some IE plugins??
- } else if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
- style = WS_POPUP;
- } else if (topLevel && !desktop) {
- if (flags & Qt::FramelessWindowHint)
- style = WS_POPUP; // no border
- else if (flags & Qt::WindowTitleHint)
- style = WS_OVERLAPPED;
- else
- style = ;
- }
- if (!desktop) {
- // if (!testAttribute(Qt::WA_PaintUnclipped))
- // ### Commented out for now as it causes some problems, but
- // this should be correct anyway, so dig some more into this
- #ifndef Q_FLATTEN_EXPOSE
- style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
- #endif
- if (topLevel) {
- if ((type == Qt::Window || dialog || tool)) {
- if (!(flags & Qt::FramelessWindowHint)) {
- if (!(flags & Qt::MSWindowsFixedSizeDialogHint)) {
- style |= WS_THICKFRAME;
- if(!(flags &
- ( Qt::WindowSystemMenuHint
- | Qt::WindowTitleHint
- | Qt::WindowMinMaxButtonsHint
- | Qt::WindowCloseButtonHint
- | Qt::WindowContextHelpButtonHint)))
- style |= WS_POPUP;
- } else {
- style |= WS_POPUP | WS_DLGFRAME;
- }
- }
- if (flags & Qt::WindowTitleHint)
- style |= WS_CAPTION;
- if (flags & Qt::WindowSystemMenuHint)
- style |= WS_SYSMENU;
- if (flags & Qt::WindowMinimizeButtonHint)
- style |= WS_MINIMIZEBOX;
- if (shouldShowMaximizeButton())
- style |= WS_MAXIMIZEBOX;
- if (tool)
- exsty |= WS_EX_TOOLWINDOW;
- if (flags & Qt::WindowContextHelpButtonHint)
- exsty |= WS_EX_CONTEXTHELP;
- } else {
- exsty |= WS_EX_TOOLWINDOW;
- }
- }
- }
- if (flags & Qt::WindowTitleHint) {
- QT_WA({
- title = q->isWindow() ? qAppName() : q->objectName();
- ttitle = (TCHAR*)title.utf16();
- } , {
- title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1();
- });
- }
- // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
- // qapplication_win.cpp. We switch it off temporarily to avoid move
- // and resize events during creationt
- q->setAttribute(Qt::WA_WState_Created, false);
- if (window) { // override the old window
- if (destroyOldWindow)
- destroyw = data.winid;
- id = window;
- setWinId(window);
- LONG res = SetWindowLongA(window, GWL_STYLE, style);
- if (!res)
- qErrnoWarning("QWidget::create: Failed to set window style");
- #ifdef _WIN64
- res = SetWindowLongPtrA( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc );
- #else
- res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc );
- #endif
- if (!res)
- qErrnoWarning("QWidget::create: Failed to set window procedure");
- } else if (desktop) { // desktop widget
- id = GetDesktopWindow();
- // QWidget *otherDesktop = QWidget::find(id); // is there another desktop?
- // if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
- // otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
- // d->setWinId(id); // make sure otherDesktop is
- // otherDesktop->d_func()->setWinId(id); // found first
- // } else {
- setWinId(id);
- // }
- } else if (topLevel) { // create top-level widget
- if (popup)
- parentw = ;
- const bool wasMoved = q->testAttribute(Qt::WA_Moved);
- int x = wasMoved ? data.crect.left() : CW_USEDEFAULT;
- int y = wasMoved ? data.crect.top() : CW_USEDEFAULT;
- int w = CW_USEDEFAULT;
- int h = CW_USEDEFAULT;
- // Adjust for framestrut when needed
- RECT rect = {,,,};
- bool isVisibleOnScreen = !q->testAttribute(Qt::WA_DontShowOnScreen);
- if (isVisibleOnScreen && AdjustWindowRectEx(&rect, style & ~WS_OVERLAPPED, FALSE, exsty)) {
- QTLWExtra *td = maybeTopData();
- if (wasMoved && (td && !td->posFromMove)) {
- x = data.crect.x() + rect.left;
- y = data.crect.y() + rect.top;
- }
- if (q->testAttribute(Qt::WA_Resized)) {
- w = data.crect.width() + (rect.right - rect.left);
- h = data.crect.height() + (rect.bottom - rect.top);
- }
- }
- //update position & initial size of POPUP window
- if (isVisibleOnScreen && topLevel && initializeWindow && (style & WS_POPUP)) {
- if (!q->testAttribute(Qt::WA_Resized)) {
- w = sw/;
- h = *sh/;
- }
- if (!wasMoved) {
- x = sw/ - w/;
- y = sh/ - h/;
- }
- }
- QT_WA({
- const TCHAR *cname = (TCHAR*)windowClassName.utf16();
- id = CreateWindowEx(exsty, cname, ttitle, style,
- x, y, w, h,
- parentw, , appinst, );
- } , {
- id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
- x, y, w, h,
- parentw, , appinst, );
- });
- if (!id)
- qErrnoWarning("QWidget::create: Failed to create window");
- setWinId(id);
- if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
- SetWindowPos(id, HWND_TOPMOST, , , , , SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
- if (flags & Qt::WindowStaysOnBottomHint)
- qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
- } else if (flags & Qt::WindowStaysOnBottomHint)
- SetWindowPos(id, HWND_BOTTOM, , , , , SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
- winUpdateIsOpaque();
- } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget
- QT_WA({
- const TCHAR *cname = (TCHAR*)windowClassName.utf16();
- id = CreateWindowEx(exsty, cname, ttitle, style,
- data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
- parentw, NULL, appinst, NULL);
- } , {
- id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
- data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
- parentw, NULL, appinst, NULL);
- });
- if (!id)
- qErrnoWarning("QWidget::create: Failed to create window");
- SetWindowPos(id, HWND_TOP, , , , , SWP_NOMOVE | SWP_NOSIZE);
- setWinId(id);
- }
- if (desktop) {
- q->setAttribute(Qt::WA_WState_Visible);
- } else if (topLevel && !q->testAttribute(Qt::WA_DontShowOnScreen)) {
- RECT cr;
- GetClientRect(id, &cr);
- // one cannot trust cr.left and cr.top, use a correction POINT instead
- POINT pt;
- pt.x = ;
- pt.y = ;
- ClientToScreen(id, &pt);
- if (data.crect.width() == || data.crect.height() == ) {
- data.crect = QRect(pt.x, pt.y, data.crect.width(), data.crect.height());
- } else {
- data.crect = QRect(QPoint(pt.x, pt.y),
- QPoint(pt.x + cr.right - , pt.y + cr.bottom - ));
- }
- if (data.fstrut_dirty) {
- // be nice to activeqt
- updateFrameStrut();
- }
- }
- q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
- hd = ; // no display context
- if (window) { // got window from outside
- if (IsWindowVisible(window))
- q->setAttribute(Qt::WA_WState_Visible);
- else
- q->setAttribute(Qt::WA_WState_Visible, false);
- }
- if (extra && !extra->mask.isEmpty())
- setMask_sys(extra->mask);
- #if defined(QT_NON_COMMERCIAL)
- QT_NC_WIDGET_CREATE
- #endif
- if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled))
- q->inputContext()->setFocusWidget(q);
- if (destroyw) {
- DestroyWindow(destroyw);
- }
- if (q != qt_tablet_widget && QWidgetPrivate::mapper)
- qt_tablet_init();
- if (q->testAttribute(Qt::WA_DropSiteRegistered))
- registerDropSite(true);
- if (maybeTopData() && maybeTopData()->opacity != )
- q->setWindowOpacity(maybeTopData()->opacity/.);
- if (topLevel && (data.crect.width() == || data.crect.height() == )) {
- q->setAttribute(Qt::WA_OutsideWSRange, true);
- }
- if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
- Q_ASSERT(q->internalWinId());
- ShowWindow(q->internalWinId(), SW_SHOW);
- }
- }
这里调用了qt_reg_winclass()(在QApplication_win.cpp里定义),查看其代码就是RegisterWindows,把window窗口的消息处理设定为:QtWndProc。QObject的初始化没有什么新意,参看QApplication得初始化。
到目前为止的初始化分析,为下一步我们分析Windows消息传递,也就是QT的事件机制打下了基础。
QT分析之QPushButton的初始化的更多相关文章
- 2、QT分析之QPushButton的初始化
原文地址:http://blog.163.com/net_worm/blog/static/127702419201001003326522/ 在简单的QT程序的第二行,声明了一个QPushButto ...
- 1、QT分析之QApplication的初始化
原文地址:http://blog.163.com/net_worm/blog/static/1277024192010097430321/ 在开始分析之前交代一下,一是分析的QT在Window平台实现 ...
- QT分析之QApplication的初始化
原文地址:http://blog.163.com/net_worm/blog/static/1277024192010097430321/ 在开始分析之前交代一下,一是分析的QT在Window平台实现 ...
- 3、QT分析之消息事件机制
原文地址:http://blog.163.com/net_worm/blog/static/127702419201001432028526/ 上回我们分析到QPushButton的初始化,知道了Wi ...
- QT分析之消息事件机制
原文地址:http://blog.163.com/net_worm/blog/static/127702419201001432028526/ 上回我们分析到QPushButton的初始化,知道了Wi ...
- 10、QT分析之WebKit
该文章整理自 网易博客 http://blog.163.com/net_worm/blog/static/12770241920101831312381/ 转载请注明出处 WebKit是QT4新整合的 ...
- 5、QT分析之网络编程
原文地址:http://blog.163.com/net_worm/blog/static/127702419201002842553382/ 首先对Windows下的网络编程总结一下: 如果是服务器 ...
- QT分析之WebKit
该文章整理自 网易博客 http://blog.163.com/net_worm/blog/static/12770241920101831312381/ 转载请注明出处 WebKit是QT4新整合的 ...
- QT分析之网络编程
原文地址:http://blog.163.com/net_worm/blog/static/127702419201002842553382/ 首先对Windows下的网络编程总结一下: 如果是服务器 ...
随机推荐
- #!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby
#!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby # This script installs to ...
- VIM 键
输入 vimtutor命令,可以打开Linux使用手册(基本使用). ***. 插入键: A: 行尾插入 a: 字符后面插入 i: 字符前面插入 I: 行首插入 r:只替换一次字符 R:一直替换,直 ...
- MongoDB入门---文档查询之$type操作符&limit方法&skip方法&简单排序(sort)操作
上一篇文章呢,已经分享过了一部分查询操作了,这篇文章呢?就来继续分享哈.接下来呢我们直接看MongoDB中的$type操作符哈.它呢是基于BSON类型来检索集合中匹配的数据类型,并且返回结果,在Mon ...
- Java设计模式(19)——行为模式之责任链模式(chain of responsibilitiy)
一.概述 概念 UML简图 角色 抽象处理器:定义处理请求的接口 具体处理器:接收到请求后可以选择处理,也可以选择发给下家处理(持有下家的引用) 当然这里必须指出,实际中纯的责任链模式很难寻找,一般是 ...
- 从Github开源项目《云阅》所学到的知识
感谢开源,感谢大神,才让我们这些菜鸟成长! 附上云阅开源项目地址:点我吧. 1.轮播图的实现. 现在的APP基本都会实现这个功能吧,然后一直都找不到好的第三方库,能够满足各种需求.然而碰到了这个开源库 ...
- 成都Uber优步司机奖励政策(4月8日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- /proc/meminfo详解
cat /proc/meminfo 读出的内核信息进行解释, 下篇文章会简单对读出该信息的代码进行简单的分析. MemTotal: 507480 kB MemFree: ...
- Python全栈 项目(HTTPServer、PiP使用)
pip是Python官方推荐的包管理工具 属于python的一部分 pip的使用 pip的安装 sudo apt-get install pyt ...
- java实现遍历一个字符串的每一个字母(总结)
基础:牢记字符串操作的各种方法: String s = "aaaljlfeakdsflkjsadjaefdsafhaasdasd"; // 出现次数 int num = ...
- 【CSVRead】-jmeter
csv read 读取文件