How to access ui components from another class? - c++

I am trying to call a method called display_txt() from my_class. This method is supposed to change some text in a label. But the method doesn't make any changes to the ui. I know the method runs due to the qDebug(). No errors occur, but the label just doesn't change to "text changed". display_txt() works fine and changes the label when called from the main widget class. There is a similar question in the forums but I couldn't use those solutions. I make an object when the button btn is pressed.
Here is the code:
widget.h
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void display_txt();
private slots:
void on_btn_clicked();
private:
Ui::Widget *ui;
};
my_class.h
#include <QWidget>
#include "widget.h"
class my_class : public QWidget
{
Q_OBJECT
public:
explicit my_class(QWidget *parent = 0);
void test(Ui::Widget ui1);
signals:
private:
Widget *wo = new Widget;
};
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include "my_class.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//display_txt();
qDebug() << "Widget object created";
}
void Widget::display_txt(){
ui->lbl->setText("text changes!!!!!");
qDebug() << "display_txt() method finished";
}
void Widget::on_btn_clicked()
{
my_class mc;
}
my_class.cpp
#include "my_class.h"
#include "QDebug"
my_class::my_class(QWidget *parent) : QWidget(parent)
{
qDebug() << "myclass ran";
wo->display_txt();
}

Related

QT Not Updating Second UI

