开发背景:

1.直接用QSqlDatabase我觉得太麻烦了;

2.对于某些数据库,多个线程同时使用一个QSqlDatabase的时候会崩溃;

3.这段时间没什么干货放出来觉得浑身不舒服,就想写一个。

于是,我就封装了一下

只要简单的实例化,然后通过query()就可以拿到QSqlQuery的实例化对象。

还自带计时,一段时间不用可自动关闭,既保证效率也不占用无用资源。

注:需要C++11的支持

不多说,上代码:

JasonQt_Database.h

  1. #ifndef __JasonQt_Database_h__
  2. #define __JasonQt_Database_h__
  3. // C++ lib import
  4. #include <functional>
  5. // Qt lib import
  6. #include <QtCore>
  7. #include <QtSql>
  8. #define PropertyDeclare(Type, Name, setName, ...)                   \
  9. private:                                                        \
  10. Type m_ ## Name __VA_ARGS__;                                    \
  11. public:                                                         \
  12. inline const Type &Name(void) const { return m_ ## Name; }      \
  13. inline void setName(const Type &Name) { m_ ## Name = Name; }    \
  14. private:
  15. namespace JasonQt_Database
  16. {
  17. enum DatabaseModeEnum{ DatabaseNameMode, DatabaseHostMode };
  18. enum QueryMode { QueryAutoMode, QueryMultiMode, QuerySingleMode };
  19. class DatabaseSettings
  20. {
  21. private:
  22. PropertyDeclare(DatabaseModeEnum, databaseMode, setDatabaseMode)
  23. PropertyDeclare(QString, databaseType, setDatabaseType)
  24. PropertyDeclare(QString, connectionName, setConnectionName)
  25. // File mode
  26. PropertyDeclare(QString, nameModeName, setNameModeName)
  27. // Host mode
  28. PropertyDeclare(QString, hostModeHostName, setHostModeHostName)
  29. PropertyDeclare(QString, hostModeDatabaseName, setHostModeDatabaseName)
  30. PropertyDeclare(QString, hostModeUserName, setHostModeUserName)
  31. PropertyDeclare(QString, hostModePassword, setHostModePassword)
  32. private:
  33. DatabaseSettings(const DatabaseModeEnum &databastMode, const QString &databaseType, const QString &connectionName);
  34. public:
  35. DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &nameModeName);
  36. DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &hostModeHostName, const QString &hostModeDatabaseName, const QString &hostModeUserName, const QString &hostModePassword);
  37. };
  38. class ConnectSettings
  39. {
  40. private:
  41. PropertyDeclare(int, maxOpenTime, setMaxOpenTime)
  42. PropertyDeclare(QueryMode, queryMode, setQueryMode)
  43. PropertyDeclare(int, minWaitTime, setMinWaitTime)
  44. public:
  45. ConnectSettings(const int &maxOpenTime = 60 * 1000, const QueryMode &queryMode = QueryAutoMode, const int &minWaitTime = -1);
  46. };
  47. class Query
  48. {
  49. private:
  50. QSqlQuery *m_query;
  51. QMutex *m_mutex = NULL;
  52. public:
  53. Query(QSqlDatabase &dataBase, QMutex *mutex = NULL);
  54. Query(Query &&other);
  55. ~Query(void);
  56. inline QSqlQuery *operator->(void) { return m_query; }
  57. inline QSqlQuery *operator*(void) { return m_query; }
  58. QSqlQuery *takeQuery(void);
  59. QMutex *takeMutex(void);
  60. };
  61. class ConnectNode: public QObject
  62. {
  63. Q_OBJECT
  64. private:
  65. QSqlDatabase *m_database = NULL;
  66. QString m_connectionName;
  67. DatabaseSettings m_dataBaseSettings;
  68. ConnectSettings m_connectSettings;
  69. QTimer *m_autoClose = NULL;
  70. QMutex *m_mutex = NULL;
  71. public:
  72. ConnectNode(const DatabaseSettings &dataBaseSettings, const ConnectSettings &connectSettings);
  73. ~ConnectNode(void);
  74. public:
  75. Query query(void);
  76. public slots:
  77. bool addDataBase(void);
  78. void removeDataBase(void);
  79. bool open(void);
  80. void close(void);
  81. signals:
  82. void controlStartAutoClose(void);
  83. void controlStopAutoClose(void);
  84. };
  85. class Control
  86. {
  87. private:
  88. DatabaseSettings m_databaseSettings;
  89. ConnectSettings m_connectSettings;
  90. QMap<qint64, ConnectNode *> m_node;
  91. QMutex m_mutex;
  92. QTime *m_wait = NULL;
  93. public:
  94. Control(const DatabaseSettings &databaseSettings, const ConnectSettings &connectSettings = ConnectSettings());
  95. Control(const Control &) = delete;
  96. ~Control(void);
  97. public:
  98. void removeAll(void);
  99. Query query(void);
  100. private:
  101. void insert(const qint64 &key);
  102. };
  103. }
  104. #endif//__JasonQt_Database_h__

