Weird problem, with MainWindow class variables.



  • So i have two separate classes. MainWindow and my own class. When i try to access MainWindow variables from my own class, i will face up some problem. Either i have method, which returns private variable from MainWindow to my own class or i try to access it when variable is public. Problem is that, the return i get, is very unrealistic. I have two variables in MainWindow class, which ones are equal to two QSlider value.

    Here are defined variables at MainWindow class

    @
    private:
    int imageWidth;
    int imageHeight;
    @

    I have 2 slots, which act, when QSliders values are changed

    @void MainWindow::on_WidthSlider_valueChanged(int value)
    {
    imageWidth = value;
    QString valueString = QString::number(value);
    ui->WidthLabel->setText(valueString);
    }

    void MainWindow::on_HeightSlider_valueChanged(int value)
    {
    imageHeight = value;
    QString valueString = QString::number(value);
    ui->HeightLabel->setText(valueString);
    }@

    Here are two methods, which one should "return" these variable values.

    @
    void MainWindow::GetImageHeight(int &height) {height = imageHeight;}

    void MainWindow::GetImageWidth(int &width) {width = imageWidth; }@

    And here is the part, how i try to access them.

    @
    MainWindow mw;
    int width, height;

    mw.GetImageHeight(height);
    mw.GetImageWidth(width);
    

    @

    PROBLEM is that, i always get wrong results. If MainWindow instance are defined as variable, then methods return 0. If they are defined as pointers, then they return -842150451. I cannot find solution to my problem, i hope someone can help me.



  • Do you connected QSlider::valueChanged(int) signal to your MainWindow::on_WidthSlider_valueChanged(int) and MainWindow::on_HeightSlider_valueChanged(int) slots?



  • Yeah, i also debugged that, is the on_HeightSlider_valueChanged(int) parameter value correct and yes it is.



  • What relations between your own class and MainWindow? May be you could create signals-slots communications between both classes.



  • This is my implementation, for example:

    mainwindow.h
    @class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    signals:
    void heightValueChanged(int value);
    void widthValueChanged(int value);

    private slots:
    void widthSliderChanged(int value);
    void heightSliderChanged(int value);

    private:
    Ui::MainWindow *ui;

    int _imageHeight;
    int _imageWidth;
    

    };@

    mainwindow.cpp
    @MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    _imageHeight(0),
    _imageWidth(0)
    {
    ui->setupUi(this);

    connect(ui->heightlSlider, SIGNAL(valueChanged(int)), this, SLOT(heightSliderChanged(int)));
    connect(ui->widthSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int)));
    

    }

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

    void MainWindow::widthSliderChanged(int value)
    {
    if (_imageWidth == value)
    return;

    _imageWidth = value;
    emit widthValueChanged(_imageWidth);
    

    }

    void MainWindow::heightSliderChanged(int value)
    {
    if (_imageHeight == value)
    return;

    _imageHeight = value;
    emit heightValueChanged(_imageHeight);
    

    }@

    ownclass.h
    @class Own : public QWidget
    {
    Q_OBJECT

    public:
    Own(QWidget *parent = 0);

    public slots:
    void imageHeight(int value);
    void imageWidth(int value);
    };
    @

    ownclass.cpp
    @Own::Own(QWidget *parent) :
    QWidget(parent)
    {

    }

    void Own::imageHeight(int value)
    {
    qDebug() << QString::number(value);
    }

    void Own::imageWidth(int value)
    {
    qDebug() << QString::number(value);
    }@

    main.cpp
    @int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    Own own;

    QObject::connect(&w, SIGNAL(heightValueChanged(int)), &own, SLOT(imageHeight(int)));
    QObject::connect(&w, SIGNAL(widthValueChanged(int)), &own, SLOT(imageWidth(int)));
    
    w.show();
    
    return a.exec&#40;&#41;;
    

    }@



  • QSlider valueChanged are already connected to on_WidthSlider_valueChanged(int value) and on_HeightSlider_valueChanged(int value)



  • I ran into something similar to this recently when trying to update a value by reference. In my case it was done this way for a very different reason but otherwise it was similar to what you are doing.

    I would suggest you re-write your access functions like this:

    @
    int MainWindow::GetImageHeight(void) {return imageHeight;}
    int MainWindow::GetImageWidth(void) {return imageWidth; }
    @

    You can use them like this:

    @
    MainWindow mw;
    int width, height;

    height = mw.GetImageHeight();
    width = mw.GetImageWidth();
    

    @



  • I have already tried this.



  • In your code you have this:

    @
    QApplication a(argc, argv);
    MainWindow w;
    Own own;
    ...
    @

    These exist only in main() which will run until a.exec() returns. For the classes 'w' and 'own' is there a pointer, or some other reference to these classes that you can use outside of main()?

    For this code:

    @
    MainWindow mw;
    int width, height;

        height = mw.GetImageHeight();
        width = mw.GetImageWidth();
    

    @

    GetImageHeight() and GetImageWidth() should return zero or possibly some other random value as it is another, unrelated class.



  • Sorry, i don't understand, what you are trying to say to me.



  • In your example (below), are you trying to get width and height from MainWindow before app.exec() ?
    @
    MainWindow mw;
    int width, height;

        mw.GetImageHeight(height);
        mw.GetImageWidth(width);
    

    @

    If so then MainWindow::imageHeight and imageWidth are not initialized and you are getting whatever random numbers are there.



  • No, im not trying to get them before app.exec()
    getImageHeight and getImageWidth are exectued after i press a button on my form and long proccess is done with network communication is done



  • I post my full source code here

    mainwindow.h
    @
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include "networking.h"
    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:

    explicit MainWindow(QWidget *parent = 0);
    void GetImageHeight(int &height);
    void GetImageWidth(int &width);
    
    ~MainWindow();
    

    private slots:

    void on_pushButton_clicked();
    void on_WidthSlider_valueChanged(int value);
    void on_HeightSlider_valueChanged(int value);
    

    private:
    int imageWidth;
    int imageHeight;

    QUrl q;
    Ui::MainWindow *ui;
    

    };

    #endif // MAINWINDOW_H

    @

    networking.h

    @
    #ifndef NETWORKING_H
    #define NETWORKING_H

    #include <QtNetwork/QNetworkAccessManager>
    #include <QtNetwork/QNetworkRequest>
    #include <QMessageBox>
    #include "mainwindow.h"

    class networking : public QObject
    {
    Q_OBJECT

    public:
        networking();
    
        void on_download_triggered(QUrl url);
        bool IsNetworkAvailable();
    
    
    private:
        QNetworkAccessManager *manager = new QNetworkAccessManager(this);
        void ProcessPicture(QImage *image);
    

    private slots:
    void onNetworkReply(QNetworkReply* reply);

    };

    #endif // NETWORKING_H

    @

    mainwindow.cpp

    @#include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {

    ui->setupUi(this);
    this->setFixedSize(378, 304);
    

    }

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

    void MainWindow::on_pushButton_clicked()
    {

    if(ui->URLbox->text().isEmpty()) QMessageBox::information(0, "Warning", "No URL inserted!");
    
    else
    {
        networking *n = new networking();
        q = ui->URLbox->text();
        if(n->IsNetworkAvailable()) n->on_download_triggered(q);
    }
    

    }

    void MainWindow::GetImageHeight(int &height) {height = imageHeight;}

    void MainWindow::GetImageWidth(int &width) {width = imageWidth; }

    void MainWindow::on_WidthSlider_valueChanged(int value)
    {
    imageWidth = value;
    QString valueString = QString::number(value);
    ui->WidthLabel->setText(valueString);
    }

    void MainWindow::on_HeightSlider_valueChanged(int value)
    {
    imageHeight = value;
    QString valueString = QString::number(value);
    ui->HeightLabel->setText(valueString);
    }

    @

    networking.cpp

    @#include "networking.h"
    #include <QtNetwork/QNetworkReply>
    #include <QFileDialog>

    networking::networking()
    {
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onNetworkReply(QNetworkReply*)));
    }
    void networking::on_download_triggered(QUrl url)
    {
    manager->get(QNetworkRequest(QUrl(url)));
    }

    void networking::ProcessPicture(QImage *image)
    {
    MainWindow *mw = new MainWindow();

    int width, height;
    
    mw->GetImageHeight(height);
    mw->GetImageWidth(width);
    
    
    qDebug() << height;
    qDebug() << width;
    
    QImage newimage = image->scaled(width, height, Qt::KeepAspectRatio);
    QString path =  QFileDialog::getSaveFileName(0, tr("Save Image"), "C://", tr("Image Files (*.png *.jpg *.bmp)"));
    
    newimage.save(path);
    

    }

    void networking::onNetworkReply(QNetworkReply* reply)
    {
    if(!reply->error())
    {
    QImage *img = new QImage();
    img->loadFromData(reply->readAll());

        if(img->isNull())
                QMessageBox::critical(0, "Error", "Inserted URL is not an image!");
    
        ProcessPicture(img);
    
    }
    else
    {
        QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
        int status = statusCode.toInt();
    
        qDebug() << status;
    
        switch(status)
        {
            case 0:
            {
                QMessageBox::critical(0, "Error", "URL doesn't exist!");
                break;
            }
            case 404:
            {
                QMessageBox::critical(0, "Error", "404 not found!");
                break;
            }
        }
    }
    

    }

    bool networking::IsNetworkAvailable()
    {
    QNetworkAccessManager m;
    QNetworkReply *check = m.get(QNetworkRequest(QUrl("google.com")));
    return (!check->error()) ? true : false;
    }
    @



  • I think this is your problem:

    @
    void networking::ProcessPicture(QImage *image)
    {
    MainWindow *mw = new MainWindow();

    int width, height;
    
    mw->GetImageHeight(height);
    mw->GetImageWidth(width);
    
    qDebug() << height;
    qDebug() << width;
    

    ...
    }
    @

    The class '*mw' is unrelated to the mw class created in main(). The member imageWidth and imageHeight are not updated in this version.

    To verify this you could create a global pointer of the MainWindow class and see if this solves the problem:

    @
    MainWindow *g_mw;

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        Own own;
    
        g_mw = &mw;
    
     
        QObject::connect(&w, SIGNAL(heightValueChanged(int)), &own, SLOT(imageHeight(int)));
        QObject::connect(&w, SIGNAL(widthValueChanged(int)), &own, SLOT(imageWidth(int)));
     
        w.show();
     
        return a.exec&#40;&#41;;
    }
    

    @

    and then in your network module

    @
    #include "networking.h"
    #include <QtNetwork/QNetworkReply>
    #include <QFileDialog>

    extern MainWindow *g_mw;

    networking::networking()
    {
    ...
    }
    ...
    void networking::ProcessPicture(QImage *image)
    {
    // MainWindow *mw = new MainWindow();

    int width, height;
    
    g_mw->GetImageHeight(height);
    g_mw->GetImageWidth(width);
    
    
    qDebug() << height;
    qDebug() << width;
    

    ...
    }
    @

    Note: I wouldn't use a global variable like this. You are better to pass a pointer (maybe as part of the constructor of your Networking class?). It is just a simple way to verify this is the problem without changing too much.



  • Rondog is right. You are creating new MainWindow object and it is not related to your main MainWindow.

    Another option to solve it would be to pass a MainWindow pointer to networking ctor and keep it there. Then in networking::ProcessPicture() use that pointer.
    networking.h

    @
    #ifndef NETWORKING_H
    #define NETWORKING_H

    class MainWindow;
     
    class networking : public QObject
    {
    

    ...
    public:
    networking(MainWindow* mw);

    ...
    private:
    MainWindow* m_mw;

    };
    #endif // NETWORKING_H
    

    @

    networking.cpp
    @
    #include "networking.h"
    #include "MainWindow.h"
    #include <QtNetwork/QNetworkReply>
    #include <QFileDialog>

    networking::networking(MainWindow* mw) : m_mw(mw)
    {
    

    ...
    }

    void networking::ProcessPicture(QImage *image)
    {
    // MainWindow *mw = new MainWindow();

    int width, height;
    
    m_mw->GetImageHeight(height);
    m_mw->GetImageWidth(width);
    
    
    qDebug() << height;
    qDebug() << width;
    

    ...
    }
    @



  • Thanks, it worked! I didn't know, why i didn't realise fault myself. Quite logical. Thanks again!



  • One last question, why i had to write class MainWindow; to my networking.h file.



  • It is a forward declaration. Compiler needs to know that a type exists but does not need to know the details. It works with the pointers and the references. Helps to avoid including unneeded headers.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.