原文地址:http://blog.163.com/net_worm/blog/static/127702419201001003326522/

在简单的QT程序的第二行,声明了一个QPushButton的对象。先简单看看其初始化过程。

QPushButton的类继承关系为:

  1. QPushButton public QAbstractButton pubic QWidget public QObject, public QPaintDevice

QPushButton的构造:

  1. QPushButton::QPushButton(const QString &text, QWidget *parent)
  2. : QAbstractButton(*new QPushButtonPrivate, parent)
  3. {
  4. Q_D(QPushButton); // 声明并获得QPushButtonPrivate函数指针d
  5. setText(text); // 设置按钮的名字
  6. d->init(); // 调用QPushButtonPrivate::init(),其实只是重新设定排布间隔
  7. }

新生成的QPushButtonPrivate对象传递给QAbstractButton之后,发生了什么事呢?

  1. QAbstractButton::QAbstractButton(QAbstractButtonPrivate &dd, QWidget *parent)
  2. : QWidget(dd, parent, )
  3. {
  4. Q_D(QAbstractButton); // 声明并获得QAbstractButtonPrivate函数指针d
  5. d->init(); // 调用QAbstractButtonPrivate::init()
  6. }

QAbstractButtonPrivate::init()做了什么呢?其实只是调用了QPushButton的几个设定函数。

继续看QWidget的初始化过程。

  1. QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
  2. : QObject(dd, ), QPaintDevice()
  3. {
  4. d_func()->init(parent, f);
  5. }

其中d_func()是宏定义Q_DECLARE_PRIVATE(QWidget)中定义的,获取QWidgetPrivate指针的函数。有点奇怪的是,这里怎么没有用Q_D宏定义,与之前的风格有点不同。

QWidgetPrivate::init()里做了什么动作呢?(关键语句用颜色标记)

  1. void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
  2. {
  3. Q_Q(QWidget);
  4. if (qApp->type() == QApplication::Tty)
  5. qFatal("QWidget: Cannot create a QWidget when no GUI is being used");
  6.  
  7. Q_ASSERT(uncreatedWidgets);
  8. uncreatedWidgets->insert(q);
  9.  
  10. QWidget *desktopWidget = ;
  11. if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
  12. desktopWidget = parentWidget;
  13. parentWidget = ;
  14. }
  15.  
  16. q->data = &data;
  17.  
  18. if (!q->parent()) {
  19. Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
  20. "Widgets must be created in the GUI thread.");
  21. }
  22.  
  23. data.fstrut_dirty = true;
  24.  
  25. data.winid = ;
  26. data.widget_attributes = ;
  27. data.window_flags = f;
  28. data.window_state = ;
  29. data.focus_policy = ;
  30. data.context_menu_policy = Qt::DefaultContextMenu;
  31. data.window_modality = Qt::NonModal;
  32.  
  33. data.sizehint_forced = ;
  34. data.is_closing = ;
  35. data.in_show = ;
  36. data.in_set_window_state = ;
  37. data.in_destructor = false;
  38.  
  39. // Widgets with Qt::MSWindowsOwnDC (typically QGLWidget) must have a window handle.
  40. if (f & Qt::MSWindowsOwnDC)
  41. q->setAttribute(Qt::WA_NativeWindow);
  42.  
  43. q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute()
  44. adjustQuitOnCloseAttribute();
  45.  
  46. q->setAttribute(Qt::WA_WState_Hidden);
  47.  
  48. //give potential windows a bigger "pre-initial" size; create_sys() will give them a new size later
  49. data.crect = parentWidget ? QRect(,,,) : QRect(,,,);
  50.  
  51. focus_next = focus_prev = q;
  52.  
  53. if ((f & Qt::WindowType_Mask) == Qt::Desktop)
  54. q->create(); // 调用了QWidget::create()
  55. else if (parentWidget)
  56. q->setParent(parentWidget, data.window_flags);
  57. else {
  58. adjustFlags(data.window_flags, q);
  59. resolveLayoutDirection();
  60. // opaque system background?
  61. const QBrush &background = q->palette().brush(QPalette::Window);
  62. setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque());
  63. }
  64. data.fnt = QFont(data.fnt, q);
  65.  
  66. q->setAttribute(Qt::WA_PendingMoveEvent);
  67. q->setAttribute(Qt::WA_PendingResizeEvent);
  68.  
  69. if (++QWidgetPrivate::instanceCounter > QWidgetPrivate::maxInstances)
  70. QWidgetPrivate::maxInstances = QWidgetPrivate::instanceCounter;
  71.  
  72. if (QApplicationPrivate::app_compile_version < 0x040200
  73. || QApplicationPrivate::testAttribute(Qt::AA_ImmediateWidgetCreation))
  74. q->create();
  75.  
  76. // 下面的三行,产生并发送了Create事件
  77. QEvent e(QEvent::Create);
  78. QApplication::sendEvent(q, &e);
  79. QApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
  80.  
  81. extraPaintEngine = ;
  82. }