JasonQt_Database.cpp

  1. #include "JasonQt_Database.h"
  2. using namespace JasonQt_Database;
  3. // DatabaseSettings
  4. DatabaseSettings::DatabaseSettings(const DatabaseModeEnum &databastMode, const QString &databaseType, const QString &connectionName)
  5. {
  6. m_databaseMode = databastMode;
  7. m_databaseType = databaseType;
  8. m_connectionName = connectionName;
  9. }
  10. DatabaseSettings::DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &nameModeName):
  11. DatabaseSettings(DatabaseNameMode, databaseType, connectionName)
  12. {
  13. m_nameModeName = nameModeName;
  14. }
  15. DatabaseSettings::DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &hostModeHostName, const QString &hostModeDatabaseName, const QString &hostModeUserName, const QString &hostModePassword):
  16. DatabaseSettings(DatabaseHostMode, databaseType, connectionName)
  17. {
  18. m_hostModeHostName = hostModeHostName;
  19. m_hostModeDatabaseName = hostModeDatabaseName;
  20. m_hostModeUserName = hostModeUserName;
  21. m_hostModePassword = hostModePassword;
  22. }
  23. // ConnectSettings
  24. ConnectSettings::ConnectSettings(const int &maxOpenTime, const QueryMode &queryMode, const int &minWaitTime)
  25. {
  26. m_maxOpenTime = maxOpenTime;
  27. m_queryMode = queryMode;
  28. m_minWaitTime = minWaitTime;
  29. }
  30. // Query
  31. Query::Query(QSqlDatabase &dataBase, QMutex *mutex):
  32. m_query(new QSqlQuery(dataBase))
  33. {
  34. m_mutex = mutex;
  35. }
  36. Query::Query(Query &&other)
  37. {
  38. m_query = other.takeQuery();
  39. m_mutex = other.takeMutex();
  40. }
  41. Query::~Query(void)
  42. {
  43. if(m_query)
  44. {
  45. delete m_query;
  46. }
  47. if(m_mutex)
  48. {
  49. m_mutex->unlock();
  50. }
  51. }
  52. QSqlQuery *Query::takeQuery(void)
  53. {
  54. auto buf = m_query;
  55. m_query = NULL;
  56. return buf;
  57. }
  58. QMutex *Query::takeMutex(void)
  59. {
  60. auto buf = m_mutex;
  61. m_mutex = NULL;
  62. return buf;
  63. }
  64. // ConnectNode
  65. ConnectNode::ConnectNode(const DatabaseSettings &dataBaseSettings, const ConnectSettings &connectSettings):
  66. m_dataBaseSettings(dataBaseSettings),
  67. m_connectSettings(connectSettings)
  68. {
  69. m_connectionName = QString("%1(%2)").arg(m_dataBaseSettings.connectionName()).arg(QString::number(qint64(QThread::currentThread()), 16));
  70. m_mutex = new QMutex(QMutex::Recursive);
  71. if(m_connectSettings.maxOpenTime())
  72. {
  73. m_autoClose = new QTimer;
  74. m_autoClose->setSingleShot(true);
  75. m_autoClose->setInterval(m_connectSettings.maxOpenTime());
  76. m_autoClose->moveToThread(qApp->thread());
  77. m_autoClose->setParent(qApp);
  78. connect(m_autoClose, SIGNAL(timeout()), this, SLOT(close()), Qt::DirectConnection);
  79. connect(this, SIGNAL(controlStartAutoClose()), m_autoClose, SLOT(start()));
  80. connect(this, SIGNAL(controlStopAutoClose()), m_autoClose, SLOT(stop()));
  81. }
  82. this->addDataBase();
  83. }
  84. ConnectNode::~ConnectNode(void)
  85. {
  86. if(m_mutex){ m_mutex->lock(); }
  87. if(m_autoClose)
  88. {
  89. m_autoClose->deleteLater();
  90. }
  91. this->removeDataBase();
  92. if(m_mutex){ m_mutex->unlock(); }
  93. if(m_mutex){ delete m_mutex; }
  94. }
  95. Query ConnectNode::query(void)
  96. {
  97. if(!m_database)
  98. {
  99. this->addDataBase();
  100. }
  101. if(!m_database->isOpen())
  102. {
  103. m_database->open();
  104. }
  105. if(m_mutex){ m_mutex->lock(); }
  106. Query buf(*m_database, m_mutex);
  107. emit controlStartAutoClose();
  108. return buf;
  109. }
  110. bool ConnectNode::addDataBase(void)
  111. {
  112. if(m_mutex){ m_mutex->lock(); }
  113. if(m_database)
  114. {
  115. this->removeDataBase();
  116. }
  117. m_database = new QSqlDatabase(QSqlDatabase::addDatabase(m_dataBaseSettings.databaseType(), m_connectionName));
  118. switch(m_dataBaseSettings.databaseMode())
  119. {
  120. case DatabaseNameMode:
  121. {
  122. m_database->setDatabaseName(m_dataBaseSettings.nameModeName());
  123. break;
  124. }
  125. case DatabaseHostMode:
  126. {
  127. m_database->setHostName(m_dataBaseSettings.hostModeHostName());
  128. m_database->setDatabaseName(m_dataBaseSettings.hostModeDatabaseName());
  129. m_database->setUserName(m_dataBaseSettings.hostModeUserName());
  130. m_database->setPassword(m_dataBaseSettings.hostModePassword());
  131. break;
  132. }
  133. default:
  134. {
  135. if(m_mutex){ m_mutex->unlock(); }
  136. return false;
  137. }
  138. }
  139. const auto &&flag = this->open();
  140. if(m_mutex){ m_mutex->unlock(); }
  141. return flag;
  142. }
  143. void ConnectNode::removeDataBase(void)
  144. {
  145. if(m_mutex){ m_mutex->lock(); }
  146. delete m_database;
  147. m_database = NULL;
  148. QSqlDatabase::removeDatabase(m_connectionName);
  149. if(m_mutex){ m_mutex->unlock(); }
  150. }
  151. bool ConnectNode::open(void)
  152. {
  153. if(!m_database)
  154. {
  155. this->addDataBase();
  156. }
  157. if(m_mutex){ m_mutex->lock(); }
  158. emit controlStartAutoClose();
  159. const auto &&Flag = m_database->open();
  160. if(m_mutex){ m_mutex->unlock(); }
  161. return Flag;
  162. }
  163. void ConnectNode::close(void)
  164. {
  165. if(m_mutex)
  166. {
  167. if(m_mutex->tryLock())
  168. {
  169. m_mutex->unlock();
  170. emit controlStopAutoClose();
  171. m_database->close();
  172. }
  173. else
  174. {
  175. emit controlStartAutoClose();
  176. }
  177. }
  178. else
  179. {
  180. emit controlStopAutoClose();
  181. m_database->close();
  182. }
  183. }
  184. // Control
  185. Control::Control(const DatabaseSettings &databaseSettings, const ConnectSettings &connectSettings):
  186. m_databaseSettings(databaseSettings),
  187. m_connectSettings(connectSettings)
  188. {
  189. if(m_connectSettings.queryMode() == QueryAutoMode)
  190. {
  191. if(databaseSettings.databaseType() == "QMYSQL")
  192. {
  193. m_connectSettings.setQueryMode(QueryMultiMode);
  194. }
  195. else if(databaseSettings.databaseType() == "QODBC")
  196. {
  197. m_connectSettings.setQueryMode(QueryMultiMode);
  198. }
  199. else
  200. {
  201. m_connectSettings.setQueryMode(QuerySingleMode);
  202. }
  203. }
  204. if(m_connectSettings.queryMode() == QuerySingleMode)
  205. {
  206. this->insert(qint64(QThread::currentThread()));
  207. }
  208. if(m_connectSettings.minWaitTime() == -1)
  209. {
  210. if(databaseSettings.databaseType() == "QMYSQL")
  211. {
  212. m_connectSettings.setMinWaitTime(0);
  213. }
  214. else if(databaseSettings.databaseType() == "QODBC")
  215. {
  216. m_connectSettings.setMinWaitTime(0);
  217. }
  218. else
  219. {
  220. m_connectSettings.setMinWaitTime(5);
  221. m_wait = new QTime;
  222. m_wait->start();
  223. }
  224. }
  225. else
  226. {
  227. m_wait = new QTime;
  228. m_wait->start();
  229. }
  230. }
  231. Control::~Control(void)
  232. {
  233. for(auto &now: m_node)
  234. {
  235. now->deleteLater();
  236. }
  237. if(m_wait)
  238. {
  239. delete m_wait;
  240. }
  241. }
  242. void Control::removeAll(void)
  243. {
  244. m_mutex.lock();
  245. for(auto &Now: m_node)
  246. {
  247. Now->removeDataBase();
  248. }
  249. m_mutex.unlock();
  250. }
  251. Query Control::query(void)
  252. {
  253. if(m_wait)
  254. {
  255. const auto &&flag = m_connectSettings.minWaitTime() - m_wait->elapsed();
  256. m_wait->restart();
  257. if(flag > 0)
  258. {
  259. QThread::msleep(flag);
  260. }
  261. }
  262. if(m_connectSettings.queryMode() == QueryMultiMode)
  263. {
  264. m_mutex.lock();
  265. const auto &¤tThread = qint64(QThread::currentThread());
  266. const auto &&now = m_node.find(currentThread);
  267. if(now != m_node.end())
  268. {
  269. auto buf((*now)->query());
  270. m_mutex.unlock();
  271. return buf;
  272. }
  273. else
  274. {
  275. this->insert(qint64(QThread::currentThread()));
  276. m_mutex.unlock();
  277. return this->query();
  278. }
  279. }
  280. else
  281. {
  282. return (*m_node.begin())->query();
  283. }
  284. }
  285. void Control::insert(const qint64 &key)
  286. {
  287. m_node[key] = new ConnectNode(m_databaseSettings, m_connectSettings);
  288. }

