美文网首页
Qt主界面获取对话框数据

Qt主界面获取对话框数据

作者: knightaoko | 来源:发表于2017-03-21 12:00 被阅读0次

    在编写Qt程序的时候,我们常常需要通过对话框来获取用户的输入数据,比如通过文件对话框获取文件的路径,通过颜色对话框获取用户所选择的颜色,这些对话框的类都是Qt帮我们写好了的,调用相应函数就能直接返回用户的输入,比如颜色对话框QColorDialog中有一个静态函数getColor,我们直接调用该函数,便会弹出颜色对话框,等我们选择好颜色并确定,该函数就会返回一个QColor的对象,这个对象就包含了我们之前所选颜色的RGB值了。

    然而,很多时候,我们需要创建自己的对话框,我们不能调用现成函数来获取用户输入,本文将提供两种方法,通过对话框来获取用户输入的案例。在此之前,我们先讨论一下显示对话框的两个函数,一个是show(),一个是exec()。show() 显示的是非模态窗口,不会阻塞程序的线程,因此如果你的对话框是创建在栈上,跳出作用域之后,对象便销毁了,因此你会发现对话框一闪而过;如果你用new关键字将对话框创建在堆上,跳出作用域之后对象不能被销毁,但是建立在堆上需要考虑及时释放内存的问题,以免造成内存泄漏。但是能够正常显示窗口不代表能够很方便地获取数据,show()不会阻塞线程,因此可能用户还没来得及输入数据,就已经执行之后的代码了。解决这个问题需要用到信号槽机制,具体解决方案会在下文详细讲解。exec()显示的是模态窗口,它开启了一个事件循环,会阻塞程序的线程,函数返回之后,我们直接可以获取对话框的数据。下面考虑这两种不同的对话框显示方式,提供两种不同的获取对话框数据的方法。

    方法一

    首先考虑简单的,使用exec()显示对话框。我们定义了一个主界面的类,叫MainWindow,界面包含一个名为btn的按钮(用于跳出对话框)和一个名为label的标签(用于显示从对话框获取的用户输入);我们还定义一个对话框类,界面包含一个名为lineEdit的单行文本框(用于接收用户输入),以及确定和取消按钮(这两个按钮是创建对话框的时候自动生成的)。两个界面如下图:

    主界面 对话框界面

    关键代码如下:

    //in mainwindow.h
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    private:
        Ui::MainWindow *ui;
        void showDialog();
    };
    
    //in mainwindow.cpp
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        //“显示对话框”按钮与显示函数建立信号槽关系
        connect(ui->btn, &QPushButton::clicked, this, &MainWindow::showDialog);
    }
    MainWindow::~MainWindow(){delete ui;}
    void MainWindow::showDialog()
    {
        Dialog dialog;
        dialog.exec();
        ui->label->setText(dialog.getinput());
    }
    
    
    //in dialog.h
    class Dialog : public QDialog
    {
        Q_OBJECT
    public:
        explicit Dialog(QWidget *parent = 0);
        ~Dialog();
        QString getinput();
    private:
        Ui::Dialog *ui;
    };
    
    //in dialog.cpp
    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
        ui->setupUi(this);
    }
    Dialog::~Dialog(){delete ui;}
    QString Dialog::getinput()
    {
        QString s = ui->lineEdit->text();
        return s;
    }
    
    

    代码说明:上面的程序还是比较容易理解的,在mainwindow.h和mainwindow.cpp里,先将btn与showDialog建立联系,在showDialog内部创建Dialog对象,并通过exec()显示,由于exec()会阻碍线程,因此待用户输入数据之后再执行后续获取数据的代码,由于我们想获取的dialog内的数据是私有的,因此在Dialog类定义了一个public的getinput()函数(之前还考虑用友元,感觉被自己蠢哭了),间接获取用户的输入,最后将数据显示在主界面的label上面,达到主界面获取对话框数据的目的。
    附:方法一源代码

    方法二:

    上面讨论的是用exec()显示对话框的情况下获取用户输入数据,那如果用show()显示对话框,该如何获取数据呢?由于show()不会开启事件循环,因此如果继续按上面的方法,用户根本来不及输入数据,后续的代码就已经执行了,因此需要用到信号槽机制。思路是这样的:按下对话框的确定按钮后,程序会自动调用QDialog::accept()函数,因此如果我们可以重载accept()函数,在其中发送信号,关联该信号的槽便会响应,我们在槽里面进行数据数据接收。
    关键代码如下:

    //in mainwindow.h
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    private:
        Ui::MainWindow *ui;
        void showDialog();
        void displayData(QString data);
        void accept();
    };
    
    //in mainwindow.cpp
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        connect(ui->btn, &QPushButton::clicked, this, &MainWindow::showDialog);
    }
    MainWindow::~MainWindow(){delete ui;}
    void MainWindow::showDialog()
    {
        Dialog *dialog = new Dialog(this);
        connect(dialog, &Dialog::receiveData, this, &MainWindow::displayData);
        dialog->show();
    }
    void MainWindow::displayData(QString data)
    {
        ui->label->setText(data);
    }
    
    //in dialog.h
    class Dialog : public QDialog
    {
        Q_OBJECT
    public:
        explicit Dialog(QWidget *parent = 0);
        ~Dialog();
    signals:
        void receiveData(QString s);
    private:
        Ui::Dialog *ui;
        void accept();
    };
    
    //in dialog.cpp
    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
        ui->setupUi(this);
    }
    Dialog::~Dialog(){delete ui;}
    void Dialog::accept() //重载accept()
    {
        QString data = ui->lineEdit->text();
        emit receiveData(data);  //发送信号给mainwindow
        QDialog::accept();
    }
    

    代码说明:用户输入数据后,按下确定按钮,程序会自动调用accept(),因此重载了accept()函数,让其将获取的输入数据作为信号(receiveData是一个信号)通过emit发送给主界面,在mainwindow.cpp,我们信号receiveData和槽displayData进行关联,displayData将接收的数据显示在主界面的label上的。总的来说,数据输入后,先调用accept(),accept()将信号(信号上带有数据)发送给displayData,displayData显示数据。通过信号槽机制,我们看到,即使对话框作为非模态窗口显示,即使其稍纵即逝,我们还是能通过特定手段获取用户的输入。
    附:方法二源代码

    运行结果:

    运行结果

    相关文章

      网友评论

          本文标题:Qt主界面获取对话框数据

          本文链接:https://www.haomeiwen.com/subject/lfzwnttx.html