不带参数启动的界面,会自动弹出连接对话框,输入正确的参数连接数据库
带参数启动,会根据参数自动连接多台服务器,双击服务器中的数据库表,右边会显示表格内容,在表格内容区点鼠标右键,可以对数据库表进行添加、删除等操作;右键点击数据库,选择【showMetaData】,会在右边显示数据表的结构(名称、类型、长度等信息),可以在下面的【SQL Query】中直接输入sql语句,直接对数据库进行查询、添加、删除、修改等操作,实例同时连接两台不同IP地址的服务器
带参数启动参考如下命令,sqlbrowser是实例程序名称,后面跟两个SQL连接字符串(字符串之间有一个空格),QODBC是驱动名称,hotelDSN是ODBC中创建的数据源
sqlbrowser QODBC://user:[email protected]/hotelDSN QODBC://user:[email protected]/aidel
在ODBC中创建的数据源:在【运行】中打开odbcad32,界面如下
大部份的代码都有注释,直接上代码
#include
#include
#include
#include "browser.h"
void addConnectionsFromCommandline(const QStringList &args, Browser *browser)
{
for (int i = 1; i < args.count(); ++i) {
/* TolerantMode:QUrl将尝试纠正一些常见的网址错误,这种模式对于解析来自不严格符合标准的来源的网址很有用
* */
QUrl url(args.at(i), QUrl::TolerantMode);
/* 如果URL非空且有效,则返回真;否则返回false
* */
if (!url.isValid()) {
/* qPrintable(args.at(i))以常量字符指针形式返回字符串,这相当于str.toLocal8Bit().constData()。
*/
qWarning("Invalid URL: %s", qPrintable(args.at(i)));
continue;
}
/* ftp地址实例 ftp://tray:[email protected]/pub/somethine:2021
* ftp 为scheme,以小写形式返回
* tray 为user
* 5uQQo_f 为password
* ftp.example.com 为host
* 2021 为port
* tray:5uQQo_f 为user info
* tray:[email protected]:2021 为authority
* /pub/somethine/ 为path
*
* https://doc.qt.io/qt-5/qurl.html#isValid
* isValid 为fragment,fragment(片断)由“#”后跟一串字符表示
*
* 对于邮件地址 mailto:[email protected]
* [email protected]为path
*
* 调用isRelative()将返回该网址是否是相对的,相对URL没有scheme。例如:
* qDebug() << QUrl("main.qml").isRelative(); // true: no scheme
qDebug() << QUrl("qml/main.qml").isRelative(); // true: no scheme
qDebug() << QUrl("file:main.qml").isRelative(); // false: has "file" scheme
qDebug() << QUrl("file:qml/main.qml").isRelative(); // false: has "file" scheme
*
* QUrl url("http://qt-project.org/support/file.html");
// url.adjusted(RemoveFilename) == "http://qt-project.org/support/"
// url.fileName() == "file.html"
* url.path().mid(1)返回url中path除第1个字符外的所有字符
* 原型 QString QString::mid(int position, int n = -1) const
* 从指定的位置索引position开始,返回一个包含n个字符的字符串
* 如果n为-1(默认值),该函数返回指定位置position后的所有可用字符
* QString x = "Nine pineapples";
QString y = x.mid(5, 4); // y == "pine"
QString z = x.mid(5); // z == "pineapples"
* url.port(-1))返回网址的端口,如果端口未指定或者-1,则返回默认端口
* */
QSqlError err = browser->addConnection(url.scheme().toUpper(), url.path().mid(1), url.host(),
url.userName(), url.password(), url.port(-1));
if (err.type() != QSqlError::NoError)
qDebug() << "Unable to open connection:" << err;
}
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow mainWin;
mainWin.setWindowTitle(QObject::tr("Qt SQL Browser"));
Browser browser(&mainWin);
mainWin.setCentralWidget(&browser);
QMenu *fileMenu = mainWin.menuBar()->addMenu(QObject::tr("&File"));
fileMenu->addAction(QObject::tr("Add &Connection..."),
[&]() {
browser.addConnection(); });
fileMenu->addSeparator();
fileMenu->addAction(QObject::tr("&Quit"), []() {
qApp->quit(); });
QMenu *helpMenu = mainWin.menuBar()->addMenu(QObject::tr("&Help"));
helpMenu->addAction(QObject::tr("About"), [&]() {
browser.about(); });
helpMenu->addAction(QObject::tr("About Qt"), []() {
qApp->aboutQt(); });
QObject::connect(&browser, &Browser::statusMessage, [&mainWin](const QString &text) {
mainWin.statusBar()->showMessage(text);});
//sqlbrowser QODBC://user:[email protected]/hotelDSN QODBC://user:[email protected]/aidel
addConnectionsFromCommandline(app.arguments(), &browser);
mainWin.show();
// QSqlDatabase::connectionNames()返回包含所有连接名称的列表
if (QSqlDatabase::connectionNames().isEmpty())
/* 调用browser对象无参的信号或槽名addConnection(),如果可以调用该成员,则返回true。如果没有这样的成员或参数不匹配,则返回false
* 如果类型是Qt::DirectConnection,将立即调用addConnection()
* 如果类型是Qt::QueuedConnection,那么一旦应用程序进入主事件循环,就会发送QEvent,并调用addConnection()
* 如果类型是Qt::BlockingQueuedConnection,则调用方法的方式与调用Qt::QueuedConnection的方式相同,只是当前线程将一直阻塞,直到事件被传递。
* 使用这种连接类型在同一线程中的对象之间进行通信将导致死锁
* 如果类型是Qt::AutoConnection,那么如果obj与调用者生活在同一个线程中,则同步调用成员;否则,它将异步调用该成员
* 原型:
* bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type,
* QGenericReturnArgument ret,
* QGenericArgument val0 = QGenericArgument(nullptr),
* QGenericArgument val1 = QGenericArgument(),
* QGenericArgument val2 = QGenericArgument(),
* QGenericArgument val3 = QGenericArgument(),
* QGenericArgument val4 = QGenericArgument(),
* QGenericArgument val5 = QGenericArgument(),
* QGenericArgument val6 = QGenericArgument(),
* QGenericArgument val7 = QGenericArgument(),
* QGenericArgument val8 = QGenericArgument(),
* QGenericArgument val9 = QGenericArgument())
* 成员函数调用的返回值放在ret中。
* 如果调用是异步的,则无法计算返回值。您最多可以向成员函数传递十个参数(val0、val1、val2、val3、val4、val5、val6、val7、val8和val9)
* QGenericArgument和QGenericReturnArgument是内部助手类。因为可以动态调用信号和槽,所以必须使用Q_ARG()和Q_RETURN_ARG()宏来封装参数。
* Q_ARG()接受一个类型名和该类型的常量引用;Q_RETURN_ARG()采用一个类型名和一个非常数引用
*
* 要同步调用某个任意对象上的compute(QString,int,double)槽,如下:
QString retVal;
QMetaObject::invokeMethod(obj, "compute", Qt::DirectConnection,
Q_RETURN_ARG(QString, retVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));
* */
QMetaObject::invokeMethod(&browser, "addConnection", Qt::QueuedConnection);
return app.exec();
}
#ifndef BROWSER_H
#define BROWSER_H
#include
#include
#include "ui_browserwidget.h"
class ConnectionWidget;
QT_FORWARD_DECLARE_CLASS(QTableView)
QT_FORWARD_DECLARE_CLASS(QPushButton)
QT_FORWARD_DECLARE_CLASS(QTextEdit)
QT_FORWARD_DECLARE_CLASS(QSqlError)
class Browser: public QWidget, private Ui::Browser
{
Q_OBJECT
public:
Browser(QWidget *parent = nullptr);
virtual ~Browser();
QSqlError addConnection(const QString &driver, const QString &dbName, const QString &host,
const QString &user, const QString &passwd, int port = -1);
void insertRow();
void deleteRow();
void updateActions();
public slots:
void exec();
void showTable(const QString &table);
void showMetaData(const QString &table);
void addConnection();
void currentChanged() {
updateActions(); }
void about();
void on_insertRowAction_triggered()
{
insertRow(); }
void on_deleteRowAction_triggered()
{
deleteRow(); }
void on_fieldStrategyAction_triggered();
void on_rowStrategyAction_triggered();
void on_manualStrategyAction_triggered();
void on_submitAction_triggered();
void on_revertAction_triggered();
void on_selectAction_triggered();
void on_connectionWidget_tableActivated(const QString &table)
{
showTable(<