个人QT学习项目(二)

多窗口之间通信和发送数据

         多窗口之间通信和数据传送中使用了两种模式:第一种是使用了单例模式。第二种使用了观察者模式。如果有不足之处或者哪里有错误请多多指点。

第一种单例模式

        点击下图空白区域,新建"新建项目",会弹出新窗口。因为这种比较简单,就使用单例模式:

 

 

单例模式介绍:

         创建一个单例的类WidMessageManage  

#ifndef MESSAGETYPES_H
#define MESSAGETYPES_H

#include <QString>
//单例模式的宏
#define POP_NEW_PRO_DIALOG_MESSAGE 1

#define UP_DATA_TREEFORM_MESSAGE   20
#define READE_SQLITE_FILE_NAMES    21
#define CREADE_SQLITE_TABLE_NAMES   22

#define READE_SQLITE_TABLE_NAMES   30


#ifndef WIDMESSAGEMANAGE_H
#define WIDMESSAGEMANAGE_H

#include <QObject>
#include <QVariant>
#include "MessageTypes.h"
class WidMessageManage : public QObject
{
    Q_OBJECT
public:
    static WidMessageManage *instance();

signals:
    //全局单例模式,信号
    void messageReceived(int MessageTypes,QVariant data);
public slots:
    //全局单例模式,发送信号
    void sendMessage(int MessageTypes,QVariant data);
};

#endif // WIDMESSAGEMANAGE_H

 

#include "WidMessageManage.h"


WidMessageManage *WidMessageManage::instance()
{
    static WidMessageManage instance;
    return &instance;
}

void WidMessageManage::sendMessage(int MessageTypes, QVariant data)
{
    emit messageReceived(MessageTypes,data);
}

单例模式使用:

        在窗口类PopCreateNewProDialog中使用WidMessageManage::instance()->sendMessage(POP_NEW_PRO_DIALOG_MESSAGE,str);函数实现单例模式发送消息和数据。

#include "PopCreateNewProDialog.h"
#include "ui_PopCreateNewProDialog.h"


#include "MessageTypes.h"
#include "WidMessageManage.h"
#include <QDebug>
#define cout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]"

PopCreateNewProDialog::PopCreateNewProDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::PopCreateNewProDialog)
{
    ui->setupUi(this);
    //1.将窗口设置窗口
    setWindowFlags(Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint);
    //2.禁止拖动窗口大小
    setFixedSize(this->width(),this->height());
    //3.将窗口设置为关闭释放内存
    setAttribute(Qt::WA_DeleteOnClose);
    //4.随主函数关闭而关闭
    setAttribute(Qt::WA_QuitOnClose, false);
    //5.设置模态模式
    setModal(true);
    setWindowTitle(tr("新建项目名称"));
}

PopCreateNewProDialog::~PopCreateNewProDialog()
{
    if(nullptr !=ui)
    {
       delete ui;
       ui=nullptr;
    }

}

void PopCreateNewProDialog::on_CreateNewPro_pB_clicked()
{
    QString str=ui->CreateNewPro_LineEdit->text();
    if(str.isEmpty())
    {
        return ;
    }
    WidMessageManage::instance()->sendMessage(POP_NEW_PRO_DIALOG_MESSAGE,str);
    deleteLater();
}

  在窗口类TreeForm中接收消息和处理。

    //通过单例模式,接收信号消息
    connect(WidMessageManage::instance(),&WidMessageManage::messageReceived,
            this,&TreeForm::WidMessageUpdateRequest);
//单例模式,接收到的信号
void TreeForm::WidMessageUpdateRequest(int messageType, QVariant data)
{
    switch (messageType) {
    case UP_DATA_TREEFORM_MESSAGE:
        updateTreeItem(qvariant_cast<QString>(data));
        break;
    case CREADE_SQLITE_TABLE_NAMES:
        CreateChildItem(qvariant_cast<QStringList>(data),m_parentName);
        break;
    default:
        break;
    }

}

观察者模式介绍:

        这里使用了中介观察者模式,实现窗口之间互相通信和传数据。

#ifndef UIMEDIATOR_H
#define UIMEDIATOR_H

#include "IObserver.h"
#include <QString>
class IObserver; // 前置声明

class UIMediator
{
public:
    virtual void addObserver(IObserver *observer) = 0;
    virtual void notifyAll(const QString &message) = 0;
};

#endif // UIMEDIATOR_H
#ifndef UIMEDIATORIMPL_H
#define UIMEDIATORIMPL_H

#include "UIMediator.h"
#include <QVector>

enum MESSAGE
{
    TREEFORM_TO_CENTRAFORM_MESSAGE =0x00000001
};

class UIMediatorImpl : public UIMediator
{
public:
    //观察者模式,注册
    void addObserver(IObserver *observer) override;
    //观察者模式,发送信号
    void notifyAll(const QString &message) override;
private:
    QVector<IObserver *> observers_;
};

