我正在使用QT的抵押贷款计算器。 当用户点击按钮时,“on_pushButton_clicked()”函数将获得输入。
问题是我很困惑如何将输入从“on_pushButton_clicked()”传递到“paintGL()”函数以用于绘图目的。
我的最后一种方法是使用全局变量来解决这个问题,但我真的想避免这样的事情...所以如果有人可以用更好的方法启发,那将非常受欢迎。
我的代码如下:
mainwindow.h
#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
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();
}
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
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)
{
}
感谢您的帮助:)
答案 0 :(得分:0)
惯用方法是使窗口小部件成为值的显示,其中值是窗口小部件的属性。这就是所有Qt控件的工作方式,例如: QLabel
可以显示一些文字,并且具有您使用text
设置的setText
属性。一旦用新文本调用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();
}
如果您希望更容易传递数据,可以将所有属性捆绑在代表贷款的数据类型中:
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成本很低,因为它返回对内部数据的const引用,而不是副本。
然后:
void MainWindow::on_pushButton_Calculate_clicked()
{
Loan loan;
loan.principal = inputcheck(ui->lineEdit_loan, loan);
loan.amortizationPeriod = inputcheck(ui->lineEdit_maturity, maturity);
...
ui->dataView->setLoan(loan);
...
}
如果您希望动态地将dataView
显示为新的顶级窗口:
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();
}
您还可以将数据视图与MainWindow
完全分离,并通过信号传递数据:
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();
}
答案 1 :(得分:0)
移动GLwidget类中的变量。在这里我假设他们被宣布为公开,但你可能想要使用setter和getter。然后,调用update来刷新小部件。
void MainWindow::on_pushButton_Calculate_clicked()
{
ui->myglwidgetname->loan = inputcheck<double>(ui->lineEdit_loan);
ui->myglwidgetname->maturity = inputcheck<int>(ui->lineEdit_maturity);
ui->myglwidgetname->rate1 = inputcheck<double>(ui->lineEdit_rate1);
ui->myglwidgetname->rate2 = inputcheck<double>(ui->lineEdit_rate2);
ui->myglwidgetname->rate3 = inputcheck<double>(ui->lineEdit_rate3);
ui->myglwidgetname->period2 = inputcheck<int>(ui->lineEdit_period2);
ui->myglwidgetname->period3 = inputcheck<int>(ui->lineEdit_period3);
ui->myglwidgetname->update();
}
另外,你想纠正你的模板化函数,因为它调用toDouble
而不管T类型根本没有意义......
答案 2 :(得分:-1)
这可以通过使用一些常见的面向对象的想法来解决,即具有setter函数的成员变量。在QGLWidget的子类(glwidget.h)中添加一些成员变量。
private:
int m_my_int_value;
double m_my_double_value;
然后,您还需要为这些值设置一些setter函数(也在glwidget.h中)。
public:
void Set_my_int_value(int val);
void Set_my_double_value(double val);
您可以将这些函数的声明放在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的实现中访问这些值。
答案 3 :(得分:-1)
你可以使用qt的Signal / Slot mechanizm。
使用输入中的所需字段创建自己的结构。您可以将其作为指针传递信号。
添加到mainwindow.h
signals:
void MySignal(MyStruct*);
在cpp:
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);
MyStruct* struct = new MyStruct();
... //add data to mystruct
emit MySignal(struct);
}
有这样的功能: 公共位置: void saveData(MyStruct * param); //正文应保存您喜欢的数据
在main.cpp中,你可以创建两个主要的小部件,就像这样。
MainWindow mainW();
GLWidget glW();
connect(&mainW, SIGNAL( MySignal(MyStruct*)), &glW, SLOT(saveData(MyStruct*)));
边缘有点粗糙,但我希望你能得到基本的想法。如果没有,请查看Signal / Slot mechanizm上的Qt文档。