看看QWidget::create()的实现:

  1. void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
  2. {
  3. Q_D(QWidget);
  4. if (testAttribute(Qt::WA_WState_Created) && window == && internalWinId())
  5. return;
  6.  
  7. if (d->data.in_destructor)
  8. return;
  9.  
  10. Qt::WindowType type = windowType();
  11. Qt::WindowFlags &flags = data->window_flags;
  12.  
  13. if ((type == Qt::Widget || type == Qt::SubWindow) && !parentWidget()) {
  14. type = Qt::Window;
  15. flags |= Qt::Window;
  16. }
  17.  
  18. if (QWidget *parent = parentWidget()) {
  19. if (type & Qt::Window) {
  20. if (!parent->testAttribute(Qt::WA_WState_Created))
  21. parent->createWinId();
  22. } else if (testAttribute(Qt::WA_NativeWindow) && !parent->internalWinId()
  23. && !testAttribute(Qt::WA_DontCreateNativeAncestors)) {
  24. // We're about to create a native child widget that doesn't have a native parent;
  25. // enforce a native handle for the parent unless the Qt::WA_DontCreateNativeAncestors
  26. // attribute is set.
  27. d->createWinId(window);
  28. // Nothing more to do.
  29. Q_ASSERT(testAttribute(Qt::WA_WState_Created));
  30. Q_ASSERT(internalWinId());
  31. return;
  32. }
  33. }
  34.  
  35. static int paintOnScreenEnv = -;
  36. if (paintOnScreenEnv == -)
  37. paintOnScreenEnv = qgetenv("QT_ONSCREEN_PAINT").toInt() > ? : ;
  38. if (paintOnScreenEnv == )
  39. setAttribute(Qt::WA_PaintOnScreen);
  40.  
  41. if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
  42. setAttribute(Qt::WA_NativeWindow);
  43.  
  44. #ifdef ALIEN_DEBUG
  45. qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
  46. << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
  47. #endif
  48.  
  49. // Unregister the dropsite (if already registered) before we
  50. // re-create the widget with a native window.
  51. if (testAttribute(Qt::WA_WState_Created) && !internalWinId() && testAttribute(Qt::WA_NativeWindow)
  52. && d->extra && d->extra->dropTarget) {
  53. d->registerDropSite(false);
  54. }
  55.  
  56. d->updateIsOpaque();
  57.  
  58. setAttribute(Qt::WA_WState_Created); // set created flag
  59. d->create_sys(window, initializeWindow, destroyOldWindow);
  60.  
  61. // a real toplevel window needs a backing store
  62. if (isWindow()) {
  63. delete d->topData()->backingStore;
  64. // QWidgetBackingStore will check this variable, hence it must be 0
  65. d->topData()->backingStore = ;
  66. if (hasBackingStoreSupport())
  67. d->topData()->backingStore = new QWidgetBackingStore(this);
  68. }
  69.  
  70. d->setModal_sys();
  71.  
  72. if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))
  73. setAttribute(Qt::WA_DropSiteRegistered, true);
  74.  
  75. // need to force the resting of the icon after changing parents
  76. if (testAttribute(Qt::WA_SetWindowIcon))
  77. d->setWindowIcon_sys(true);
  78. if (isWindow() && !d->topData()->iconText.isEmpty())
  79. d->setWindowIconText_helper(d->topData()->iconText);
  80. if (windowType() != Qt::Desktop) {
  81. d->updateSystemBackground();
  82.  
  83. if (isWindow() && !testAttribute(Qt::WA_SetWindowIcon))
  84. d->setWindowIcon_sys();
  85. }
  86. }