使用:

  1. // Qt lib import
  2. #include <QCoreApplication>
  3. #include <QtConcurrent>
  4. #include <QSqlError>
  5. // JasonQt lib import
  6. #include "JasonQt/JasonQt_Database.h"
  7. int main(int argc, char *argv[])
  8. {
  9. QCoreApplication a(argc, argv);
  10. /*
  11. * 注:关于附加参数
  12. * 这是可以不写的,如果要写的话,可以参考这个:
  13. *
  14. * 单次打开数据库最大时间:也就是最大open的时间,对于某些数据库,长时间open但不使用,不仅会造成资源浪费还会意外断开。在设置了60 * 1000后,且60秒内未进行查询,就自动断开。
  15. * 多线程支持:简单的说就是高级点的数据库,比如 MySql 写 JasonQt_Database::QueryMultiMode ;低级的,比如 Sqlite ,写 JasonQt_Database::QuerySingleMode ,就可以了。
  16. * 最小等待时间:对于某些数据库,比如Sqlite,密集查询时可能出错,此时可以适当的提升两次查询之间的最小等待时间,比如10ms
  17. */
  18. // Sqlite的连接方式                    类型        连接名        Sqlite文件路径      单次打开数据库最大时间                多线程支持           最小等待时间
  19. JasonQt_Database::Control control({ "QSQLITE", "TestDB", "/Users/Jason/test.db" }, { 60 * 1000,        JasonQt_Database::QuerySingleMode, 10});
  20. // MySql的连接方式                      类型      连接名        IP        数据库    用户名        密码
  21. //  JasonQt_Database::Control control({ "QMYSQL", "TestDB", "localhost", "JasonDB", "root", "YourPassword" });
  22. // SqlServer的连接方式                  类型      连接名                                    数据库              数据库名   用户名         密码
  23. //  JasonQt_Database::Control control({ "QODBC", "TestDB", "Driver={SQL SERVER};server=iZ23kn6vmZ\\TEST;database=test;uid=sa;pwd=YourPassword;" });
  24. auto insert = [&]()
  25. {
  26. auto query(control.query()); // 这里的query在解引用( -> 或者 * )后返回的是 QSqlQuery ,直接用就可以了,不需要单独打开数据库或者其他的初始化
  27. query->prepare("insert into Test1 values(?)"); // 模拟插入操作
  28. query->addBindValue(rand() % 1280);
  29. if(!query->exec())
  30. {
  31. qDebug() << "Error" << __LINE__;
  32. }
  33. query->clear();
  34. query->prepare("insert into Test2 values(NULL, ?, ?)");
  35. query->addBindValue(rand() % 1280);
  36. QString buf;
  37. for(int now = 0; now < 50; now++)
  38. {
  39. buf.append('a' + (rand() % 26));
  40. }
  41. query->addBindValue(buf);
  42. if(!query->exec())
  43. {
  44. qDebug() << "Error" << __LINE__;
  45. }
  46. };
  47. auto delete_ = [&]()
  48. {
  49. auto query(control.query());
  50. query->prepare("delete from Test1 where data = ?");
  51. query->addBindValue(rand() % 1280);
  52. if(!query->exec())
  53. {
  54. qDebug() << "Error" << __LINE__;
  55. }
  56. query->clear();
  57. query->prepare("delete from Test2 where data1 = ?");
  58. query->addBindValue(rand() % 1280);
  59. if(!query->exec())
  60. {
  61. qDebug() << "Error" << __LINE__;
  62. }
  63. };
  64. auto update = [&]()
  65. {
  66. auto query(control.query());
  67. query->prepare("update Test1 set data = ? where data = ?");
  68. query->addBindValue(rand() % 1280);
  69. query->addBindValue(rand() % 1280);
  70. if(!query->exec())
  71. {
  72. qDebug() << "Error" << __LINE__;
  73. }
  74. query->clear();
  75. query->prepare("update Test2 set data1 = ?, data2 = ? where data1 = ?");
  76. query->addBindValue(rand() % 1280 + 1);
  77. QString buf;
  78. for(int now = 0; now < 50; now++)
  79. {
  80. buf.append('a' + (rand() % 26));
  81. }
  82. query->addBindValue(buf);
  83. query->addBindValue(rand() % 1280 + 1);
  84. if(!query->exec())
  85. {
  86. qDebug() << "Error" << __LINE__;
  87. }
  88. };
  89. auto select = [&]()
  90. {
  91. auto query(control.query());
  92. query->prepare("select * from Test1 where data = ?");
  93. query->addBindValue(rand() % 1280);
  94. if(!query->exec())
  95. {
  96. qDebug() << "Error" << __LINE__;
  97. }
  98. query->clear();
  99. query->prepare("select * from Test2 where data1 = ?");
  100. query->addBindValue(rand() % 1280);
  101. if(!query->exec())
  102. {
  103. qDebug() << "Error" << __LINE__;
  104. }
  105. };
  106. volatile int count = 0, last = 0;
  107. QTime time;
  108. time.start();
  109. QThreadPool::globalInstance()->setMaxThreadCount(10);
  110. for(int now = 0; now < 3; now++) // 开启3个线程测试
  111. {
  112. QtConcurrent::run([&]()
  113. {
  114. while(true)
  115. {
  116. count++;
  117. if(!(count % 1000))
  118. {
  119. const auto &&now = time.elapsed();
  120. qDebug() << now - last; // 打印每完成1000语句的时间
  121. last = now;
  122. }
  123. switch(rand() % 20)
  124. {
  125. case 0:  { insert(); break; }
  126. case 1:  { delete_(); break; }
  127. case 2:  { update(); break; }
  128. default: { select(); break; }
  129. }
  130. }
  131. QThread::msleep(10);
  132. });
  133. }
  134. return a.exec();
  135. }

