Access widgets in QMainWindow from another class - c++

Although it is a frequently asked question, and I've tried many ways including those from SO, like Trying to access widgets of MainWindow from another class, However I still cannot work out a solution, below is my code which reported error "Unknown type name 'CustomClass'" in mainwindow.h:
Thanks in advance for any help!
customclass.h
#ifndef CUSTOMCLASS_H
#define CUSTOMCLASS_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
class MainWindow;
class CustomClass
{
public:
CustomClass(MainWindow *parent);
MainWindow * mainWindow;
void testFunc();
};
#endif // CUSTOMCLASS_H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "customclass.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
Ui::MainWindow *ui;
CustomClass *customClass = new CustomClass(this);
};
#endif // MAINWINDOW_H
customclass.cpp
#include "customclass.h"
CustomClass::CustomClass(MainWindow *parent)
{
this->mainWindow = parent;
}
void CustomClass::testFunc()
{
mainWindow->ui->label->setText("Hello World!");
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
customClass->testFunc();
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

please read about Circular Dependencies in C++ .
you have problems because you create a loop, you included #include "customclass.h" in MainWindow class and also #include "mainwindow.h" in CustomClass .
it's better that you don't use MainWindow in other classes and add CustomClass objects in MainWindow. The idea is that MainWindow is your root window class and we create one object from it in main.cpp you can do what you ask but logically it's not good.
as we can see in QMainWindow Class document.
The QMainWindow class provides a main application window
A main window provides a framework for building an application's user
interface.
This is your base, you should add the feature you want inside this class not add it in other widgets.
It's the main class for other widgets. This is a clean way to code and if you look at big projects in GitHub you will see this.

move #include "mainwindow.h" and #include "ui_mainwindow.h" inside customclass.h into customclass.cpp before #include "customclass.h" and it works! Thank you!#drescherjm
The fixed code is shown below:
customclass.h
#ifndef CUSTOMCLASS_H
#define CUSTOMCLASS_H
class MainWindow;
class CustomClass
{
public:
CustomClass(MainWindow *parent);
~CustomClass();
MainWindow *mainWindow;
void testFunc();
};
#endif // CUSTOMCLASS_H
customclass.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"//Move these two lines from the header to here
#include "customclass.h"
CustomClass::CustomClass(MainWindow *parent)
{
this->mainWindow = parent;
}
CustomClass::~CustomClass()
{
}
void CustomClass::testFunc()
{
mainWindow->ui->label->setText("Hello World!");
}

Related

Downloading txt file with qtnetwork

I am trying to download a txt file from a url in QT but i can't seem to make it work.
I am following this guide https://wiki.qt.io/Download_Data_from_URL. I implemented the filedownloader class exactly like it's made in the guide, but when i try to use it like specified in the guide I cannot make it work. I created a slot to be called when the download is finished, but if i try to call the downloader inside like the guide it says it is an undeclared identifier.
Does anyone know how to correctly implement this code?
this is the .cpp of my code
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mainwindow.h"
#include <QStringList>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QList>
#include <QtNetwork/QNetworkReply>
#include <QStringList>
#include <QTimer>
#include <QUrl>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <filedownloader.h>
#include <iostream>
#include <QObject>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QUrl emiurl( "url of my file");
// call to the downloader class.In the guide it's made differently, but it doesn't work
FileDownloader emiload(emiurl,this);
//this connect links the end of the download with the textwriter slot
QObject::connect(&emiload, SIGNAL (downloaded()), this, SLOT (textwriter()));
}
>MainWindow::~MainWindow()
{
delete ui;
}
//slot needed to create the txt file from the downloaded one
void MainWindow::textwriter()
{
QByteArray emibyte;
emibyte=emiload->downloadedData(); //this line gives me error
QFile emifile("emi.txt");
emifile.open(QIODevice::WriteOnly);
std::cout << emibyte.size() << std::endl;
QDataStream out(&emifile);
out << emibyte;
std::cout << emifile.size() << std::endl;
}
Now here's the .h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "filedownloader.h"
#include <QMainWindow>
#include <QtNetwork/QNetworkAccessManager>
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;
private slots:
void textwriter();
};
#endif // MAINWINDOW_H
To make the undeclared identifier go away and successfully compile, you need to add FileDownloader to the class' declaration. This way, it will be known throughout the class.
I chose to go with the approach that's usual in Qt, to declare a pointer to FileDownloader.
#pragma once // <--- this is supported by virtually any compiler today
#include <QMainWindow>
#include <QtNetwork/QNetworkAccessManager>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class FileDownloader; // <-- forward declaration is enough, but you can also #include "filedownloader.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
~MainWindow();
private:
Ui::MainWindow* ui = nullptr;
FileDownloader* emiload = nullptr; // <--- the important line!
private slots:
void textwriter();
};
And then instantiate and call emiload in the constructor:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// create an instance of FileDownloader with "new".
emiload = new FileDownloader(QUrl("url of my file"), this);
// using member pointer connection available since Qt5
connect(emiload, &FileDownloader::downloaded, this, &MainWindow::textwriter);
}

