• C/C++ QT实现自定义对话框


    对话框分为多种,常见的有通用对话框,自定义对话框,模态对话框,非模态对话框等,其中通用对话框包括了,QFileDialog文件对话框,QColorDialog颜色对话框,QFontDialog字体对话框,QInputDialog输入对话框等,自定义对话框则主要是实现自己布局的简单页面,区别于窗体对话框则显得更加简单一些,除对话框外,多窗体设计也是最常用的,例如多窗体嵌入,MID窗体等,下面则是每种窗体的代码总结。

    创建自定义窗体

    1.首先使用两个控件,TableView主要是表格处理,TreeView主要是树形框,这两者可以通过 QItemSelectionModel 模型绑定起来从而可实现菜单联动。

    # mainwindow.h
    
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <iostream>
    #include <QStandardItem>
    #include <QItemSelectionModel>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
        QStandardItemModel *model;       // 定义数据模型
        QItemSelectionModel *selection;  // 定义Item选择模型
    };
    #endif // MAINWINDOW_H
    
    # mainwindow.cpp
    
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        model = new QStandardItemModel(4,5,this);
        selection = new QItemSelectionModel(model);
    
        // 关联到tableView
        ui->tableView->setModel(model);
        ui->tableView->setSelectionModel(selection);
    
        // 关联到treeView
        ui->treeView->setModel(model);
        ui->treeView->setSelectionModel(selection);
    
        // 添加表头
        QStringList HeaderList;
        HeaderList << "序号" << "姓名" << "年龄" << "性别" << "婚否";
        model->setHorizontalHeaderLabels(HeaderList);
    
        // 批量添加数据
        QStringList DataList[3];
        QStandardItem *Item;
    
        DataList[0] << "1001" << "admin" << "24" << "男" << "是";
        DataList[1] << "1002" << "lyshark" << "23" << "男" << "否";
        DataList[2] << "1003" << "lucy" << "37" << "女" << "是";
    
        int Array_Length = DataList->length();                          // 获取每个数组中元素数
        int Array_Count = sizeof(DataList) / sizeof(DataList[0]);       // 获取数组个数
    
        for(int x=0; x<Array_Count; x++)
        {
            for(int y=0; y<Array_Length; y++)
            {
                Item = new QStandardItem(DataList[x][y]);
                model->setItem(x,y,Item);
            }
        }
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    2.首先来创建一个自定义对话框,创建对话框先要在项目上右键,选项【addNew】选择【QT】点击【QT设计师】,我们这里选择最后一个最为界面框架。

    3.默认情况下,QT会生成三个文件【.ui 界面库】【.h 头文件】【.cpp 源文件】名字相同的三个文件,对应一个界面。

    4.设计好界面布局,然后开始写代码。

    dialogsize.h

    #ifndef DIALOGSIZE_H
    #define DIALOGSIZE_H
    
    #include <QDialog>
    
    namespace Ui {
    class DialogSize;
    }
    
    class DialogSize : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit DialogSize(QWidget *parent = nullptr);
        ~DialogSize();
    
        int rowCount();                         // 获取对话框输入的行数
        int columnCount();                      // 获取对话框输入的列数
        void etRowColumn(int row, int column);  // 初始对话框上两个SpinBox的值
    
    private:
        Ui::DialogSize *ui;
    };
    
    #endif // DIALOGSIZE_H
    

    dialogsize.cpp

    #include "dialogsize.h"
    #include "ui_dialogsize.h"
    
    DialogSize::DialogSize(QWidget *parent) :QDialog(parent),ui(new Ui::DialogSize)
    {
        ui->setupUi(this);
    }
    
    DialogSize::~DialogSize()
    {
        delete ui;
    }
    
    // 主窗体调用获取当前行数
    int DialogSize::rowCount()
    {
        return  ui->spinBoxRow->value();
    }
    
    // 主窗体调用获取当前列数
    int DialogSize::columnCount()
    {
        return  ui->spinBoxColumn->value();
    }
    
    // 设置主窗体中的TableView行数与列数
    void DialogSize::setRowColumn(int row, int column)
    {
        ui->spinBoxRow->setValue(row);
        ui->spinBoxColumn->setValue(column);
    }
    

    mainwindow.cpp 主窗体中按钮一被点击时执行。

    // 当按钮1被点击触发
    void MainWindow::on_pushButton_clicked()
    {
        DialogSize *ptr = new DialogSize(this);     // 创建一个对话框
        Qt::WindowFlags flags = ptr->windowFlags(); // 需要获取返回值
        ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint);  // 设置对话框固定大小
        ptr->setRowColumn(model->rowCount(),model->columnCount());      // 对话框数据初始化
    
        int ref = ptr->exec();             // 以模态方式显示对话框
        if (ref==QDialog::Accepted)        // OK键被按下,对话框关闭
        {
            // 当BtnOk被按下时,则设置对话框中的数据
            int cols=ptr->columnCount();
            model->setColumnCount(cols);
    
            int rows=ptr->rowCount();
            model->setRowCount(rows);
        }
        
        // 最后删除释放对话框句柄
        delete ptr;
    }
    

    配置完后,我们还需要绑定两个槽函数,首先来到dialog窗体上,手动添加两条槽函数,当按钮被点击后,后发送一个信号,主窗体接收到后处理即可。

    运行效果如下,这是一个模态对话框,所谓模态就是说,当打开时不能再次操作主窗体,只有模态对话框关闭时才能继续操作主窗体。

    接着来写一个非模态对话框,这次创建一个Dialog名字就叫做DialogHead并绘制好界面。

    dialoghead.h

    #ifndef DIALOGHEAD_H
    #define DIALOGHEAD_H
    
    #include <QDialog>
    #include <QStringListModel>
    
    namespace Ui {
    class DialogHead;
    }
    
    class DialogHead : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit DialogHead(QWidget *parent = nullptr);
        ~DialogHead();
    
        void setHeaderList(QStringList& headers);   // 设置表头数据
        QStringList headerList();                   // 返回表头数据
    private:
        QStringListModel *model;       // 定义数据模型
        Ui::DialogHead *ui;
    };
    
    #endif // DIALOGHEAD_H
    
    

    dialoghead.cpp

    #include "dialoghead.h"
    #include "ui_dialoghead.h"
    
    DialogHead::DialogHead(QWidget *parent) :QDialog(parent),ui(new Ui::DialogHead)
    {
        ui->setupUi(this);
        model = new QStringListModel;
        ui->listView->setModel(model);
    }
    
    DialogHead::~DialogHead()
    {
        delete ui;
    }
    
    // 设置当前listView中的数据
    void DialogHead::setHeaderList(QStringList &headers)
    {
        model->setStringList(headers);
    }
    // 返回当前的表头
    QStringList DialogHead::headerList()
    {
        return model->stringList();
    }
    

    mainwindow.cpp

    // 对话框设置表头数据
    void MainWindow::on_pushButton_2_clicked()
    {
        DialogHead *ptr = new DialogHead(this);
        Qt::WindowFlags flags = ptr->windowFlags();
        ptr->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint);
    
        // 如果表头列数变化,则从新初始化
        if(ptr->headerList().count() != model->columnCount())
        {
            QStringList strList;
    
            // 获取现有的表头标题
            for (int i=0;i<model->columnCount();i++)
            {
                strList.append(model->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString());
            }
    
            // 用于对话框初始化显示
            ptr->setHeaderList(strList);
        }
    
        int ref = ptr->exec();  // 调用弹窗
        if(ref==QDialog::Accepted)
        {
            QStringList strList=ptr->headerList();//获取对话框上修改后的StringList
            model->setHorizontalHeaderLabels(strList);// 设置模型的表头标题
        }
    
        delete ptr;
    }
    

    最后在Dialog上绑定信号与曹。

    前面的交互都是使用传统的相互引用实现的,实现起来较复杂,同样可以使用信号与曹来实现,将信号与曹关联起来,在进行操作时发送信号,槽函数接受并相应。

    实现多窗体设计

    多窗体分为窗体卡和MID窗体,这两种窗体也最常用。

    1.首先是窗体卡片,这里在创建是应该选择Widget窗体,这个窗体最干净没啥控件,所以我们选择它。

    formdoc.h

    #ifndef FORMDOC_H
    #define FORMDOC_H
    
    #include <QWidget>
    
    namespace Ui {
    class FormDoc;
    }
    
    class FormDoc : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit FormDoc(QWidget *parent = nullptr);
        ~FormDoc();
    
    private:
        Ui::FormDoc *ui;
    };
    
    #endif // FORMDOC_H
    

    formdoc.cpp

    #include "formdoc.h"
    #include "ui_formdoc.h"
    #include "mainwindow.h"
    
    #include <QVBoxLayout>
    #include <iostream>
    
    FormDoc::FormDoc(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::FormDoc)
    {
        ui->setupUi(this);
    
        QVBoxLayout *Layout = new QVBoxLayout();
        Layout->setContentsMargins(2,2,2,2);
        Layout->setSpacing(2);
        this->setLayout(Layout);
    
        MainWindow *parWind = (MainWindow*)parentWidget(); //获取父窗口指针
        QString ref = parWind->GetTableNumber();           // 获取选中标签索引
        std::cout << ref.toStdString().data() << std::endl;
    }
    
    FormDoc::~FormDoc()
    {
        delete ui;
    }
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    #include "formdoc.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
        QString GetTableNumber();
    
    private slots:
        void on_pushButton_clicked();
    
        void on_tabWidget_tabCloseRequested(int index);
    
        void on_tabWidget_currentChanged(int index);
    
    private:
        Ui::MainWindow *ui;
    };
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <iostream>
    
    MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->tabWidget->setVisible(false);
        ui->tabWidget->clear();//清除所有页面
        ui->tabWidget->tabsClosable(); //Page有关闭按钮,可被关闭
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    // 定义函数来获取当前Table名字
    QString MainWindow::GetTableNumber()
    {
        QString ref = QString(ui->tabWidget->currentIndex());
        return ref;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        FormDoc *ptr = new FormDoc(this);                // 新建选项卡
        ptr->setAttribute(Qt::WA_DeleteOnClose);         // 关闭时自动销毁
    
        int cur = ui->tabWidget->addTab(ptr,QString::asprintf(" 192.168.1.%d",ui->tabWidget->count()));
    
        ui->tabWidget->setTabIcon(cur,QIcon(":/image/1.ico"));
    
        ui->tabWidget->setCurrentIndex(cur);
        ui->tabWidget->setVisible(true);
    }
    
    // 关闭Tab时执行
    void MainWindow::on_tabWidget_tabCloseRequested(int index)
    {
        if (index<0)
            return;
        QWidget* aForm=ui->tabWidget->widget(index);
        aForm->close();
    }
    
    // 在无Tab页面是默认禁用
    void MainWindow::on_tabWidget_currentChanged(int index)
    {
        Q_UNUSED(index);
        bool en=ui->tabWidget->count()>0;
        ui->tabWidget->setVisible(en);
    }
    

    实现美观对话框,前两个对话框只能弹出一次,最后一个对话框可以弹出多次,主要代码如下。

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <iostream>
    
    #include "formmain.h"
    #include "formoption.h"
    #include "formcharts.h"
    
    MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->tabWidget->setVisible(false);
        ui->tabWidget->clear();        //清除所有页面
        ui->tabWidget->tabsClosable(); //Page有关闭按钮,可被关闭
    
        ui->tabWidget->setTabPosition(QTabWidget::North);       // 设置选项卡方位
        ui->tabWidget->setIconSize(QSize(50, 25));              // 设置图标整体大小
        //ui->tabWidget->setTabShape(QTabWidget::Triangular);   // 设置选项卡形状
        ui->tabWidget->setMovable(true);                        // 设置选项卡是否可拖动
        ui->tabWidget->usesScrollButtons();                     // 选项卡滚动
    
        ui->toolBar->setMovable(false);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    // 首页菜单创建
    void MainWindow::on_actionMain_triggered()
    {
        int tab_count = ui->tabWidget->count();
        int option_count = 0;
    
        for(int x=0; x < tab_count; x++)
        {
            // 获取出每个菜单的标题
            QString tab_name = ui->tabWidget->tabText(x);
    
            if(tab_name == "首页菜单")
                option_count = option_count + 1;
        }
    
        if(option_count < 1)
        {
            FormMain *ptr = new FormMain(this);              // 新建选项卡
            ptr->setAttribute(Qt::WA_DeleteOnClose);         // 关闭时自动销毁
    
            int cur=ui->tabWidget->addTab(ptr,QString::asprintf("首页菜单"));
            ui->tabWidget->setTabIcon(cur,QIcon(":/image/1.ico"));
    
            ui->tabWidget->setCurrentIndex(cur);
            ui->tabWidget->setVisible(true);
        }
    }
    
    // 创建系统设置菜单
    void MainWindow::on_actionOption_triggered()
    {
        int tab_count = ui->tabWidget->count();
        int option_count = 0;
    
        for(int x=0; x < tab_count; x++)
        {
            // 获取出每个菜单的标题
            QString tab_name = ui->tabWidget->tabText(x);
    
            if(tab_name == "系统设置")
                option_count = option_count + 1;
        }
    
        // 判断首页菜单是否只有一个,可判断标签个数来识别
        if(option_count < 1)
        {
            FormOption *ptr = new FormOption(this);
            ptr->setAttribute(Qt::WA_DeleteOnClose);
    
            int cur = ui->tabWidget->addTab(ptr,QString::asprintf("系统设置"));
            ui->tabWidget->setTabIcon(cur,QIcon(":/image/2.ico"));
    
            ui->tabWidget->setCurrentIndex(cur);
            ui->tabWidget->setVisible(true);
        }
    }
    
    // 绘图页面的弹出
    void MainWindow::on_actionCharts_triggered()
    {
        FormCharts *ptr = new FormCharts(this);
    
        ptr->setAttribute(Qt::WA_DeleteOnClose);
    
        int cur = ui->tabWidget->addTab(ptr,QString::asprintf("图形绘制"));
        ui->tabWidget->setTabIcon(cur,QIcon(":/image/3.ico"));
    
        ui->tabWidget->setCurrentIndex(cur);
        ui->tabWidget->setVisible(true);
    }
    
    // 关闭TabWiget时
    void MainWindow::on_tabWidget_tabCloseRequested(int index)
    {
        if (index<0)
            return;
        QWidget* aForm=ui->tabWidget->widget(index);
        aForm->close();
    }
    


    版权声明: 本博客,文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!

    警告:如果您恶意转载本人文章,则您的整站文章,将会变为我的原创作品!
  • 相关阅读:
    Docker手动搭建sentry错误日志系统
    Flask源码解析:Flask应用执行流程及原理
    django Rest Framework---缓存通过drf-extensions扩展来实现
    Python实现 -- 冒泡排序、选择排序、插入排序
    Python查找算法之 -- 列表查找和二分查找
    java设计模式之单例模式
    中文乱码解决方案
    web应用中Filter过滤器之开发应用
    web应用中的Filter过滤器之基础概述
    会话跟踪技术
  • 原文地址:https://www.cnblogs.com/LyShark/p/14135453.html
Copyright © 2020-2023  润新知