这里QWidgetPrivate::create_sys()定义在QWidget_win.cpp里。

  1. void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
  2. {
  3. Q_Q(QWidget);
  4. static int sw = -, sh = -;
  5.  
  6. Qt::WindowType type = q->windowType();
  7. Qt::WindowFlags flags = data.window_flags;
  8.  
  9. bool topLevel = (flags & Qt::Window);
  10. bool popup = (type == Qt::Popup);
  11. bool dialog = (type == Qt::Dialog
  12. || type == Qt::Sheet
  13. || (flags & Qt::MSWindowsFixedSizeDialogHint));
  14. bool desktop = (type == Qt::Desktop);
  15. bool tool = (type == Qt::Tool || type == Qt::Drawer);
  16.  
  17. HINSTANCE appinst = qWinAppInst();
  18. HWND parentw, destroyw = ;
  19. WId id;
  20.  
  21. QString windowClassName = qt_reg_winclass(q);
  22.  
  23. if (!window) // always initialize
  24. initializeWindow = true;
  25.  
  26. if (popup)
  27. flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
  28.  
  29. if (sw < ) { // get the (primary) screen size
  30. sw = GetSystemMetrics(SM_CXSCREEN);
  31. sh = GetSystemMetrics(SM_CYSCREEN);
  32. }
  33.  
  34. if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget
  35. popup = false; // force this flags off
  36. if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95)
  37. data.crect.setRect(GetSystemMetrics( /* SM_XVIRTUALSCREEN */), GetSystemMetrics( /* SM_YVIRTUALSCREEN */),
  38. GetSystemMetrics( /* SM_CXVIRTUALSCREEN */), GetSystemMetrics( /* SM_CYVIRTUALSCREEN */));
  39. else
  40. data.crect.setRect(, , GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
  41. }
  42.  
  43. parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : ;
  44.  
  45. #ifdef UNICODE
  46. QString title;
  47. const TCHAR *ttitle = ;
  48. #endif
  49. QByteArray title95;
  50. int style = WS_CHILD;
  51. int exsty = ;
  52.  
  53. if (window) {
  54. style = GetWindowLongA(window, GWL_STYLE);
  55. if (!style)
  56. qErrnoWarning("QWidget::create: GetWindowLong failed");
  57. topLevel = false; // #### needed for some IE plugins??
  58. } else if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) {
  59. style = WS_POPUP;
  60. } else if (topLevel && !desktop) {
  61. if (flags & Qt::FramelessWindowHint)
  62. style = WS_POPUP; // no border
  63. else if (flags & Qt::WindowTitleHint)
  64. style = WS_OVERLAPPED;
  65. else
  66. style = ;
  67. }
  68. if (!desktop) {
  69. // if (!testAttribute(Qt::WA_PaintUnclipped))
  70. // ### Commented out for now as it causes some problems, but
  71. // this should be correct anyway, so dig some more into this
  72. #ifndef Q_FLATTEN_EXPOSE
  73. style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
  74. #endif
  75. if (topLevel) {
  76. if ((type == Qt::Window || dialog || tool)) {
  77. if (!(flags & Qt::FramelessWindowHint)) {
  78. if (!(flags & Qt::MSWindowsFixedSizeDialogHint)) {
  79. style |= WS_THICKFRAME;
  80. if(!(flags &
  81. ( Qt::WindowSystemMenuHint
  82. | Qt::WindowTitleHint
  83. | Qt::WindowMinMaxButtonsHint
  84. | Qt::WindowCloseButtonHint
  85. | Qt::WindowContextHelpButtonHint)))
  86. style |= WS_POPUP;
  87. } else {
  88. style |= WS_POPUP | WS_DLGFRAME;
  89. }
  90. }
  91. if (flags & Qt::WindowTitleHint)
  92. style |= WS_CAPTION;
  93. if (flags & Qt::WindowSystemMenuHint)
  94. style |= WS_SYSMENU;
  95. if (flags & Qt::WindowMinimizeButtonHint)
  96. style |= WS_MINIMIZEBOX;
  97. if (shouldShowMaximizeButton())
  98. style |= WS_MAXIMIZEBOX;
  99. if (tool)
  100. exsty |= WS_EX_TOOLWINDOW;
  101. if (flags & Qt::WindowContextHelpButtonHint)
  102. exsty |= WS_EX_CONTEXTHELP;
  103. } else {
  104. exsty |= WS_EX_TOOLWINDOW;
  105. }
  106. }
  107. }
  108.  
  109. if (flags & Qt::WindowTitleHint) {
  110. QT_WA({
  111. title = q->isWindow() ? qAppName() : q->objectName();
  112. ttitle = (TCHAR*)title.utf16();
  113. } , {
  114. title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1();
  115. });
  116. }
  117.  
  118. // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
  119. // qapplication_win.cpp. We switch it off temporarily to avoid move
  120. // and resize events during creationt
  121. q->setAttribute(Qt::WA_WState_Created, false);
  122.  
  123. if (window) { // override the old window
  124. if (destroyOldWindow)
  125. destroyw = data.winid;
  126. id = window;
  127. setWinId(window);
  128. LONG res = SetWindowLongA(window, GWL_STYLE, style);
  129. if (!res)
  130. qErrnoWarning("QWidget::create: Failed to set window style");
  131. #ifdef _WIN64
  132. res = SetWindowLongPtrA( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc );
  133. #else
  134. res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc );
  135. #endif
  136. if (!res)
  137. qErrnoWarning("QWidget::create: Failed to set window procedure");
  138. } else if (desktop) { // desktop widget
  139. id = GetDesktopWindow();
  140. // QWidget *otherDesktop = QWidget::find(id); // is there another desktop?
  141. // if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
  142. // otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
  143. // d->setWinId(id); // make sure otherDesktop is
  144. // otherDesktop->d_func()->setWinId(id); // found first
  145. // } else {
  146. setWinId(id);
  147. // }
  148. } else if (topLevel) { // create top-level widget
  149. if (popup)
  150. parentw = ;
  151.  
  152. const bool wasMoved = q->testAttribute(Qt::WA_Moved);
  153. int x = wasMoved ? data.crect.left() : CW_USEDEFAULT;
  154. int y = wasMoved ? data.crect.top() : CW_USEDEFAULT;
  155. int w = CW_USEDEFAULT;
  156. int h = CW_USEDEFAULT;
  157.  
  158. // Adjust for framestrut when needed
  159. RECT rect = {,,,};
  160. bool isVisibleOnScreen = !q->testAttribute(Qt::WA_DontShowOnScreen);
  161. if (isVisibleOnScreen && AdjustWindowRectEx(&rect, style & ~WS_OVERLAPPED, FALSE, exsty)) {
  162. QTLWExtra *td = maybeTopData();
  163. if (wasMoved && (td && !td->posFromMove)) {
  164. x = data.crect.x() + rect.left;
  165. y = data.crect.y() + rect.top;
  166. }
  167.  
  168. if (q->testAttribute(Qt::WA_Resized)) {
  169. w = data.crect.width() + (rect.right - rect.left);
  170. h = data.crect.height() + (rect.bottom - rect.top);
  171. }
  172. }
  173. //update position & initial size of POPUP window
  174. if (isVisibleOnScreen && topLevel && initializeWindow && (style & WS_POPUP)) {
  175. if (!q->testAttribute(Qt::WA_Resized)) {
  176. w = sw/;
  177. h = *sh/;
  178. }
  179. if (!wasMoved) {
  180. x = sw/ - w/;
  181. y = sh/ - h/;
  182. }
  183. }
  184.  
  185. QT_WA({
  186. const TCHAR *cname = (TCHAR*)windowClassName.utf16();
  187. id = CreateWindowEx(exsty, cname, ttitle, style,
  188. x, y, w, h,
  189. parentw, , appinst, );
  190. } , {
  191. id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
  192. x, y, w, h,
  193. parentw, , appinst, );
  194. });
  195. if (!id)
  196. qErrnoWarning("QWidget::create: Failed to create window");
  197. setWinId(id);
  198. if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
  199. SetWindowPos(id, HWND_TOPMOST, , , , , SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  200. if (flags & Qt::WindowStaysOnBottomHint)
  201. qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
  202. } else if (flags & Qt::WindowStaysOnBottomHint)
  203. SetWindowPos(id, HWND_BOTTOM, , , , , SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  204. winUpdateIsOpaque();
  205. } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget
  206. QT_WA({
  207. const TCHAR *cname = (TCHAR*)windowClassName.utf16();
  208. id = CreateWindowEx(exsty, cname, ttitle, style,
  209. data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
  210. parentw, NULL, appinst, NULL);
  211. } , {
  212. id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style,
  213. data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
  214. parentw, NULL, appinst, NULL);
  215. });
  216. if (!id)
  217. qErrnoWarning("QWidget::create: Failed to create window");
  218. SetWindowPos(id, HWND_TOP, , , , , SWP_NOMOVE | SWP_NOSIZE);
  219. setWinId(id);
  220. }
  221.  
  222. if (desktop) {
  223. q->setAttribute(Qt::WA_WState_Visible);
  224. } else if (topLevel && !q->testAttribute(Qt::WA_DontShowOnScreen)) {
  225. RECT cr;
  226. GetClientRect(id, &cr);
  227. // one cannot trust cr.left and cr.top, use a correction POINT instead
  228. POINT pt;
  229. pt.x = ;
  230. pt.y = ;
  231. ClientToScreen(id, &pt);
  232.  
  233. if (data.crect.width() == || data.crect.height() == ) {
  234. data.crect = QRect(pt.x, pt.y, data.crect.width(), data.crect.height());
  235. } else {
  236. data.crect = QRect(QPoint(pt.x, pt.y),
  237. QPoint(pt.x + cr.right - , pt.y + cr.bottom - ));
  238. }
  239.  
  240. if (data.fstrut_dirty) {
  241. // be nice to activeqt
  242. updateFrameStrut();
  243. }
  244. }
  245.  
  246. q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
  247. hd = ; // no display context
  248.  
  249. if (window) { // got window from outside
  250. if (IsWindowVisible(window))
  251. q->setAttribute(Qt::WA_WState_Visible);
  252. else
  253. q->setAttribute(Qt::WA_WState_Visible, false);
  254. }
  255.  
  256. if (extra && !extra->mask.isEmpty())
  257. setMask_sys(extra->mask);
  258.  
  259. #if defined(QT_NON_COMMERCIAL)
  260. QT_NC_WIDGET_CREATE
  261. #endif
  262.  
  263. if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled))
  264. q->inputContext()->setFocusWidget(q);
  265.  
  266. if (destroyw) {
  267. DestroyWindow(destroyw);
  268. }
  269.  
  270. if (q != qt_tablet_widget && QWidgetPrivate::mapper)
  271. qt_tablet_init();
  272.  
  273. if (q->testAttribute(Qt::WA_DropSiteRegistered))
  274. registerDropSite(true);
  275.  
  276. if (maybeTopData() && maybeTopData()->opacity != )
  277. q->setWindowOpacity(maybeTopData()->opacity/.);
  278.  
  279. if (topLevel && (data.crect.width() == || data.crect.height() == )) {
  280. q->setAttribute(Qt::WA_OutsideWSRange, true);
  281. }
  282.  
  283. if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
  284. Q_ASSERT(q->internalWinId());
  285. ShowWindow(q->internalWinId(), SW_SHOW);
  286. }
  287. }