How to connect a button from ui-file class to slots from other classes?

I have 3 classes.
class with a mainwindow which comes from the designer(ui-file)
class wich will manage database stuff like inserts
controller class. I want to extend the whole thing to networkcommunication later.
My problem:
I want to connect a simple QPushButton ui->addbutton from the window class with a slot addEntry from the databaseclass, but I get this error :
ERROR: no matching function for call to
'generalControler::connect(QPushButton*, const char*, dbmanager*&,
const char*)'
mydb, SLOT(addEntry()));
//no difference with &mydb or *mydb
MainWindow(0x13f57988, name = "MainWindow") QPushButton(0x13f5f3e0, name = "addButton")
MainWindow(0x13f57988, name = "MainWindow") 0x13f5f3e0//<--?????
//<=Here u see the adresses printed with Qdebug(). top: mainwindowclass. bot: generalcontrolerclass
//why there is missing information after returning the adress of a 'ui->addButton' to another class? Is this maybe the problem?
main.cpp
#include <QApplication>
#include "generalcontroler.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
generalControler controler;
return a.exec();
}
generalcontroler.h
#ifndef GENERALCONTROLER_H
#define GENERALCONTROLER_H
#include <QApplication>
#include "mainwindow.h"
#include "dbmanager.h"
class generalControler : public QObject
{
Q_OBJECT
public:
generalControler();
};
#endif // GENERALCONTROLER_H
generalcontroler.cpp
#include "generalcontroler.h"
#include <QDebug>
generalControler::generalControler(){
MainWindow* window = new MainWindow;
window->show();
dbmanager* mydb= new dbmanager("path_to_my_database.db", window);
mydb->addEntry();
qDebug()<<window->getThis()<<window->getcloseButton();
connect(window->getaddButton(), SIGNAL(clicked()),
mydb, SLOT(addEntry()));
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QPushButton* getaddButton();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){
ui->setupUi(this);
}
QPushButton* MainWindow::getaddButton()
{
return ui->addButton;
}
dbmanager.h
#ifndef DBMANAGER_H
#define DBMANAGER_H
#include <QSqlDatabase>
#include <QDebug>
#include "mainwindow.h"
class dbmanager: public QObject{
Q_OBJECT
public:
dbmanager(const QString& path);
public slots:
void addEntry();
private:
QSqlDatabase mydatabase;
};
#endif // DBMANAGER_H
dbmanager.cpp
#include "dbmanager.h"
dbmanager::dbmanager(const QString& path)
{
mydatabase = QSqlDatabase::addDatabase("QSQLITE");
mydatabase.setDatabaseName(path);
if (!mydatabase.open())
{
qDebug() << "Error: connection fail";
}
else
{
qDebug() << "Database: connection ok";
}
}
void dbmanager::addEntry()
{
qDebug()<<"addEntry success";
}
I was searching for 6 hours but I never saw such an example with 2 classes, a controler and an ui-file. Could anyone help me?
The connect looks good to me. Try if #include <QPushButton> in generalcontroler.cpp helps. If the compiler knows about QPushButton only by forward-declaration, it doesn't know that it's a QObject and thus the connect() signatures (with QObject* in it) don't match.

How to set an Image on QLabel from other form in Qt

