目录
背景
工作一年零1个月了(加上实习),靠着工作中学到的东西,花了周末2天时间,做了一个小系统,这个小系统中有2个进程,一个是用于数据展示的进程。
另外一个进程是用来调取Qt插件,这个插件可能连接了Mysql,也可能连接了SQLSever等数据库,调用插件后,读取插件返回的数据库的数据;
展示软件通过设置一个描述字符串,这个字符串可以是检索Mysql的语句!
把展示软件的描述字符串内容和这个字符串的ID,通过共享内存的方式给插件调用端,插件调用端是一个中转,把数据给对应的插件。获得了数据后!
再使用共享内存的方式给数据展示进程!
实践环境
语言有C++,和SQL,
其中C++使用Qt框架(Qt Creator 5.7作为IDE,编译器为MinGw)
数据库使用的是Mysql数据库;
逻辑结构图
所以本次实践涉及3个程序,一个是数据展示进程,一个是服务进程(提供展示数据),一个是插件
运行截图
话不多说,先看动态演示!
添加很多展示数据后!
拖动动态数据:
设置描述符后:
上面设置的描述符为:
select value from sourcenetload.datasample where idval=6
以上的数据都是从数据库中读取的!
这里数据改变的原因是,我在Mysql中写了一个存储过程,这个存储过程能修改表中所有数据,
用写了一个事件,每秒进行调用,下面将会详细给出!
服务进程中转站截图:
插件端
数据展示进程源码
程序结构如下:
dynamicdata.h
#ifndef DYNAMICDATA_H
#define DYNAMICDATA_H
#include <QGraphicsItem>
class DynamicData : public QGraphicsItem
{
public:
DynamicData();
~DynamicData();
QRectF boundingRect()const Q_DECL_OVERRIDE;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) Q_DECL_OVERRIDE;
int getId();
void setId(const int &id);
QString getText();
void setText(const QString &str);
QString getDescrib();
void setDescrib(const QString &str);
private:
int m_id;
QString m_text;
QString m_describ;
};
#endif // DYNAMICDATA_H
mygraphicsscene.h
#ifndef MYGRAPHICSSCENE_H
#define MYGRAPHICSSCENE_H
#include <QObject>
#include <QPointF>
#include <QGraphicsView>
class MyGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
MyGraphicsScene(QWidget *parent = 0);
~MyGraphicsScene();
void createDynamicData(const QPointF &pt, const int &id);
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
void dropEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
void dragMoveEvent(QGraphicsSceneDragDropEvent *event) Q_DECL_OVERRIDE;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
};
#endif // MYGRAPHICSSCENE_H
mygraphicsview.h
#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H
#include <QObject>
#include <QGraphicsView>
class MyGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
MyGraphicsView(QWidget *parent = 0);
~MyGraphicsView();
protected:
void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE;
void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
private:
int m_count;
};
#endif // MYGRAPHICSVIEW_H
mylistwidget.h
#ifndef MYLISTWIDGET_H
#define MYLISTWIDGET_H
#include <QObject>
#include <QListWidget>
class MyListWidget : public QListWidget
{
Q_OBJECT
public:
MyListWidget(QWidget *parent = 0);
~MyListWidget();
protected:
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
private:
QPoint m_dragPosition;
QListWidgetItem *m_dragItem;
};
#endif // MYLISTWIDGET_H
setdatadialog.h
#ifndef SETDATADIALOG_H
#define SETDATADIALOG_H
#include <QDialog>
namespace Ui {
class setDataDialog;
}
class setDataDialog : public QDialog
{
Q_OBJECT
public:
explicit setDataDialog(QWidget *parent = 0, const int &id = -1, const QString &str = "NULL");
~setDataDialog();
QString getDescrib();
protected slots:
void okBtnClicked();
void cancelBtnClicked();
private:
Ui::setDataDialog *ui;
};
#endif // SETDATADIALOG_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QSharedMemory;
class QTimer;
QT_END_NAMESPACE
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected slots:
void shareMemoryTimeout();
private:
Ui::Widget *ui;
QSharedMemory *m_sharedMemory;
QSharedMemory *m_sharedMemory2;
QTimer *m_timer;
};
#endif // WIDGET_H
dynamicdata.cpp
#include "dynamicdata.h"
#include <QPainter>
#include <QDebug>
#include <QBrush>
#include <QMessageBox>
DynamicData::DynamicData()
{
m_text = "-123456789";
m_describ = "NULL";
}
DynamicData::~DynamicData()
{
}
QRectF DynamicData::boundingRect() const
{
qreal penWidth = 1;
return QRectF(0 - penWidth / 2, 0 - penWidth / 2, 80 + penWidth, 10 + penWidth);
}
void DynamicData::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
painter->setBrush(Qt::red);
painter->drawText(0, 0, 80, 10, Qt::AlignCenter, m_text);
}
int DynamicData::getId()
{
return m_id;
}
void DynamicData::setId(const int &id)
{
m_id = id;
}
QString DynamicData::getText()
{
return m_text;
}
void DynamicData::setText(const QString &str)
{
m_text = str;
update();
}
QString DynamicData::getDescrib()
{
return m_describ;
}
void DynamicData::setDescrib(const QString &str)
{
m_describ = str;
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
mygraphicsscene.cpp
#include "mygraphicsscene.h"
#include "dynamicdata.h"
#include "setdatadialog.h"
#include <QDebug>
#include <QMimeData>
#include <QPen>
#include <QMessageBox>
#include <QGraphicsSceneDragDropEvent>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QTransform>
#include <QDragMoveEvent>
MyGraphicsScene::MyGraphicsScene(QWidget *parent) : QGraphicsScene(parent)
{
}
MyGraphicsScene::~MyGraphicsScene()
{
}
void MyGraphicsScene::createDynamicData(const QPointF &pt, const int &id)
{
DynamicData *item = new DynamicData;
item->setPos(pt);
item->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
item->setId(id);
addItem(item);
}
void MyGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
if(event->mimeData()->hasFormat("text/plain")){
event->acceptProposedAction();
}
}
void MyGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
QGraphicsScene::dropEvent(event);
}
void MyGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
event->accept();
}
void MyGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
QTransform deviceTransform;
DynamicData* item = static_cast<DynamicData*>(itemAt(event->scenePos(), deviceTransform));
if(item != NULL){
setDataDialog *msetDataDialog = new setDataDialog(NULL, item->getId(), item->getDescrib());
if(msetDataDialog->exec() == QDialog::Accepted){
item->setDescrib(msetDataDialog->getDescrib());
}
delete msetDataDialog;
}
QGraphicsScene::mousePressEvent(event);
}
mygraphicsview.cpp
#include "mygraphicsview.h"
#include "mygraphicsscene.h"
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#include <QDebug>
MyGraphicsView::MyGraphicsView(QWidget *parent) : QGraphicsView(parent)
{
MyGraphicsScene *scene = new MyGraphicsScene;
scene->setSceneRect(-1000, -1000, 1000, 1000);
setScene(scene);
m_count = 0;
}
MyGraphicsView::~MyGraphicsView()
{
}
void MyGraphicsView::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasFormat("text/plain")){
event->acceptProposedAction();
}
QGraphicsView::dragEnterEvent(event);
}
void MyGraphicsView::dropEvent(QDropEvent *event)
{
if(event->mimeData()->hasFormat("text/plain")){
MyGraphicsScene *scene = (MyGraphicsScene*)this->scene();
scene->createDynamicData(mapToScene(event->pos()), m_count++);
event->acceptProposedAction();
}
QGraphicsView::dropEvent(event);
}
mylistwidget.cpp
#include "mylistwidget.h"
#include <QMouseEvent>
#include <QListWidgetItem>
#include <QDrag>
#include <QMimeData>
#include <QPainter>
#include <QApplication>
#include <QPixmap>
MyListWidget::MyListWidget(QWidget *parent) : QListWidget(parent)
{
}
MyListWidget::~MyListWidget()
{
}
void MyListWidget::mouseMoveEvent(QMouseEvent *event)
{
if(!(event->buttons() & Qt::LeftButton))
return;
if((event->pos() - m_dragPosition).manhattanLength() < QApplication::startDragDistance())
return;
if(!m_dragItem)
return;
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
mimeData->setText(currentItem()->text());
drag->setMimeData(mimeData);
if(mimeData->text() == "动态数据"){
QPixmap dragImg(100, 50);
QPainter painter(&dragImg);
painter.setBrush(QBrush(Qt::red));
painter.drawRect(0, 0, 100, 50);
drag->setPixmap(dragImg);
}
drag->exec(Qt::CopyAction|Qt::MoveAction);
}
void MyListWidget::mousePressEvent(QMouseEvent *event)
{
m_dragPosition=event->pos();
m_dragItem=this->itemAt(event->pos());
QListWidget::mousePressEvent(event);
}
setdatadialog.cpp
#include "setdatadialog.h"
#include "ui_setdatadialog.h"
setDataDialog::setDataDialog(QWidget *parent, const int &id, const QString &str) :
QDialog(parent),
ui(new Ui::setDataDialog)
{
ui->setupUi(this);
this->setWindowTitle("CSDN IT1995设置描述符号");
ui->idLineEdit->setText(QString::number(id));
ui->idLineEdit->setEnabled(false);
ui->describLineEdit->setText(str);
connect(ui->okPushButton, SIGNAL(clicked(bool)), this, SLOT(okBtnClicked()));
connect(ui->cancelPushButton, SIGNAL(clicked(bool)), this, SLOT(cancelBtnClicked()));
}
setDataDialog::~setDataDialog()
{
delete ui;
}
QString setDataDialog::getDescrib()
{
return ui->describLineEdit->text();
}
void setDataDialog::okBtnClicked()
{
accept();
}
void setDataDialog::cancelBtnClicked()
{
reject();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "dynamicdata.h"
#include <QSharedMemory>
#include <QGraphicsItem>
#include <QTImer>
#include <QDebug>
#include <QDataStream>
#include <QBuffer>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("CSDN IT1995");
ui->listWidget->insertItem(0, "动态数据");
m_sharedMemory = new QSharedMemory("CSDN IT1995");
m_sharedMemory2 = new QSharedMemory(this);
m_sharedMemory2->setKey("5991TI NDSC");
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(shareMemoryTimeout()));
m_timer->start(500);
}
Widget::~Widget()
{
delete ui;
}
//这里我偷懒了,应该要抽2-3个函数出来的。
void Widget::shareMemoryTimeout()
{
//偷懒了
QList<QGraphicsItem *> list = ui->graphicsView->items();
if(list.isEmpty())
return;
if(m_sharedMemory->isAttached()){
if(!m_sharedMemory->detach()){
return;
}
}
QString str;
foreach(QGraphicsItem *item, list){
int id = static_cast<DynamicData*>(item)->getId();
QString describ = static_cast<DynamicData*>(item)->getDescrib();
str.append(QString::number(id) + ";" + describ + "#");
}
str = str.left(str.length() - 1);
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QDataStream out(&buffer);
out << str;
if(!m_sharedMemory->create(buffer.size())){
qDebug() << "create failed!";
return;
}
m_sharedMemory->lock();
char *to = static_cast<char*>(m_sharedMemory->data());
memcpy(to, str.toStdString().c_str(), (int)buffer.size());
m_sharedMemory->unlock();
//获取数据 偷懒了
if(!m_sharedMemory2->attach()){
return;
}
QBuffer buffer2;
m_sharedMemory2->lock();
buffer2.setData((char*)m_sharedMemory2->constData(), m_sharedMemory2->size());
buffer2.open(QBuffer::ReadOnly);
QString data2 = buffer2.readAll();
m_sharedMemory2->unlock();
m_sharedMemory2->detach();
//设置item的值 偷懒了
QStringList listData = data2.split("#");
listData.removeLast();
qDebug() << listData;
for(int i = 0; i < listData.size(); i++){
QStringList idList = listData[i].split(";");
foreach(QGraphicsItem *item, list){
int id = static_cast<DynamicData*>(item)->getId();
if(id == idList[0].toInt()){
static_cast<DynamicData*>(item)->setText(idList[1]);
ui->graphicsView->update();
}
}
}
}
setdatadialog.ui
widget.ui
服务进程(插件调用)源码
程序结构如下:
appinterface.h
#ifndef APPINTERFACE_H
#define APPINTERFACE_H
#include <QObject>
class AppInterface{
public:
virtual ~AppInterface(){}
virtual QString name() = 0;
virtual QWidget *widget() = 0;
virtual void setSQLData(const QString &cmdData){ Q_UNUSED(cmdData); }
virtual QString getSQLData(){ return""; }
QString libDir(){
return m_libDir.isEmpty() ? "./" : m_libDir;
}
void setLibDir(const QString &libDir){
m_libDir = libDir;
}
private:
QString m_libDir;
};
QT_BEGIN_NAMESPACE
#define Interface_iid "com.IT1995.Interface"
Q_DECLARE_INTERFACE(AppInterface, Interface_iid)
QT_END_NAMESPACE
#endif // APPINTERFACE_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QMap>
namespace Ui {
class Widget;
}
QT_BEGIN_NAMESPACE
class QSharedMemory;
QT_END_NAMESPACE
class AppInterface;
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
void readPlugin();
~Widget();
protected:
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
void setMap(const QString &data);
private:
Ui::Widget *ui;
QSharedMemory *m_sharedMemory;
QSharedMemory *m_sharedMemory2;
int m_timerId;
int m_timerId2;
QMap<int, QString> m_map;
QList<AppInterface*> m_widgetList;
QString m_sendMsg;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "appinterface.h"
#include <QDir>
#include <QPluginLoader>
#include <QMessageBox>
#include <QSharedMemory>
#include <QDebug>
#include <QDataStream>
#include <QBuffer>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("CSDN IT1995中转站");
m_sharedMemory = new QSharedMemory(this);
m_sharedMemory2 = new QSharedMemory(this);
m_sharedMemory->setKey("CSDN IT1995");
m_sharedMemory2->setKey("5991TI NDSC");
m_timerId = startTimer(500);
m_timerId2 = startTimer(500);
m_sendMsg = "";
readPlugin();
}
void Widget::readPlugin()
{
QDir pluginsDir(qApp->applicationDirPath() + "/plugin");
foreach(QString filename, pluginsDir.entryList(QDir::Files)){
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(filename));
QObject *plugin = pluginLoader.instance();
if(plugin){
AppInterface *app = qobject_cast<AppInterface*>(plugin);
if(app){
m_widgetList.append(app);
}
}
}
if(m_widgetList.isEmpty()){
QMessageBox::warning(this, "warning", "load plugin error");
}
else{
foreach(AppInterface *w, m_widgetList){
w->widget();
qDebug() << w->name();
}
}
}
Widget::~Widget()
{
delete ui;
}
void Widget::timerEvent(QTimerEvent *event)
{
if(event->timerId() == m_timerId2){
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QDataStream out(&buffer);
out << m_sendMsg;
if(!m_sharedMemory2->create(buffer.size())){
qDebug() << "create failed!";
return;
}
m_sharedMemory2->lock();
char *to = static_cast<char*>(m_sharedMemory2->data());
memcpy(to, m_sendMsg.toStdString().c_str(), (int)buffer.size());
m_sharedMemory2->unlock();
}
else if(event->timerId() == m_timerId){
if(!m_sharedMemory->attach()){
return;
}
QBuffer buffer;
m_sharedMemory->lock();
buffer.setData((char*)m_sharedMemory->constData(), m_sharedMemory->size());
buffer.open(QBuffer::ReadOnly);
QString data = buffer.readAll();
m_sharedMemory->unlock();
m_sharedMemory->detach();
setMap(data);
//qDebug() << data;
//获取数据
m_sendMsg.clear();
foreach(AppInterface *w, m_widgetList){
QList<int> mapList = m_map.keys();
for(int i = 0; i < mapList.size(); i++){
w->setSQLData(m_map.value(mapList[i]));
m_sendMsg.append(QString::number(mapList[i]) + ";" + w->getSQLData() + "#");
}
}
m_sendMsg.left(m_sendMsg.size() - 1);
qDebug() << m_sendMsg;
}
}
void Widget::setMap(const QString &data)
{
QStringList list = data.split("#");
for(int i = 0; i < list.size(); i++){
QStringList singleList = list[i].split(";");
m_map.insert(singleList[0].toInt(), singleList[1]);
}
}
widget.ui
插件源码
程序结构如下:
这个插件主要是用于读取Mysql
appinterface.h
#ifndef APPINTERFACE_H
#define APPINTERFACE_H
#include <QObject>
class AppInterface{
public:
virtual ~AppInterface(){}
virtual QString name() = 0;
virtual QWidget *widget() = 0;
virtual void setSQLData(const QString &cmdData){ Q_UNUSED(cmdData); }
virtual QString getSQLData(){ return""; }
QString libDir(){
return m_libDir.isEmpty() ? "./" : m_libDir;
}
void setLibDir(const QString &libDir){
m_libDir = libDir;
}
private:
QString m_libDir;
};
QT_BEGIN_NAMESPACE
#define Interface_iid "com.IT1995.Interface"
Q_DECLARE_INTERFACE(AppInterface, Interface_iid)
QT_END_NAMESPACE
#endif // APPINTERFACE_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QSqlDatabase>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
void setData(const QString &cmdData);
QString getData();
~Widget();
protected:
bool connectMySQL();
QString getSqlData(const QString &cmd);
private:
Ui::Widget *ui;
QSqlDatabase m_db;
QString m_cmd;
};
#endif // WIDGET_H
widgetplugin.h
#ifndef WIDGETPLUGIN_H
#define WIDGETPLUGIN_H
#include <QObject>
#include "appinterface.h"
#include "widget.h"
class WidgetPlugin : public QObject, AppInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "com.IT1995.Interface")
Q_INTERFACES(AppInterface)
public:
QString name(){ return QStringLiteral("MySQL插件");}
QWidget *widget(){
m_widget = new Widget();
return m_widget;
}
void setSQLData(const QString &cmdData){
m_widget->setData(cmdData);
}
virtual QString getSQLData(){
return m_widget->getData();
}
private:
Widget *m_widget;
};
#endif // WIDGETPLUGIN_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMessageBox>
#include <QSqlQuery>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
if(!connectMySQL()){
//QMessageBox::information(this, "tip", "连接Mysql数据库失败");
return;
}
//QMessageBox::information(this, "tip", "连接Mysql数据库成功");
}
void Widget::setData(const QString &cmdData)
{
m_cmd = cmdData;
}
QString Widget::getData()
{
return getSqlData(m_cmd);
}
Widget::~Widget()
{
delete ui;
}
bool Widget::connectMySQL()
{
m_db = QSqlDatabase::addDatabase("QMYSQL");
m_db.setHostName("127.0.0.1");
m_db.setPort(3306);
m_db.setDatabaseName("mysql");
m_db.setUserName("root");
m_db.setPassword("root");
if(!m_db.open()){
qDebug() << "error";
return false;
}
return true;
}
QString Widget::getSqlData(const QString &cmd)
{
QSqlQuery query;
if(!query.exec(cmd) || query.size() <= 0){
return "-1234567890";
}
while(query.next()){
//理论只有一条
return query.value(0).toString();
}
return "-1234567890";
}
widget.ui
这个ui里面没东西
MySQL相关
mysql存储过程,表结构,事件已经在下面的博文中给出了,在此不再详细说明:
MySQL工作笔记-使用事件和存储过程定时更新某表数据