这里调用了qt_reg_winclass()(在QApplication_win.cpp里定义),查看其代码就是RegisterWindows,把window窗口的消息处理设定为:QtWndProc。QObject的初始化没有什么新意,参看QApplication得初始化。

到目前为止的初始化分析,为下一步我们分析Windows消息传递,也就是QT的事件机制打下了基础。

QT分析之QPushButton的初始化的更多相关文章

  1. 2、QT分析之QPushButton的初始化

    原文地址:http://blog.163.com/net_worm/blog/static/127702419201001003326522/ 在简单的QT程序的第二行,声明了一个QPushButto ...

  2. 1、QT分析之QApplication的初始化

    原文地址:http://blog.163.com/net_worm/blog/static/1277024192010097430321/ 在开始分析之前交代一下,一是分析的QT在Window平台实现 ...

  3. QT分析之QApplication的初始化

    原文地址:http://blog.163.com/net_worm/blog/static/1277024192010097430321/ 在开始分析之前交代一下,一是分析的QT在Window平台实现 ...

  4. 3、QT分析之消息事件机制

    原文地址:http://blog.163.com/net_worm/blog/static/127702419201001432028526/ 上回我们分析到QPushButton的初始化,知道了Wi ...

  5. QT分析之消息事件机制

    原文地址:http://blog.163.com/net_worm/blog/static/127702419201001432028526/ 上回我们分析到QPushButton的初始化,知道了Wi ...

  6. 10、QT分析之WebKit

    该文章整理自 网易博客 http://blog.163.com/net_worm/blog/static/12770241920101831312381/ 转载请注明出处 WebKit是QT4新整合的 ...

  7. 5、QT分析之网络编程

    原文地址:http://blog.163.com/net_worm/blog/static/127702419201002842553382/ 首先对Windows下的网络编程总结一下: 如果是服务器 ...

  8. QT分析之WebKit

    该文章整理自 网易博客 http://blog.163.com/net_worm/blog/static/12770241920101831312381/ 转载请注明出处 WebKit是QT4新整合的 ...

  9. QT分析之网络编程

    原文地址:http://blog.163.com/net_worm/blog/static/127702419201002842553382/ 首先对Windows下的网络编程总结一下: 如果是服务器 ...