Before taking up the main subject, please mind that i`m a beginner of Qt.
I made a AddIm.cpp, and I want to set an image on QLabel in MainWindow.
here is my source in AddIm.cpp
void AddIm::on_pushButton_clicked()
{
MainWindow mainwindow;
mainwindow.setImage();
}
and here is MainWindow.cpp
void MainWindow::setImage()
{
QPixmap pix("./test.jpg");
ui->label->setPixmap(pix);
}
and MainWindow.h
class MainWindow : public QMainWindow
{
public:
void setImage();
~ some source ~
private:
Ui::MainWindow *ui;
};
it doesn't work at all. so I added a button in MainWindow for testing.
and when it clicked, setImage works. but when I execute setImage in AddIm.
it doesn't work. please let me know why
Your problem has nothing to do with your knowledge with Qt but rather your knowledge of c++.
In AddIm::on_pushButton_clicked(), you create a new MainWindow object on the stack, create the image, and then exit the function.
When a function exits, all local stack objects are destroyed. This means that your image is indeed being loaded but the window is being destroyed before you get a chance to see it. Even if it survived to live longer than the function allowed, you never show the window so it remains hidden.
UPDATE:
Change AddIm.cpp to be the following:
void AddIm::on_pushButton_clicked()
{
MainWindow *mainwindow = new MainWindow;
mainwindow->setAttribute(Qt::WA_DeleteOnClose, true);
mainwindow->setImage();
mainwindow->show();
}
Compare this with with your code to see where you might have gone wrong. I tried as much as possible to code it just like you did. I hardly use the designer, i like to code everything. It works as expected.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QWidget>
#include <QLabel>
#include <QPixmap>
class MainWindow : public QWidget {
Q_OBJECT
public:
void setImage();
private:
QLabel *label;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
void MainWindow::setImage() {
QPixmap pix(":/test.jpg");
label = new QLabel;
label->setPixmap(pix);
label->show();
}
addim.h
#ifndef ADDIM_H
#define ADDIM_H
#include <QMainWindow>
#include <QPushButton>
#include <QHBoxLayout>
#include "mainwindow.h"
class AddIm : public QMainWindow {
Q_OBJECT
public:
AddIm(QWidget *parent = 0);
~AddIm();
private slots:
void on_pushButton_clicked();
private:
QPushButton *button;
};
#endif // ADDIM_H
addim.cpp
#include "addim.h"
AddIm::AddIm(QWidget *parent) : QMainWindow(parent) {
button = new QPushButton("Show Image");
setCentralWidget(button);
connect(button, SIGNAL(clicked()), this, SLOT(on_pushButton_clicked()));
}
void AddIm::on_pushButton_clicked() {
MainWindow mainwindow;
mainwindow.setImage();
}
AddIm::~AddIm() {
}
main.cpp
#include "addim.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
AddIm window;
window.show();
return a.exec();
}
You did not shown the window.
First, you have to create a C++ Class not a single .cpp file. Then add a pointer to the window in your AddIm.h file:
private:
MainWindow* mainwindow;
Then in your AddIm.cpp file:
mainwindow = new MainWindow(this);
mainwindow->setAttribute(Qt::WA_DeleteOnClose, true); // prevent memory leak when closing window
mainwindow->setImage();
mainwindow->show();
And remember to include MainWIndow in AddIm.h
#include "mainwindow.h"

(QWebView) QWidget: Must construct a QApplication before a QPaintDevice

Just trying to make a simple web viewer app so I can view a webpage in a widget and I am getting the error:
QWidget: Must construct a QApplication before a QPaintDevice
I feel like this is a problem with the webkit? I am statically linking this project.
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtGui>
#include <QWebPage>
#include <QtWebKit>
#include "Windows.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QWebView *view = new QWebView(parent);
view->load(QUrl("http://google.com/"));
view->show();
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
.pro file
QT += core gui webkit network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = webkittest
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
header file
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWebView>
#include <QUrl>
#include <QtPlugin>
#include <QGridLayout>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QMessageBox>
#include <QDialog>
#include <QtWebKit>
class QAction;
class QCheckBox;
class QComboBox;
class QGroupBox;
class QLabel;
class QLineEdit;
class QMenu;
class QPushButton;
class QSpinBox;
class QTextEdit;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
protected:
//void closeEvent(QCloseEvent *event);
//void keyPressEvent(QKeyEvent *);
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
private slots:
//void onSslErrors(QNetworkReply* reply, const QList<QSslError> &errors);
private:
Ui::MainWindow *ui;
QWebView* m_pWebView;
#endif // MAINWINDOW_H
Any ideas what could be causing that?
Fixed this by installing the latest version of Qt framework and dynamically linking webkit as they have disable static linking.

C++ Qt - strange behavior when Class T's attribute has parent is T

Not sure this issue about Qt or C++ in general, I'm just a newbie for both of these!
I got a simple Qt app, with a MainWindow and Hello class like below:
hello.h
#ifndef HELLO_H
#define HELLO_H
#include <QWidget>
#include "mainwindow.h"
class Hello : public QWidget
{
Q_OBJECT
public:
explicit Hello(MainWindow *parent = 0);
signals:
public slots:
};
#endif // HELLO_H
heloo.cpp
#include "hello.h"
Hello::Hello(MainWindow *parent) :
QWidget(parent)
{
//nothing here yet
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
#include "hello.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Hello* hi;
};
#endif // MAINWINDOW_H
mainwindows.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
hi = new Hello(this);
}
MainWindow::~MainWindow()
{
}
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
and here is the error when I build my project:
from ../untitled1/main.cpp:2: ../untitled1/hello.h:11: error: expected
‘)’ before ‘*’ token
and the line cause the error is:
explicit Hello(MainWindow *parent = 0);
Can you help me to resolve the issue!
Thanks you!
You have circular inclusion of header files in "hello.h" and "maindwindow.h". There is no need to include these files in the header file as you are just using a pointer. A simple forward declaration such as class MainWindow; in "hello.h" is sufficient.