#endif // UIMEDIATORIMPL_H
#include "UIMediatorImpl.h"


void UIMediatorImpl::addObserver(IObserver *observer)
{
    observers_.push_back(observer);
}

void UIMediatorImpl::notifyAll(const QString &message)
{
    for (auto observer : observers_) {
        observer->onNotify(message);
    }
}

观察者模式使用:

 在入口类中创建 UIMediatorImpl 实例化。因为窗口类是嵌入了几层 ,所有这里啰嗦几句。

MainWindow窗口类只是用来,承载窗口使用所有是空白的。主要承载MainForm窗口类使用

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    void initController();
private:
    UIMediatorImpl mediator;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , p_Controller(new ControllerManager(&mediator))
    , p_StackWid(new QStackedWidget(this))
    , p_mainForm(new MainForm(&mediator,this))
{
    ui->setupUi(this);
    this->statusBar()->setSizeGripEnabled(false);//隐藏状态栏上的拖动图标
    p_StackWid->addWidget(p_mainForm);
    ui->mainWid_centralwidget->layout()->addWidget(p_StackWid);

    initController();

}

 各个子窗口会在MainForm 实例化,并把观察者中介UIMediator按照参数,传到需要的子窗口类中。 

#ifndef MAINFORM_H
#define MAINFORM_H

#include <QWidget>

#include "TreeForm.h"
#include "CentralForm.h"
#include "ParamForm.h"
#include "BottomForm.h"


class UIMediatorImpl;
namespace Ui {
class MainForm;
}

class MainForm : public QWidget
{
    Q_OBJECT

public:
    explicit MainForm(UIMediator *mediator,QWidget *parent = nullptr);
    ~MainForm();


private:
    Ui::MainForm *ui;
    TreeForm      *p_treeForm;
    CentralForm   *p_centralForm;
    ParamForm     *p_paramForm;
    BottomForm    *p_bottomForm;
};

#endif // MAINFORM_H
#include "MainForm.h"
#include "ui_MainForm.h"


MainForm::MainForm(UIMediator *mediator, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainForm)
  , p_treeForm(new TreeForm(mediator))
  , p_centralForm(new CentralForm(mediator))
  , p_paramForm(new ParamForm)
  , p_bottomForm(new BottomForm)
{
    ui->setupUi(this);
    ui->treewid->layout()->addWidget(p_treeForm);
    ui->centralwid->layout()->addWidget(p_centralForm);
    ui->paramwid->layout()->addWidget(p_paramForm);
    ui->bottomwid->layout()->addWidget(p_bottomForm);


}



MainForm::~MainForm()
{
    delete ui;
}

子窗口使用观察者模式:

#ifndef TREEFORM_H
#define TREEFORM_H

#include <QWidget>
#include <QMenu>
#include <QVariant>
#include <QTreeWidgetItem>
#include "PopCreateNewProDialog.h"
#include "addSQLiteTableDialog.h"

#include "IObserver.h"
#include "UIMediator.h"

class UIMediator;

namespace Ui {
class TreeForm;
}

class TreeForm : public QWidget ,IObserver
{
    Q_OBJECT

public:
    explicit TreeForm(UIMediator *mediator,QWidget *parent = nullptr);
    ~TreeForm();

    //观察者模式,接收信号
    void onNotify(const QString &message) override;
    //观察者模式,发送信号
    void doSomething(const QString &message);
private:
    //观察者模式,中介者
    UIMediator *mediator_;

private:
    void updateTreeItem(const QString &PathFile);
private:
    //初始化菜单
    void InitRightMenu();

private slots:
    //弹出,创建新项目的Dialog
    void PopCreateProDialog();
    //qtreeWidget右键弹出菜单窗口
    void SlotsPopUpMenu(const QPoint &pos);

    void PopCreateTableDialog();
    //执行点击内容时需要做的操作
    void on_TreeForm_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
    // 执行在展开项时需要做的操作
    void on_TreeForm_treeWidget_itemExpanded(QTreeWidgetItem *item);
    // 用户点击了三角箭头,当前项折叠
    void on_TreeForm_treeWidget_itemCollapsed(QTreeWidgetItem *item);

public slots:
    //单例模式,接收到的信号
    void WidMessageUpdateRequest(int messageType, QVariant data);

private:
    //创建Item
    void CreateTopItem(const QString &PathFile,const QString Type);
    //创建Item的子项目
    void CreateChildItem(const QStringList &strList,const QString &parentName);
    //Delete Child Item
    void DeleteChildItem(QTreeWidgetItem *item);
private:
    QMenu *p_newProMenu;
    QMenu *p_CreateTableMenu;