I have 2 UIs and I am trying to update one from the other. I have the classes phone, user_ui, test_ui, and user_transmitter. The user_ui is the one that a user can interact with such as if the user pressed the toggle button on the UI of the user_ui then the status should be displayed on the UI of the test_ui. The user_transmitter transmits the inputs and outputs and that's its only job, there is no UI to it. The phone class just contains the variables and nothing else.
user_ui.h:
#ifndef USER_UI_H
#define USER_UI_H
#include <QMainWindow>
#include <QTimer>
#include <phone.h>
#include "user_transmitter.h"
#include "test_ui.h"
using namespace std;
QT_BEGIN_NAMESPACE
namespace Ui { class user_ui; }
QT_END_NAMESPACE
class user_ui : public QMainWindow
{
Q_OBJECT
public:
user_ui(QWidget *parent = nullptr);
~user_ui();
Phone phone;
QTimer *timer;
private:
Ui::user_ui *ui;
user_transmitter user_t;
void updateUI();
void connections();
signals:
void toggeButton(int);
private slots:
void toggleButton1();
void update();
};
#endif // USER_UI_H
user_ui.cpp:
#include "user_ui.h"
#include "ui_user_ui.h"
#include <QMessageBox>
user_ui::user_ui(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::user_ui)
{
ui->setupUi(this);
update();
connections();
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
user_ui::~user_ui()
{
delete ui;
}
void user_ui::update()
{
ui->status->setText((phone.status) ? "On" : "Off");
}
void user_ui::connections() {
QObject::connect(this, &user_ui::toggleButton, &user_t, &user_transmitter::toggleButton);
connect(ui->button, SIGNAL(released()), this, SLOT(toggleButton1()));
}
void user_ui::toggleButton1() {
phone.status= !phone.status;
emit toggleButton(1);
}
user_transmitter.h:
#ifndef USER_TRANSMITTER_H
#define USER_TRANSMITTER_H
#include <vector>
#include "phone.h"
#include "test_ui.h"
class user_transmitter : public QObject
{
Q_OBJECT
public:
explicit user_transmitter(QObject *parent = nullptr);
Phone phones;
public slots:
void toggleButton(int);
private:
void setUpSignals();
test_ui test;
signals:
void button(int,bool);
};
#endif // USER_TRANSMITTER_H
user_transmitter.cpp:
#include "user_transmitter.h"
user_transmitter::user_transmitter(QObject *parent) : QObject(parent)
{
setUpSignals();
}
void user_transmitter::setUpSignals(){
QObject::connect(this, &user_transmitter::button, &test, &test_ui::button);
}
void user_transmitter::button(int index)
{
phones.status = !phones.status;
cout << "From transmitter: " << phones.status<< endl;
emit button(index, phones.status);
}
test_ui.h:
#ifndef TEST_UI_H
#define TEST_UI_H
#include <QWidget>
namespace Ui {
class test_ui;
}
class test_ui : public QWidget
{
Q_OBJECT
public:
explicit test_ui(QWidget *parent = nullptr);
~test_ui();
QTimer *timer;
public slots:
void button(int,bool);
private:
Ui::test_ui *ui;
signals:
};
#endif // TEST_UI_H
test_ui.cpp:
#include "test_ui.h"
#include "ui_test_ui.h"
test_ui::test_ui(QWidget *parent) :
QWidget(parent),
ui(new Ui::test_ui)
{
ui->setupUi(this);
}
test_ui::~test_ui()
{
delete ui;
}
void test_ui::button(int index, bool status){
qDebug() << "From test: " << status;
ui->status->setText((status) ? "On" : "Off");
}
My problem is that when I press the toggle button of user_ui's UI, the "on" or "off" status should display on the user UI and the test_ui. It displays on the user UI but not the test_ui. The qdebug line in the transmitter and the test class print but the UI of the test does not get updated so I am guessing that the function is getting called. So, I am not sure if it's a signal slot problem since the qdebug line is printing or if it's a timing problem.
I tested out my test UI by trying to print something in the QLineEdit box from a different function in that class and it works so there is no problem there.
I was able to solve my problem by simply adding my Signal and Slot connections from the 2 classes (user_ui & user_transmitter) to my main.cpp.

setWindowState from QMainWindow from QWidget

I have a QMainWindow Application which also includes an QStackedWidget.
The pages of the QstackedWidget are promoted to ui widgets for example heating_widget.ui
If I use a button slot on my QMainWindow I can use this to get my application to fullscreen:
void SmartHome::on_fullscreen_on_clicked()
{
SmartHome::setWindowState(Qt::WindowFullScreen);
}
But how can I do this from a button which is in the heating_widget.cpp file?
Using:
void heating_widget::on_fullscreen_on_clicked()
{
SmartHome::setWindowState(Qt::WindowFullScreen);
}
obviously doesn't work and throws this error at me:
cannot call member function 'void
QWidget::setWindowState(Qt::WindowStates)' without object
SmartHome::setWindowState(Qt::WindowFullScreen);
I know this has something to do with parent() but I can't get it to work.
Do you have any idea?
My smarthome.h file:
#ifndef SMARTHOME_H
#define SMARTHOME_H
#include <QTime>
#include <QMainWindow>
namespace Ui {
class SmartHome;
}
class SmartHome : public QMainWindow
{
Q_OBJECT
public:
explicit SmartHome(QWidget *parent = 0);
~SmartHome();
private slots:
void on_Info_Button_clicked();
void on_News_Button_clicked();
void on_Heating_clicked();
void timerslot();
void on_Config_clicked();
void on_About_clicked();
public slots:
void setFullscreen();
private:
Ui::SmartHome *ui;
QTimer* myTimer;
};
#endif // SMARTHOME_H
My heating_widget.h :
#ifndef HEATING_WIDGET_H
#define HEATING_WIDGET_H
#include "smarthome.h"
#include <QWidget>
namespace Ui {
class heating_widget;
class SmartHome;
}
class heating_widget : public QWidget
{
Q_OBJECT
public:
explicit heating_widget(QWidget *parent = 0);
~heating_widget();
private slots:
void on_fullscreen_on_clicked();
private:
Ui::heating_widget *ui;
};
#endif // HEATING_WIDGET_H
and my heating.widget.cpp:
#include "heating_widget.h"
#include "ui_heating_widget.h"
#include "smarthome.h"
#include "iostream"
heating_widget::heating_widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::heating_widget)
{
ui->setupUi(this);
QObject::connect(ui->fullscreen_on, SIGNAL(clicked()), this , SLOT(SmartHome::setFullscreen()));
}
heating_widget::~heating_widget()
{
delete ui;
}
void heating_widget::on_fullscreen_on_clicked()
{
parentWidget()->setWindowState(Qt::WindowFullScreen);
std::cout<<"clicked"<<std::endl;
}
I would do it in the following way:
void heating_widget::on_fullscreen_on_clicked()
{
foreach(QWidget *widget, QApplication::topLevelWidgets()) {
if (auto mainWindow = qobject_cast<SmartHome *>(widget)) {
mainWindow->setWindowState(Qt::WindowFullScreen);
}
}
}
The idea is finding your main window among application top level widgets and change its state. This code can be called from anywhere in your application regardless of the windows hierarchy.

Qt slot method (which is another class) not firing when emiting the signal