随机推荐

  1. #!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby

    #!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby # This script installs to ...

  2. VIM 键

    输入 vimtutor命令,可以打开Linux使用手册(基本使用). ***. 插入键: A: 行尾插入 a: 字符后面插入 i: 字符前面插入 I: 行首插入 r:只替换一次字符  R:一直替换,直 ...

  3. MongoDB入门---文档查询之$type操作符&limit方法&skip方法&简单排序(sort)操作

    上一篇文章呢,已经分享过了一部分查询操作了,这篇文章呢?就来继续分享哈.接下来呢我们直接看MongoDB中的$type操作符哈.它呢是基于BSON类型来检索集合中匹配的数据类型,并且返回结果,在Mon ...

  4. Java设计模式(19)——行为模式之责任链模式(chain of responsibilitiy)

    一.概述 概念 UML简图 角色 抽象处理器:定义处理请求的接口 具体处理器:接收到请求后可以选择处理,也可以选择发给下家处理(持有下家的引用) 当然这里必须指出,实际中纯的责任链模式很难寻找,一般是 ...

  5. 从Github开源项目《云阅》所学到的知识

    感谢开源,感谢大神,才让我们这些菜鸟成长! 附上云阅开源项目地址:点我吧. 1.轮播图的实现. 现在的APP基本都会实现这个功能吧,然后一直都找不到好的第三方库,能够满足各种需求.然而碰到了这个开源库 ...

  6. 成都Uber优步司机奖励政策(4月8日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. /proc/meminfo详解

    cat /proc/meminfo   读出的内核信息进行解释, 下篇文章会简单对读出该信息的代码进行简单的分析. MemTotal:       507480 kB MemFree:         ...

  8. Python全栈 项目(HTTPServer、PiP使用)

    pip是Python官方推荐的包管理工具   属于python的一部分            pip的使用    pip的安装             sudo apt-get install pyt ...

  9. java实现遍历一个字符串的每一个字母(总结)

    基础:牢记字符串操作的各种方法: ​​​ ​ String s = "aaaljlfeakdsflkjsadjaefdsafhaasdasd"; // 出现次数 int num = ...

  10. 【CSVRead】-jmeter

    csv     read 读取文件