    QAction *p_newProQAction;
    QAction *p_CreateTableQAction;
private:
    QString m_TreeItemParentName=NULL;
    QList<QTreeWidgetItem *> topParentItemNames;
    QString m_parentName;
    QString mItemParentName=NULL;
private:
    PopCreateNewProDialog *p_popCreateNewDialog=nullptr;
    addSQLiteTableDialog  *p_addSQLiteTableDialog=nullptr;
private:
    Ui::TreeForm *ui;

};

#endif // TREEFORM_H
#include "TreeForm.h"
#include "ui_TreeForm.h"

#include "MessageTypes.h"
#include "WidMessageManage.h"

#include "UIMediator.h"
#include <QDir>
#include <QFileInfo>
#include <QDateTime>
#include <map>
#include <QTreeWidgetItem>


#include <QDebug>
#define cout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]"

TreeForm::TreeForm(UIMediator *mediator,QWidget *parent) :
    QWidget(parent),
    mediator_(mediator)
  , ui(new Ui::TreeForm)
{
    ui->setupUi(this);
    ui->TreeForm_treeWidget->setHeaderLabel(tr("项目名称"));
    InitRightMenu();
    //响应右键菜单信号槽-qtreeWidget右键弹出菜单窗口
    connect(ui->TreeForm_treeWidget,&QTreeWidget::customContextMenuRequested,
                this,&TreeForm::SlotsPopUpMenu);

    //通过单例模式,接收信号消息
    connect(WidMessageManage::instance(),&WidMessageManage::messageReceived,
            this,&TreeForm::WidMessageUpdateRequest);
    //注册观察者模式,信号接收人
    mediator_->addObserver(this);

    /**************************************************************/
    //刷新Item目录
    WidMessageManage::instance()->sendMessage(READE_SQLITE_FILE_NAMES,NULL);
}

TreeForm::~TreeForm()
{
    delete ui;
}
//观察者模式,接收信号
void TreeForm::onNotify(const QString &message)
{


}
//观察者模式,触发信号
void TreeForm::doSomething(const QString &message)
{
    mediator_->notifyAll(message);
}

void TreeForm::updateTreeItem(const QString &PathFile)
{
    QString targetFormat=".db";
    CreateTopItem(PathFile,targetFormat);
}


//初始化右键菜单
void TreeForm::InitRightMenu()
{
    //打开右键菜单属性
    ui->TreeForm_treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    /*********************新建项目************************/
    //右键菜单
    p_newProMenu =new QMenu(ui->TreeForm_treeWidget);
    p_newProQAction=new QAction;
    p_newProQAction->setText(tr("新建项目"));
    p_newProMenu->addAction(p_newProQAction);
    p_newProMenu->addAction("取消");
    //响应右键菜单信号槽
    connect(p_newProQAction,SIGNAL(triggered()),
            this,SLOT(PopCreateProDialog()));
    /*********************新建表************************/
    //右键菜单
    p_CreateTableMenu=    new QMenu(ui->TreeForm_treeWidget);
    p_CreateTableQAction= new QAction;
    p_CreateTableQAction->setText(tr("创建SQLite表名"));
    p_CreateTableMenu->addAction(p_CreateTableQAction);
    p_CreateTableMenu->addAction(tr("取消"));
    //响应右键菜单信号槽
    connect(p_CreateTableQAction,SIGNAL(triggered()),
            this,SLOT(PopCreateTableDialog()));

}
//弹出,创建新项目的Dialog
void TreeForm::PopCreateProDialog()
{
     p_popCreateNewDialog=new PopCreateNewProDialog;
     p_popCreateNewDialog->show();
}
//qtreeWidget右键弹出菜单窗口
void TreeForm::SlotsPopUpMenu(const QPoint &pos)
{
    //弹出菜单
    QTreeWidgetItem *clickedItem=ui->TreeForm_treeWidget->itemAt(pos);
    //弹出菜单判断是否,有父Item
    if(NULL != clickedItem)
    {
        //判断是父节点
        if(clickedItem->parent()==nullptr)
        {
            m_TreeItemParentName=clickedItem->text(0);
            p_CreateTableMenu->exec(ui->TreeForm_treeWidget->mapToGlobal(pos));
        }
    }
    //弹出菜单是没有父Item 在空白处点击了右键,弹性窗口菜单
    else
    {
        p_newProMenu->exec(ui->TreeForm_treeWidget->mapToGlobal(pos));
    }



}

void TreeForm::PopCreateTableDialog()
{
    addSQLiteTableDialog::CreateEidtSQLiteDialog(mItemParentName);
}
//单例模式,接收到的信号
void TreeForm::WidMessageUpdateRequest(int messageType, QVariant data)
{
    switch (messageType) {
    case UP_DATA_TREEFORM_MESSAGE:
        updateTreeItem(qvariant_cast<QString>(data));
        break;
    case CREADE_SQLITE_TABLE_NAMES:
        CreateChildItem(qvariant_cast<QStringList>(data),m_parentName);
        break;
    default:
        break;
    }

}

