C++ Qt:如何将输入值从点击按钮传递到paintGL()函数

C++ Qt:如何将输入值从点击按钮传递到paintGL()函数,c++,qt,C++,Qt,我正在使用QT开发抵押贷款计算器。 当用户单击按钮时,“on_button_clicked()”函数将获得输入 问题是,我不知道如何将输入从“on_putton_clicked()”传递到“paintGL()”函数以用于绘图 我最后的办法是使用全局变量来解决这个问题,但我真的想避免这样的事情……因此,如果有人能用更好的方法来启发,那将是非常受欢迎的 我的代码如下: 主窗口 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainW

我正在使用QT开发抵押贷款计算器。 当用户单击按钮时,“on_button_clicked()”函数将获得输入

问题是,我不知道如何将输入从“on_putton_clicked()”传递到“paintGL()”函数以用于绘图

我最后的办法是使用全局变量来解决这个问题,但我真的想避免这样的事情……因此,如果有人能用更好的方法来启发,那将是非常受欢迎的

我的代码如下:

主窗口

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "ui_mainwindow.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:

    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    template <class T>
    T inputcheck(QLineEdit *input, T output);
    //friend class GLwidget;
    double loan;
    int maturity;
    double rate1;
    double rate2;
    double rate3;
    int period2;
    int period3;    

private slots:
    void on_pushButton_Calculate_clicked();

    void on_pushButton_Quit_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
signals:
    void MySignal(MyStruct*);
\ifndef主窗口
#定义主窗口
#包括
#包括“ui_main window.h”
名称空间用户界面{
类主窗口;
}
类主窗口:公共QMainWindow
{
Q_对象
公众:
显式主窗口(QWidget*parent=0);
~main窗口();
样板
T输入检查(QLineEdit*输入,T输出);
//朋友类小部件;
双重贷款;
智力成熟度;
双费率1;
双费率2;
双费率3;
int周期2;
int周期3;
专用插槽:
单击按钮计算时无效();
单击按钮退出时无效();
私人:
Ui::MainWindow*Ui;
};
#endif//main窗口
mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCoreApplication>
#include <QDesktopWidget>
#include "glwidget.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

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

template <class T>
T MainWindow::inputcheck(QLineEdit *input, T output) 
{
    bool ok;
    output = input->text().toDouble(&ok);
    if(TRUE && output > 0)
    {
        return output;
    }
    else
    {
        input->setText("ERR");
        return 0;
    }
}

void MainWindow::on_pushButton_Calculate_clicked()
{

    // getting inputs()
    loan = inputcheck(ui->lineEdit_loan, loan);
    maturity = inputcheck(ui->lineEdit_maturity, maturity);
    rate1 = inputcheck(ui->lineEdit_rate1, rate1);
    rate2 = inputcheck(ui->lineEdit_rate2, rate2);
    rate3 = inputcheck(ui->lineEdit_rate3, rate3);
    period2 = inputcheck(ui->lineEdit_period2, period2);
    period3 = inputcheck(ui->lineEdit_period3, period3);
    printf("loan:%f, maturity:%d,rate1:%f,rate2:%f,rate3:%f, period2:%d, period3:%d\n", loan, maturity, rate1, rate2, rate3, period2, period3);      

}

void MainWindow::on_pushButton_Quit_clicked()
{
    QCoreApplication::quit();

}
#包括“mainwindow.h”
#包括“ui_main window.h”
#包括
#包括
#包括“glwidget.h”
主窗口::主窗口(QWidget*父窗口):
QMainWindow(父级),
用户界面(新用户界面::主窗口)
{
用户界面->设置用户界面(此);
}
MainWindow::~MainWindow()
{
删除用户界面;
}
样板
T MainWindow::inputcheck(QLineEdit*输入,T输出)
{
布尔ok;
输出=输入->文本();
if(TRUE&&output>0)
{
返回输出;
}
其他的
{
输入->设置文本(“错误”);
返回0;
}
}
void主窗口::在按钮上单击计算()
{
//获取输入()
loan=输入检查(ui->lineEdit\u loan,loan);
到期日=输入检查(ui->lineEdit\u到期日,到期日);
rate1=输入检查(ui->lineEdit\u rate1,rate1);
rate2=输入检查(ui->lineEdit_rate2,rate2);
rate3=输入检查(ui->lineEdit_rate3,rate3);
period2=输入检查(ui->lineEdit\u period2,period2);
period3=输入检查(ui->lineEdit\u period3,period3);
printf(“贷款:%f,到期日:%d,利率1:%f,利率2:%f,利率3:%f,周期2:%d,周期3:%d\n”,贷款,到期日,利率1,利率2,利率3,周期2,周期3);
}
void主窗口::按按钮退出
{
QCoreApplication::quit();
}
glwidget.h

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QObject>
#include <QGLWidget>


class calculation;
class GLwidget : public QGLWidget
{
    Q_OBJECT
public:
    explicit GLwidget(QWidget *parent = 0);
    void initializeGL();
    void paintGL();
    void resizeGL(int width, int height);

private:

};