I know this question asked many times but still confused and cannot find a solution.
I have a MainWindow and a class.
In my class I have a signal which I emit in the method call.
Problem: Slot method is not firing.
Here is my code.
BWorker.h
#pragma once
#include <QObject>
class BWorker : public QObject
{
Q_OBJECT
public:
BWorker(QObject *parent);
~BWorker();
void doSomething();
signals:
void signalSomething();
};
BWorker.cpp
#include "BWorker.h"
BWorker::BWorker(QObject *parent)
: QObject(parent)
{
}
BWorker::~BWorker()
{
}
void BWorker::doSomething()
{
emit signalSomething();
}
QtGuiApplication1.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtGuiApplication1.h"
class QtGuiApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtGuiApplication1(QWidget *parent = Q_NULLPTR);
public slots:
void workDone();
private:
Ui::QtGuiApplication1Class ui;
};
QtGuiApplication1.cpp
#include "QtGuiApplication1.h"
#include "BWorker.h"
QtGuiApplication1::QtGuiApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
BWorker bworker(this);
connect(&bworker, SIGNAL(bworker.signalSomething), this, SLOT(workDone()));
bworker.doSomething();
}
void QtGuiApplication1::workDone() {
}
Your problem is here:
SIGNAL(bworker.signalSomething)
This is not valid and you should see a message in terminal saying that there is no such signal. The correct syntax for your case would be:
SIGNAL(signalSomething())
Please post your code by copy-pasting it. Do not edit the code: The problem could be emerged from where you edited.
The code of mine worked fine.
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void workDone();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "worker.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
Worker worker(this);
connect(&worker, SIGNAL(signalSomething()), this, SLOT(workDone()));
//connect(&worker, &Worker::signalSomething, this, &MainWindow::workDone);
worker.doSomething();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::workDone()
{
qDebug() << "Done.";
}
worker.h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
void doSomething();
signals:
void signalSomething();
public slots:
};
#endif // WORKER_H
worker.cpp:
#include "worker.h"
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::doSomething()
{
emit signalSomething();
}
Application Output:
Debugging starts
Done.
Debugging has finished
Printed out "Done." means the codes are working.

Qt get combobox currentIndex from another class(out of ui class)

I want to get the currentIndex of combobox in the main Widget, then send this value to another class. I tried to make a function to return the currentIndex, however, I always get '0'. Could someone explain me why, or give me an example? Plus, I think it's because I create a new object in another class, but how can I get the actived Widget's pointer? Here are the codes:
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui { class Widget; }
class Widget : public QWidget {
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
int comboboxText();
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui; };
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include "database.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
int Widget::comboboxText(){
return ui->comboBox->currentIndex();
}
void Widget::on_pushButton_clicked()
{
qDebug() << "from Widget: " << comboboxText();
Database database;
database.getIndex();
}
database.h
#ifndef DATABASE_H
#define DATABASE_H
#include <QObject>
#include <QDebug>
class Database : public QObject
{
Q_OBJECT
public:
explicit Database(QObject *parent = 0);
void getIndex();
signals:
public slots:
};
#endif // DATABASE_H
database.cpp
#include "database.h"
#include <widget.h>
Database::Database(QObject *parent) : QObject(parent)
{
}
void Database::getIndex(){
Widget a;
qDebug()<< "from database: " << a.comboboxText();
}

How can a QWidget get the "entire" parent?

I have instantiated a widgetClass in MainWindow.cpp. I want to pass in "this" to this widget as more than just (QWidget* parent) but also (MainWindow* parent). But on the build, the widgetClass is established before the MainWindow and so it errors out.
I want to get to instanceVariables in the MainWindow??
ie:
myWidget(QWidget* parent, MainWindow* parent);
There are some issues on such task.. Maybe the problem is that you have to use Forward Declaration to include one class in one other that include the first ones.. Or maybe the fact the default constructor of QWidget has the first argument as the default parameter.. what is your error exactly?
Anyway, here is a complete example:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "mywidget.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
int foo(int n);
private:
Ui::MainWindow *ui;
MyWidget *w;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
w = new MyWidget(this);
this->setCentralWidget(w);
}
MainWindow::~MainWindow()
{
delete ui;
}
int MainWindow::foo(int n)
{
std::cout << "foo" << std::endl;
return n+42;
}
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
class MainWindow;
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(MainWindow *main, QWidget *parent = 0);
signals:
public slots:
};
#endif // MYWIDGET_H
mywidget.cpp
#include "mywidget.h"
#include "mainwindow.h"
#include <iostream>
MyWidget::MyWidget(MainWindow *main, QWidget *parent) :
QWidget(parent)
{
std::cout << main->foo(0) << std::endl;
}
Does this help?
The answer proposed by nkint is the cleanest way to do. However, there exist quick hacks if you don't have time or can't change the architecture of your software:
If you know for sure that the parent of MyWidget is a QMainWindow, you can simply do:
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent)
{
QMainWindow * main = static_cast<QMainWindow*>(parent);
std::cout << main->foo(0) << std::endl;
}
If you are not sure, i.e. may or may not actually be a QMainWindow, then you can do:
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent)
{
QMainWindow * main = qobject_cast<QMainWindow*>(parent);
// here, main is null if and only if parent was not a QMainWindow
if(main)
std::cout << main->foo(0) << std::endl;
}
qobject_cast is similar to dynamic_cast. More precisely, the documentation says:
The qobject_cast() function behaves similarly to the standard C++ dynamic_cast(), with the advantages that it doesn't require RTTI support and it works across dynamic library boundaries.
qobject_cast() can also be used in conjunction with interfaces; see the Plug & Paint example for details.
Warning: If T isn't declared with the Q_OBJECT macro, this function's return value is undefined.