Qt中仍可以利用传统的进程间通信方式(共享内存..)
· 在桌面环境中,在传统的进程间通信方式的基础上发展了更为方便的面向对象的通信方式
-
KDE环境:DCOP
-
GNOME环境:Bonobo
· DBUS:freedesktop开源项目的Linux IPC通信机制,KDE和GNOME环境都能支持
· Qt Embedded中定义了一种自己的轻量级的进程间通信机制QCOP
QCOP:
· QCOP利用QcopChannel类来实现.
· QcopChannel从Qobject类继承而来
-
提供了静态函数send()来发送需要传递的消息和数据
-
静态函数isRegistered()来查询某个Channel是否已经被注册
-
当从channel中接收消息和数据时,我们需要构造一个QcopChannel的子类并重写receive()函数,或者提供一个槽并利用connect()函数将receive()信号连接起来
·利用QCOP可以方便的结合qt本身的信号和槽的机制,使用非常方便
·但对于非QT程序与Qt程序的通信,则只能使用其他IPC方式
QCOP示例:
在一个进程中发送消息和数据:
QbyteArray data; QdataStream out(&data,QIODevice::WriteOnly); out<<celNum; QcopChannel::send(“/System/Temperature”,”ConvertCelTOFah(int)”,data); |
在另一个进程中接收消息和数据:
QcopChannel *channel=new QcopChannel(“/System/Temperature”,this); connect(channel,SIGNAL(received(const Qstring &, constQbyteArray&)), this,SLOT(handleMsg(const Qstring&,const QbyteArray&))); |
下面是一个示例:
//CopServ.h 作为服务端运行 –qws #ifndef CONVERSION_SCREEN_H #define CONVERSION_SCREEN_H #include <QWidget> class CopServ : public QWidget { Q_OBJECT public: CopServ(); ~CopServ() {}; private slots: void launchFah(); void launchCel(); private: void createScreen(); void launchApp(const char* path); }; #endif //CONVERSION_SCREEN_H //CopServ.cpp程序主体 #include <QPushButton> #include <QSlider> #include <QLabel> #include <QDial> #include <QLCDNumber> #include <QVBoxLayout> #include <QHBoxLayout> #include <QGridLayout> #include <QSettings> #include <QApplication> #include <QCoreApplication> #include <unistd.h> #include <sys/types.h> #include "CopServ.h" CopServ::CopServ() : QWidget() { createScreen(); } void CopServ::createScreen() { QPushButton* celBtn = new QPushButton("Cel"); QPushButton* fahBtn = new QPushButton("Fah"); QPushButton* quitBtn = new QPushButton("Quit"); QGridLayout *mainLayout = new QGridLayout; mainLayout->addWidget(celBtn, 0, 0); mainLayout->addWidget(fahBtn, 0, 1); mainLayout->addWidget(quitBtn, 1, 0); setLayout(mainLayout); connect(celBtn, SIGNAL(clicked()), this, SLOT(launchCel())); connect(fahBtn, SIGNAL(clicked()), this, SLOT(launchFah())); connect(quitBtn, SIGNAL(clicked()), qApp, SLOT(quit())); setGeometry(0, 50, 240, 320); setWindowTitle("Server Window"); } void CopServ::launchApp(const char* path) //启动子程序 { if (path == NULL) { qDebug("Launch path is NULL!/n"); } pid_t pid = fork(); //创建子进程 if (pid == 0) { qDebug("new process forked. PID is:%d/n", getpid()); int result = execl(path, path, 0); if (result < 0) { qDebug("failed to launch application!/n"); } _exit(-1); } } void CopServ::launchCel() { launchApp("./cel/cel"); } void CopServ::launchFah() { launchApp("./fah/fah"); } //main.cpp #include <QApplication> #include "CopServ.h" int main(int argc, char *argv[]) { QApplication app(argc, argv, QApplication::GuiServer); CopServ screen; // screen.setGeometry(0, 0, 240, 320); screen.show(); return app.exec(); } |
//Cel.h //子程序1的头文件 #ifndef CEL_H #define CEL_H #include <QWidget> class QSlider; class QHBoxLayout; class Cel : public QWidget { Q_OBJECT public: Cel(); ~Cel() {}; private slots: void handleMsg(const QString &message, const QByteArray &data); void sendMsg(int celNum); //槽 private: void fahToCel(int fahNum); void createScreen(); void createCel(); void listenChannel(); QSlider* slider; QHBoxLayout* celLayout; }; //Cel.cpp #endif //CEL_H #include <QPushButton> #include <QSlider> #include <QLabel> #include <QLCDNumber> #include <QVBoxLayout> #include <QHBoxLayout> #include <QApplication> #include <QCopChannel> #include <QDataStream> #include <QByteArray> #include "Cel.h" Cel::Cel() : QWidget() { createScreen(); listenChannel(); } void Cel::createScreen() { QPushButton* quitBtn = new QPushButton("Quit"); createCel(); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(quitBtn); mainLayout->addLayout(celLayout); setLayout(mainLayout); slider->setFocus(); connect(quitBtn, SIGNAL(clicked()), qApp, SLOT(quit())); setWindowTitle("Celsius"); } void Cel::createCel() { slider = new QSlider(Qt::Vertical); slider->setRange(0, 100); slider->setValue(0); slider->setTickPosition(QSlider::TicksLeft); QLabel* celLabel = new QLabel("0"); celLayout = new QHBoxLayout; celLayout->addWidget(celLabel, 0, Qt::AlignRight); celLayout->addWidget(slider, 0, Qt::AlignLeft); celLayout->setSpacing(10); connect(slider, SIGNAL(valueChanged(int)), celLabel, SLOT(setNum(int))); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sendMsg(int))); } void Cel::fahToCel(int fahNum) { int celNum = (fahNum - 32) * 5 / 9; slider->setValue(celNum); } void Cel::listenChannel() { QCopChannel *channel = new QCopChannel("/System/Temperature", this);//注册Channel connect(channel, SIGNAL(received(const QString &, const QByteArray &)), this, SLOT(handleMsg(const QString &, const QByteArray &))); } void Cel::handleMsg(const QString &message, const QByteArray &data)//处理收到信息 { QDataStream in(data); if (message == "ConvertFahToCel(int)") { int fahNum; in >> fahNum; fahToCel(fahNum); } } void Cel::sendMsg(int celNum) //发送信息 { QByteArray data; QDataStream out(&data, QIODevice::WriteOnly); out << celNum; QCopChannel::send("/System/Temperature", "ConvertCelToFah(int)", data); } #include <QApplication> #include "Cel.h" int main(int argc, char *argv[]) { QApplication app(argc, argv/*, QApplication::GuiClient*/); Cel screen; screen.setGeometry(0, 25, 100, 250); screen.show(); return app.exec(); } |
//Fah.h 子程序2的头文件 #ifndef FAH_H #define FAH_H #include <QWidget> class QDial; class QVBoxLayout; class Fah : public QWidget { Q_OBJECT public: Fah(); ~Fah() {}; private slots: void handleMsg(const QString &message, const QByteArray &data); void sendMsg(int fahNum); //自定义槽 private: void celToFah(int celNum); void createScreen(); void createFah(); void listenChannel(); QDial* dial; QVBoxLayout* fahLayout; }; #endif //FAH_H #include <QPushButton> #include <QDial> #include <QLCDNumber> #include <QVBoxLayout> #include <QApplication> #include <QCopChannel> #include <QDataStream> #include <QByteArray> #include "Fah.h" Fah::Fah() : QWidget() { createScreen(); listenChannel(); } void Fah::createScreen() { QPushButton* quitBtn = new QPushButton("Quit"); createFah(); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(quitBtn); mainLayout->addLayout(fahLayout); setLayout(mainLayout); dial->setFocus(); connect(quitBtn, SIGNAL(clicked()), qApp, SLOT(quit())); setWindowTitle("Fahrenheit"); } void Fah::createFah() { QLCDNumber* lcdNum = new QLCDNumber(3); lcdNum->setSegmentStyle(QLCDNumber::Filled); lcdNum->display(32); dial = new QDial; dial->setRange(32, 212); dial->setValue(32); dial->setNotchesVisible(true); fahLayout = new QVBoxLayout; fahLayout->addWidget(lcdNum, 0, Qt::AlignBottom | Qt::AlignHCenter); fahLayout->addWidget(dial); fahLayout->setSpacing(10); connect(dial, SIGNAL(valueChanged(int)), lcdNum, SLOT(display(int))); connect(dial, SIGNAL(valueChanged(int)), this, SLOT(sendMsg(int))); } void Fah::celToFah(int celNum) { int fahNum = (celNum * 9 / 5) + 32; dial->setValue(fahNum); } void Fah::listenChannel() { QCopChannel *channel = new QCopChannel("/System/Temperature", this); connect(channel, SIGNAL(received(const QString &, const QByteArray &)), this, SLOT(handleMsg(const QString &, const QByteArray &))); } void Fah::handleMsg(const QString &message, const QByteArray &data) { QDataStream in(data); if (message == "ConvertCelToFah(int)") { int celNum; in >> celNum; celToFah(celNum); } } void Fah::sendMsg(int fahNum) { QByteArray data; QDataStream out(&data, QIODevice::WriteOnly); out << fahNum; QCopChannel::send("/System/Temperature", "ConvertFahToCel(int)", data); } #include <QApplication> #include "Fah.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Fah screen; screen.setGeometry(130, 25, 100, 250); screen.show(); return app.exec(); } |