#endif // GLWIDGET_H
\ifndef GLWIDGET\u H
#定义glu\H
#包括
#包括
班级计算;
类GLwidget:publicqglwidget
{
Q_对象
公众:
显式GLwidget(QWidget*parent=0);
void initializeGL();
void paintGL();
空隙大小(内部宽度、内部高度);
私人:
};
#endif//glu\H
glwidget.cpp

#include "glwidget.h"
#include <gl/GL.h>


GLwidget::GLwidget(QWidget *parent):QGLWidget(parent)
{
}

void GLwidget::initializeGL()
{
}

void GLwidget::paintGL()
{
**// I need the inputs to be here!!**
}

void GLwidget::resizeGL(int width, int height)
{
}
#包括“glwidget.h”
#包括
GLwidget::GLwidget(QWidget*父项):QGLWidget(父项)
{
}
void GLwidget::initializeGL()
{
}
void GLwidget::paintGL()
{
**//我需要输入到这里**
}
void GLwidget::resizeGL(整数宽度、整数高度)
{
}

感谢您的帮助:)

这可以通过使用一些常见的面向对象思想来解决,即带有setter函数的成员变量。在QGLWidget(glwidget.h)的子类中添加一些成员变量

private:
  int m_my_int_value;
  double m_my_double_value;
然后,您还需要一些用于这些值的setter函数(也在glwidget.h中)

您可以将这些函数的声明放在glwidget.cpp中

void GLwidget::Set_my_int_value(int val)
{
  if(val != m_my_int_value)
  {
    m_my_int_value = val;
    update();
  }
}

void GLwidget::Set_my_double_value(double val)
{
  if(val != m_my_double_value)
  {
    m_my_double_value = val;
    update();
  }
}

在on_click函数中调用这些setter函数。这些值将在您的paintGL实现中被访问。

这可以通过使用一些常见的面向对象思想来解决,即带有setter函数的成员变量。在QGLWidget(glwidget.h)的子类中添加一些成员变量

private:
  int m_my_int_value;
  double m_my_double_value;
然后,您还需要一些用于这些值的setter函数(也在glwidget.h中)

您可以将这些函数的声明放在glwidget.cpp中

void GLwidget::Set_my_int_value(int val)
{
  if(val != m_my_int_value)
  {
    m_my_int_value = val;
    update();
  }
}

void GLwidget::Set_my_double_value(double val)
{
  if(val != m_my_double_value)
  {
    m_my_double_value = val;
    update();
  }
}

在on_click函数中调用这些setter函数。这些值将在您的paintGL实现中被访问。

惯用的方法是使小部件成为值的显示,值是小部件的属性。这就是所有Qt控件的工作方式,例如
QLabel
可以显示一些文本,并且具有使用
setText
设置的
text
属性。一旦用新文本调用了
setText
,标签就会知道如何自我更新。因此:

class DataView : public QOpenGLWidget
{
  Q_OBJECT
  Q_PROPERTY(double principal READ principal WRITE setPrincipal)
  Q_PROPERTY(int amortizationPeriod READ amortizationPeriod WRITE setAmortizationPeriod)
  ...
  double m_principal = {};
  int m_amortizationPeriod = {};
public:
  explicit GLwidget(QWidget *parent = {}) : QOpenGLWidget(parent) {}
  void initializeGL() override;
  void paintGL() override;
  void resizeGL(int w, int h) override;
  double principal() const { return m_principal; }
  void setPrincipal(double principal) {
    if (m_principal == principal) return;
    m_principal = principal;
    update();
  }
  int amortizationPeriod() const { return m_amortizationPeriod; }
  void setAmortizationPeriod(int period) {
    if (m_amortizationPeriod == period) return;
    m_amortizationPeriod = period;
    update();
  }
  ...
};
update()
计划从事件循环重新绘制。更新请求被合并,因此在一行中设置多个属性只会对小部件绘制一次

因此,假设您将
dataView
作为Ui表单的一个元素:

void MainWindow::on_pushButton_Calculate_clicked()
{
    auto principal = inputcheck(ui->lineEdit_loan, loan);
    auto amortizationPeriod = inputcheck(ui->lineEdit_maturity, maturity);
    ...
    ui->dataView->setPrincipal(principal);
    ui->dataView->setAmortizationPeriod(amortizationPeriod);
    ...
}
也许您希望动态地将
dataView
显示为一个新的顶级窗口:

void MainWindow::on_pushButton_Calculate_clicked()
{
    auto principal = inputcheck(ui->lineEdit_loan, loan);
    auto amortizationPeriod = inputcheck(ui->lineEdit_maturity, maturity);
    ...
    auto dataView = new DataView(this);
    dataView->setWindowFlags(dataWidget->windowFlags() | Qt::Window);
    dataView->setPrincipal(principal);
    dataView->setAmortizationPeriod(amortizationPeriod);
    ...
    dataView->show();
}
void MainWindow::on_pushButton_Calculate_clicked()
{
    Loan loan;
    loan.principal = inputcheck(ui->lineEdit_loan, loan);
    loan.amortizationPeriod = inputcheck(ui->lineEdit_maturity, maturity);
    ...
    auto dataView = new DataView(this);
    dataView->setWindowFlags(dataView->windowFlags() | Qt::Window);
    dataView->setLoan(loan);
    dataView->show();
}
如果希望更方便地传递数据,可以将所有属性绑定到表示贷款的数据类型中:

struct Loan {
  double principal = {};
  int amortizationPeriod = {};
  ...
  bool operator==(const Loan & o) const {
    return 
      qFuzzyCompare(principal, o.principal)
      && amortizationPeriod == o.amortizationPeriod
      && ...;
    // use qFuzzyCompare when comparing floating point values
  }
};
Q_DECLARE_METATYPE(Loan)

class DataView : public QOpenGLWidget
{
  Q_OBJECT
  Q_PROPERTY(Loan loan READ loan WRITE setLoan)
  Loan m_loan;
public:
  explicit GLwidget(QWidget *parent = {}) : QOpenGLWidget(parent) {}
  void initializeGL() override;
  void paintGL() override;
  void resizeGL(int w, int h) override;
  const Loan & loan() const { return m_loan; }
  Loan getLoan() const { return m_loan; }
  void setLoan(const Loan & loan) {
     if (m_loan == loan) return;
     m_loan = loan;
     update();
  }
};
方便时,可以使用
getLoan
获取贷款的可修改副本。通常的
loan
getter成本较低,因为它返回对内部数据的常量引用,而不是副本

然后:

如果您希望将
数据视图
动态显示为新的顶级窗口:

void MainWindow::on_pushButton_Calculate_clicked()
{
    auto principal = inputcheck(ui->lineEdit_loan, loan);
    auto amortizationPeriod = inputcheck(ui->lineEdit_maturity, maturity);
    ...
    auto dataView = new DataView(this);
    dataView->setWindowFlags(dataWidget->windowFlags() | Qt::Window);
    dataView->setPrincipal(principal);
    dataView->setAmortizationPeriod(amortizationPeriod);
    ...
    dataView->show();
}
void MainWindow::on_pushButton_Calculate_clicked()
{
    Loan loan;
    loan.principal = inputcheck(ui->lineEdit_loan, loan);
    loan.amortizationPeriod = inputcheck(ui->lineEdit_maturity, maturity);
    ...
    auto dataView = new DataView(this);
    dataView->setWindowFlags(dataView->windowFlags() | Qt::Window);
    dataView->setLoan(loan);
    dataView->show();
}
您还可以将数据视图与
main窗口完全解耦,并通过信号将数据传递出去:

class MainWindow : public QMainWindow {
  ...
public:
  Q_SLOT newLoan(const Loan &);
  ...
};

void MainWindow::on_pushButton_Calculate_clicked()
{
    Loan loan;
    loan.principal = inputcheck(ui->lineEdit_loan, loan);
    loan.amortizationPeriod = inputcheck(ui->lineEdit_maturity, maturity);
    ...
    emit newLoan(loan);
}

int main(int argc, char ** argv) {
  QApplication app(argc, argv);
  MainWindow mainWindow;
  DataView dataView;
  QObject::connect(&mainWindow, &MainWindow::newLoan, [&](const Loan & loan){
    dataView.setLoan(loan);
    dataView.show();
  });
  mainWindow.show();
  return app.exec();
}
如果数据视图始终可见,您将有:

int main(int argc, char ** argv) {
  QApplication app(argc, argv);
  MainWindow mainWindow;
  DataView dataView;
  QObject::connect(&mainWindow, &MainWindow::newLoan, &dataView, &DataView::setLoan);
  mainWindow.show();
  dataView.show();
  return app.exec();
}

惯用的方法是使小部件成为值的显示,值是小部件的属性。这就是所有Qt控件的工作方式,例如
QLabel
可以显示一些文本,并且具有使用
setText
设置的
text
属性。一旦用新文本调用了
setText
,标签就会知道如何自我更新。因此:

class DataView : public QOpenGLWidget
{
  Q_OBJECT
  Q_PROPERTY(double principal READ principal WRITE setPrincipal)
  Q_PROPERTY(int amortizationPeriod READ amortizationPeriod WRITE setAmortizationPeriod)
  ...
  double m_principal = {};
  int m_amortizationPeriod = {};
public:
  explicit GLwidget(QWidget *parent = {}) : QOpenGLWidget(parent) {}
  void initializeGL() override;
  void paintGL() override;
  void resizeGL(int w, int h) override;
  double principal() const { return m_principal; }
  void setPrincipal(double principal) {
    if (m_principal == principal) return;
    m_principal = principal;
    update();
  }
  int amortizationPeriod() const { return m_amortizationPeriod; }
  void setAmortizationPeriod(int period) {
    if (m_amortizationPeriod == period) return;
    m_amortizationPeriod = period;
    update();
  }
  ...
};
update()
计划从事件循环重新绘制。更新请求被合并,thu