void TreeForm::CreateTopItem(const QString &PathFile,const QString Type)
{
    topParentItemNames.clear();
    // 清空原有的顶层项
    ui->TreeForm_treeWidget->clear();
    QString targetFormat=Type;
    if(PathFile.isNull())
    {
        cout<<"filesName";
        return;
    }
    // 用于存储文件创建时间和文件名的映射
    QString fliename=PathFile;//.toString();
    QDir directory(fliename);
    QStringList files=directory.entryList(QDir::Files);
    QMap<QDateTime,QString>fileMap;
    foreach (const QString &file, files)
    {
        //判断数据类型,挑选.DB数据类型
        if(file.endsWith(targetFormat))
        {
            QFileInfo fileInfo(directory.absoluteFilePath(file));
            QDateTime createdTime = fileInfo.created(); // 获取文件创建时间
            // 将文件创建时间和文件名存入映射中
            fileMap.insert(createdTime, file);
        }

    }
    // 提取 QMap 的 key 到 QList 中
    QList<QDateTime> sortedKeys = fileMap.keys();

    // 根据创建时间创建 QTreeWidgetItem 并添加到 treeWidget 中
    int sortedKeys_size=sortedKeys.size();
    for(int i =  sortedKeys_size- 1; i >= 0; --i)
    {
        const QDateTime &time = sortedKeys.at(i);
        QTreeWidgetItem *newTopItem=new QTreeWidgetItem(ui->TreeForm_treeWidget);
        newTopItem->setTextAlignment(0,Qt::AlignLeft | Qt::AlignVCenter); // 左对齐
 //       newTopItem->setData(0, Qt::UserRole, index); // 设置序号数据
 //       newTopItem->setText(0, QString::number(index) + ". " + file); // 显示序号和文件名

        // 去掉文件名后缀
        QString fileWithoutExtension = fileMap.value(time);
        fileWithoutExtension.remove(targetFormat);

        newTopItem->setData(0, Qt::UserRole, fileWithoutExtension); // 设置文件名数据
        newTopItem->setText(0, fileWithoutExtension); // 显示文件名
        // 设置显示三角箭头
        newTopItem->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);

        ui->TreeForm_treeWidget->addTopLevelItem(newTopItem);
        topParentItemNames.append(newTopItem);

    }
//    cout<<topParentItemNames.size();
    //    cout<<topParentItemNames.at(3)->text(0);
}
//创建Item的子项目
void TreeForm::CreateChildItem(const QStringList &strList,const QString &parentName)
{
    // 遍历 QList<QTreeWidgetItem *> topParentItemNames
    //topParentItemNames.clear();
    for (QTreeWidgetItem *parentItem : topParentItemNames)
    {

        // 根据具体条件判断是否当前的 parentItem 是你要找的父项
        if (parentItem->text(0) == parentName) // 假设父项的文本与 parentName 匹配
        {

            // 创建子项并添加到父项中
            for (const QString &text : strList)
            {
                QTreeWidgetItem *childItem = new QTreeWidgetItem(parentItem, QStringList(text));
                parentItem->addChild(childItem);
            }
            // 如果只需要找到一个合适的父项,可以在此处 break;
            break;
        }
    }

}

void TreeForm::DeleteChildItem(QTreeWidgetItem *item)
{
    // 删除子项
    for (int i = item->childCount() - 1; i >= 0; --i)
    {
        delete item->child(i);
    }
}
//执行点击内容时需要做的操作
void TreeForm::on_TreeForm_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
{
    cout << "Arrow clicked - Expanded";
    if (column == 0) { // 只处理第一列的点击事件,如果有多列,根据实际情况修改
            if (item->childCount() > 0 && ui->TreeForm_treeWidget->isItemExpanded(item)) {
                // 用户点击了三角箭头,并且当前项展开着
                // 执行相应的动作
                cout << "Arrow clicked - Expanded";
            } else if (item->childCount() > 0 && !ui->TreeForm_treeWidget->isItemExpanded(item)) {
                // 用户点击了三角箭头,并且当前项折叠着
                // 执行相应的动作
                cout << "Arrow clicked - Collapsed";
                DeleteChildItem(item);
            }
    }
}
//执行在展开项时需要做的操作
void TreeForm::on_TreeForm_treeWidget_itemExpanded(QTreeWidgetItem *item)
{

    QString str=item->text(0);
    if(str!=NULL)
    {
        m_parentName=str;
        WidMessageManage::instance()->sendMessage(READE_SQLITE_TABLE_NAMES,str);
    }

}
// 用户点击了三角箭头,当前项折叠
void TreeForm::on_TreeForm_treeWidget_itemCollapsed(QTreeWidgetItem *item)
{
    DeleteChildItem(item);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值