一种事件驱动型的界面交互架构(基于Qt框架)

该博客介绍了一种用于上位机桌面软件的事件驱动型界面交互架构,旨在实现界面和业务逻辑的分离。架构包含指令和指令执行管理器两部分,通过创建指令对象并将其添加到执行管理器的队列中,由后台线程统一处理。当指令执行完毕,通过信号槽机制通知界面。示例代码展示了如何创建指令基类、命令执行管理器以及一个具体的打开文件指令的实现。
摘要由CSDN通过智能技术生成

一种事件驱动型的界面交互架构

背景

通常在一些上位机的桌面软件开发中,界面会有很多操作控件,实现界面和底层业务逻辑的分离是非常有必要的,这样的代码层次分明,界面和业务逻辑耦合度低。

架构的组成

架构大致分为两个部分:

  • 一个是指令
  • 一个是指令执行管理器

界面在控件在进行某些操作后,创建相应的指令对象,然后将指令对象添加到指令执行管理器中(入队列),然后由指令执行管理器中的线程进行统一处理,执行管理器内部有一个队列容器,执行一条指令,出队列一条指令。

架构代码

  • 指令基类 (头文件)
#ifndef IUICOMMAND_H
#define IUICOMMAND_H

#include <QObject>

class CmdExecuteMgr;

class IUICommand : public QObject
{
    Q_OBJECT
public:
    explicit IUICommand(bool bReply = false, QObject *parent = nullptr);
    virtual ~IUICommand();

public:
    void AddToCmdExecuteMgr(CmdExecuteMgr* pCmdExeMgr);     // 将指令添加到指令执行管理容器中
    virtual void Execute() = 0;                             // 执行指令,执行的返回成功或失败结果返给 m_bExeResult

    bool GetReply();
    bool GetExeResult();

    void EmitSignalCmdExecuteOver();

signals:
    void SignalCmdExecuteOver(IUICommand*);                 // 指令执行完成的信号

public slots:

protected:
    bool m_bReply;
    bool m_bExeResult;
};

#endif // IUICOMMAND_H

  • 指令基类 (源文件)
#include "IUICommand.h"
#include "CmdExecuteMgr.h"

IUICommand::IUICommand(bool bReply /*= false*/, QObject *parent /*= nullptr*/)
    : QObject(parent), m_bReply(bReply), m_bExeResult(false)
{
    // ....
}

IUICommand::~IUICommand()
{

}

void IUICommand::AddToCmdExecuteMgr(CmdExecuteMgr* pCmdExeMgr)
{
    if (nullptr != pCmdExeMgr)
        pCmdExeMgr->AppendCmd(this);
}

bool IUICommand::GetReply()
{
    return m_bReply;
}

bool IUICommand::GetExeResult()
{
    return m_bExeResult;
}

void IUICommand::EmitSignalCmdExecuteOver()
{
    emit SignalCmdExecuteOver(this);
}

  • 命令执行管理器(头文件)
#ifndef CMDEXECUTEMGR_H
#define CMDEXECUTEMGR_H

#include <list>
#include <QThread>
#include "IUICommand.h"

using std::list;

class CmdExecuteMgr : public QThread
{
    Q_OBJECT
public:
    explicit CmdExecuteMgr(QObject *parent = nullptr);
    ~CmdExecuteMgr() override;

public:
    void AppendCmd(IUICommand* pCmd);

protected:
    virtual void run() override;

private:
    void HandleNextCmd();

signals:

public slots:

private:
    list<IUICommand*> m_CmdList;
};


#endif // CMDEXECUTEMGR_H

  • 命令执行管理器(源文件)
#include "CmdExecuteMgr.h"

CmdExecuteMgr::CmdExecuteMgr(QObject *parent) : QThread(parent)
{

}

CmdExecuteMgr::~CmdExecuteMgr()
{

}

void CmdExecuteMgr::AppendCmd(IUICommand* pCmd)
{
    if (nullptr != pCmd)
        m_CmdList.push_back(pCmd);
}

void CmdExecuteMgr::run()
{
    // 这里在正式的项目中一般要设置为软件运行的标识符
    while (true)
    {
        HandleNextCmd();

        // 这个时间可以自主设置
        QThread::msleep(100);
    }
}

void CmdExecuteMgr::HandleNextCmd()
{
    if (m_CmdList.empty())
        return;

    IUICommand* pCmd = m_CmdList.front();

    if (nullptr == pCmd)
        return;

     pCmd->Execute();

     // 需要返回
     if (pCmd->GetReply())
     {
        pCmd->EmitSignalCmdExecuteOver();
     }
     else
     {
         delete pCmd;
     }

     m_CmdList.pop_front();
}

示例:

  • 打开文件指令(头文件)
#ifndef OPENFILECMD_H
#define OPENFILECMD_H

#include <QObject>
#include <iostream>
#include <string>
#include "IUICommand.h"

using namespace std;

struct FileData
{

};

class OpenFileCmd : public IUICommand
{
    Q_OBJECT
public:
    explicit OpenFileCmd(const string& strFilePath, bool bReply = false);
    ~OpenFileCmd() override;

public:
    void SetFilePath(const string& strFilePath);
    const string& GetFilePath() const;

    const FileData& GetFileData() const;

    void Execute() override;


signals:

public slots:

private:
    string m_strFilePath;               // 指令执行需要的参数
    FileData m_FileData;
};

#endif // OPENFILECMD_H

  • 打开文件指令(源文件)
#include "OpenFileCmd.h"

OpenFileCmd::OpenFileCmd(const string& strFilePath, bool bReply /*= false*/)
    : IUICommand(bReply), m_strFilePath(strFilePath)
{
    // ...
}

OpenFileCmd::~OpenFileCmd()
{

}

void OpenFileCmd::SetFilePath(const string& strFilePath)
{
    m_strFilePath = strFilePath;
}

const string& OpenFileCmd::GetFilePath() const
{
    return m_strFilePath;
}

const FileData &OpenFileCmd::GetFileData() const
{
    return m_FileData;
}

void OpenFileCmd::Execute()
{
    // 打开文件
    // 将数据写到 m_FileData
    // 将打开的结果给到 m_bExeResult
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值