zoukankan      html  css  js  c++  java
  • Qt中Ui名字空间以及setupUi函数的原理和实现

    用最新的QtCreator选择GUI的应用会产生含有如下文件的工程


     

    下面就简单分析下各部分的功能。

    .pro文件是供qmake使用的文件,不是本文的重点【不过其实也很简单的】,在此不多赘述。

    所以呢,还是从main开始,

    [cpp] view plain copy
     
    1. #include <QtGui/QApplication>  
    2. #include "mainwindow.h"  
    3. int main(int argc, char *argv[])  
    4. {  
    5. QApplication a(argc, argv);  
    6. MainWindow w;  
    7. w.show();  
    8. return a.exec();  
    9. }  

    很简单的样子

    QApplication a(argc, argv)和a.exec()可以理解为载入了Qt的架构,跑Qt的程序都要有此部,就不多说了。

    其中调用了个MainWindow并把它show了出来,具体分析下

    下面是mainwindow.h中的内容

    [cpp] view plain copy
     
    1. #ifndef MAINWINDOW_H  
    2. #define MAINWINDOW_H  
    3. #include <QtGui/QMainWindow>  
    4. namespace Ui  
    5. {  
    6. class MainWindow;  
    7. }  
    8. class MainWindow : public QMainWindow  
    9. {  
    10. Q_OBJECT  
    11. public:  
    12. MainWindow(QWidget *parent = 0);  
    13. ~MainWindow();  
    14. private:  
    15. Ui::MainWindow *ui;  
    16. };  
    17. #endif // MAINWINDOW_H  


    开始的namespace Ui可能让人有点摸不着头脑,这是因为qt把ui相关的类单独独立了出来,但类名相同,禁用namespace区别【但是就目前的使用来说,感觉这样做不怎么好,后面我会解释原因】

     

    声明namespace Ui是因为要调用Ui中的MainWindow,此MainWindow非彼MainWindow,后面涉及的*ui指针会调用它!

     

    关于Q_OBJECT就不说了,Qt中与signal和slot相关的类都要这么声明下。

     

    仔细看出了构造,析构就没啥了,只有那么个*ui!不过现在如果运行下,也只会生成个窗体而已。

     

    下面来看构造函数和析构函数,其实也就是mainwindow.c

    [cpp] view plain copy
     
    1. #include "mainwindow.h"  
    2. #include "ui_mainwindow.h"  
    3. MainWindow::MainWindow(QWidget *parent)  
    4. : QMainWindow(parent), ui(new Ui::MainWindow)  
    5. {  
    6. ui->setupUi(this);  
    7. }  
    8. MainWindow::~MainWindow()  
    9. {  
    10. delete ui;  
    11. }  

    构造时在堆上new了个Ui域中的MainWindow,并调用setupUi,析构仅仅是将其delete了,还是很简单!

     

    正如前面所述Qt很好的把ui分离了出去,前面图中的那个.ui文件就是让QtDesigner使的布局用文件!

     

    现在运行下,会生成ui_mainwindow.h,这个里面会涉及到真正布局用的函数,也就是那个Ui域中的MainWindow.下面具体看一下,

    [cpp] view plain copy
     
    1. #ifndef UI_MAINWINDOW_H  
    2. #define UI_MAINWINDOW_H  
    3. #include <QtCore/QVariant>  
    4. #include <QtGui/QAction>  
    5. #include <QtGui/QApplication>  
    6. #include <QtGui/QButtonGroup>  
    7. #include <QtGui/QHeaderView>  
    8. #include <QtGui/QMainWindow>  
    9. #include <QtGui/QMenuBar>  
    10. #include <QtGui/QStatusBar>  
    11. #include <QtGui/QToolBar>  
    12. #include <QtGui/QWidget>  
    13. QT_BEGIN_NAMESPACE  
    14. class Ui_MainWindow  
    15. {  
    16. public:  
    17. QMenuBar *menuBar;  
    18. QToolBar *mainToolBar;  
    19. QWidget *centralWidget;  
    20. QStatusBar *statusBar;  
    21. void setupUi(QMainWindow *MainWindow)  
    22. {  
    23. if (MainWindow->objectName().isEmpty())  
    24. MainWindow->setObjectName(QString::fromUtf8("MainWindow"));  
    25. MainWindow->resize(600, 400);  
    26. menuBar = new QMenuBar(MainWindow);  
    27. menuBar->setObjectName(QString::fromUtf8("menuBar"));  
    28. MainWindow->setMenuBar(menuBar);  
    29. mainToolBar = new QToolBar(MainWindow);  
    30. mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));  
    31. MainWindow->addToolBar(mainToolBar);  
    32. centralWidget = new QWidget(MainWindow);  
    33. centralWidget->setObjectName(QString::fromUtf8("centralWidget"));  
    34. MainWindow->setCentralWidget(centralWidget);  
    35. statusBar = new QStatusBar(MainWindow);  
    36. statusBar->setObjectName(QString::fromUtf8("statusBar"));  
    37. MainWindow->setStatusBar(statusBar);  
    38. retranslateUi(MainWindow);  
    39. QMetaObject::connectSlotsByName(MainWindow);  
    40. // setupUi  
    41. void retranslateUi(QMainWindow *MainWindow)  
    42. {  
    43. MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));  
    44. Q_UNUSED(MainWindow);  
    45. // retranslateUi  
    46. };  
    47. namespace Ui {  
    48. class MainWindow: public Ui_MainWindow {};  
    49. // namespace Ui  
    50. QT_END_NAMESPACE  
    51. #endif // UI_MAINWINDOW_H  

    吼吼,一下子多了不少,但其实还是很容易的。Ui_MainWindow声明了几个构件,具体我就不说了,因为也没啥可说的,它实现了setupUi函式,也就是前面那个MainWindow中调用的setupUi。

    但是要说明的是QMetaObject::connectSlotsByName函式会自动连接相应名 称的信号与槽,但要注意它连接的是传入的MainWindow及其子构件【不是子类】,注意前边ui->setupUi(this)中传入的 this,也就是非ui域中的MainWindow,所以如果要声明signal和slot时还是要在非ui域的MainWindow中来声明,然后通过 ui->xxx的形式来与GUI产生交互!如果我们在QtDesiner中拖放一个按钮然后点击go to slot就很容易印证这一点。

    retranslateUi则会为ui中的构件命名,具体也不在此多说。

    最后还是看看这段代码

    [cpp] view plain copy
     
    1. namespace Ui {  
    2.   
    3. class MainWindow: public Ui_MainWindow {};  
    4.   
    5. // namespace Ui  

    前面非Ui域中的MainWindow的*ui指向的是Ui域中的MainWindow,而Ui域中的MainWindow出了继承了Ui_MainWindow之外,内部一贫如洗!【有点绕口了】

    来张图片,再复习下

     

    最后要说明的有两点,个人感觉是QtCreator的BUG,

    其一是如果自己定制控件,并且想在内置的designer中载入,win下用mingw是不可行的,因为sdk套件中的 designer是用微软的编译器编译的,当然也有个比较方便的解决的办法,就是把qtcreator的源码下来,用现有的creator再编译一遍,然 后覆盖过去就行了。

    其二也是前面提到的,两个同名的MainWindow仅用Ui域来区分,虽然感觉这样做从设计上来说是很美的,但调试时却会有些许的问题,总之在creator中调试不能识别正确的域,具体见下图例


     

    像上面这张图this实际上应该指向的是Ui域中的MainWindow 【this其实指向的是MainWindow,它并不知是哪个域的MainWindow,再往下展开就错误的指向了Ui域】,但调试的数据区指向了Ui域 中的MainWindow,当然也不是没有解决的办法,你可以手工将Ui域中的MainWindow改下名就可以获得正确的调试信息了,只是这样做稍显麻 烦,而且再度运行qmake后可能还要重新修改。

    http://blog.csdn.net/desert187/article/details/39672371
  • 相关阅读:
    LeetCode 842. Split Array into Fibonacci Sequence
    LeetCode 1087. Brace Expansion
    LeetCode 1219. Path with Maximum Gold
    LeetCode 1079. Letter Tile Possibilities
    LeetCode 1049. Last Stone Weight II
    LeetCode 1046. Last Stone Weight
    LeetCode 1139. Largest 1-Bordered Square
    LeetCode 764. Largest Plus Sign
    LeetCode 1105. Filling Bookcase Shelves
    LeetCode 1027. Longest Arithmetic Sequence
  • 原文地址:https://www.cnblogs.com/findumars/p/5185114.html
Copyright © 2011-2022 走看看