我也写了一个示例工程,可以前往这里下载

http://download.csdn.net/detail/wsj18808050/8566497

http://blog.csdn.net/wsj18808050/article/details/44891715

QSqlDatabase的进一步封装(多线程支持+更加简单的操作)——同时支持MySQL, SQL Server和Sqlite的更多相关文章

  1. 功能齐全、效率一流的免费开源数据库导入导出工具(c#开发,支持SQL server、SQLite、ACCESS三种数据库),每月借此处理数据5G以上

    软件名:DataPie 功能:支持SQL server.SQLite.ACCESS数据库的导入.导出.存储过程调用,支持EXCEL2007.EXCEL2003.ACCESS2007. CSV文件导入数 ...

  2. 查询获取所有数据库名及数据库中表的集合、数据库连接字符串(类生成器,暂时支持mysql,sql server,后期有oracle再更新)

    现所在公司做项目开发时,经常会自己创建model类,网上的生成器也很多,完全满足自己的不太现实,所以感觉自己做一个更有底气,主要针对过程中的一些语句进行整理,也供其他人学习参考. 连接字符串: mys ...

  3. 最简单 无返回值 无参数 sql server存储过程

    CREATE proc Upadte_stateas update Table_1 set [state]=2 where id in (select id from Table_1 where st ...

  4. SQL Server 2016原生支持JSON

    转载原地址: http://www.cnblogs.com/lyhabc/p/4747694.html SQL Server 2005 开始支持 XML 数据类型,提供原生的 XML数据类型.XML ...

  5. 自动化安装SQL Server+SP就那么简单

    随着业务.企业规模的日益壮大,DB的数量也在不断增多,配置一台新增DB,从服务器的参数配置,磁盘阵列规划,DB安装部署,DB参数调优等等一列步骤下来,手工操作的效率变得越来越低,因为我负责的数据库近些 ...

  6. 动化安装SQL Server+SP就那么简单

    随着业务.企业规模的日益壮大,DB的数量也在不断增多,配置一台新增DB,从服务器的参数配置,磁盘阵列规划,DB安装部署,DB参数调优等等一列步骤下来,手工操作的效率变得越来越低,因为我负责的数据库近些 ...

  7. Microsoft SQL Server JDBC 驱动程序支持矩阵

    本页包含 Microsoft SQL Server JDBC 驱动程序的支持矩阵和支持生命周期策略. Microsoft JDBC 驱动程序支持生命周期矩阵和策略 Microsoft 支持生命周期 ( ...

  8. YxdJSON - Delphi 高性能 JSON 库(支持RTTI和序列化操作)

    源:YxdJSON - Delphi 高性能 JSON 库(支持RTTI和序列化操作) Delphi 高性能 JSON 库(支持RTTI和序列化操作) 支持平台: Windows, Android, ...

  9. SQL Server On Linux:基于实际项目案例,总结功能支持情况及相关问题解决方案,讲如何快速完成迁移

    上个月,有个朋友问我说Sql Sever向Mysql迁移有什么好的经验分享,他们公司客户明确提出不再提供Windows服务器,现在计划Mysql迁移.我说Mysql迁移成本太高了,不妨可以了解一下SQ ...

随机推荐

  1. laravel5.1框架简介及安装

    最近自己出来实习了,进入了一个新的环境,不仅是生活中,在代码和架构中也完全是一个新的架构.由于公司使用laravel5.1框架,所以最近学习了laravel5.1框架,好了接下来就简单介绍一下lara ...

  2. python学习day2(一)

    一.上周作业回顾 1.登陆接口: 思路流程: 1.登陆,三次锁定用户 2.用户信息文件,黑名单文件 3.检测黑名单,如输入账号在黑名单中存在,不允许登陆 4.用户密码判断 主要知识点:while,fo ...

  3. MATLAB中文论坛帖子整理(GUI)

    MATLAB中文论坛帖子整理(GUI) 目   录  1.GUI新手之——教你读懂GUI的M文件... 10 2.GUI程序中改变current directory引起的问题... 15 3.GUI中 ...

  4. SSH连接不上

    网上查了 大概说,一要安装开启ssh服务 然后关掉防火墙 service sshd restart service iptables stop 可是我用了之后还是连接不上, 很郁闷. 我尝试着ping ...

  5. Ajax学习教程在线阅读

      1.什么是AJAX ?(1) 2.什么是AJAX ?(2) 3.什么是AJAX ?(3) 4.什么是AJAX ?(4) 5.Ajax基础教程(1)-Ajax简介 1.1 Web应用简史 6.Aja ...

  6. Python导入模块的三种形式

    Python导入模块的3中方式: 1.import module_name 这样在程序里就可以通过module_name.metnod_name()的方式访问模块里的函数了 Example: > ...

  7. Qt部件学习之-烧鹅

    1,布局管理器 candidates

  8. usb键鼠标驱动分析

    一.鼠标 linux下的usb鼠标驱动在/drivers/hid/usbhid/usbmouse.c中实现 1.加载初始化过程 1.1模块入口 module_init(usb_mouse_init); ...

  9. Floodlight中 处理packetin消息的顺序(1)

    当Controller和SW建立连接之后,就能够处理来自SW的各种OF msg.当接收到 packetin 消息之后,会将其分发给各个监听了这个OFMessage的listeners,所以假设我们要设 ...

  10. jQuery模拟原生态App上拉刷新下拉加载

    jQuery模拟原生态App上拉刷新下拉加载效果代码,鼠标上拉时会显示loading字样,并且会模拟加载一条静态数据,支持触屏设备使用. <!doctype html> <html ...