Cannot Access the Qt UI from an external cpp file - c++

Im trying to make a program an in that program I want to press a button that processes some text in another cpp file and appends my QTextEdit. I basically as a test just setup my button to run a function in the other file and also in when the program starts. When it starts it properly prints to the Text Edit as well as my console but when I press my button it only prints to the console and not to my TextEdit. For the function that appends the text in my TextEdit and prints to the console, I made it a public slot so I could access it from my other file.
This is my quiz.cpp
#include <iostream>
#include "quiz.h"
#include "ui_quiz.h"
#include "test.h"
Quiz::Quiz(QWidget *parent) : QMainWindow(parent), ui(new Ui::Quiz) {
ui->setupUi(this);
setText();
}
Quiz::~Quiz() {
delete ui;
}
void Quiz::on_actionQuit_triggered() {
QCoreApplication::quit();
}
void Quiz::on_pushButton_clicked() {
run();
}
void Quiz::setText() {
ui->console->append("Hello");
std::cout << "Hello world!" << std::endl;
}
This is its header:
#ifndef QUIZ_H
#define QUIZ_H
#include <QMainWindow>
namespace Ui {
class Quiz;
}
class Quiz : public QMainWindow
{
Q_OBJECT
public:
explicit Quiz(QWidget *parent = 0);
~Quiz();
public slots:
void setText();
private slots:
void on_actionQuit_triggered();
void on_pushButton_clicked();
private:
Ui::Quiz *ui;
};
#endif // QUIZ_H
This is my test.cpp:
#include "quiz.h"
#include "test.h"
#include "ui_quiz.h"
void run() {
Quiz* quiz = new Quiz();
quiz->setText();
}
and its header:
#ifndef TEST_H
#define TEST_H
#endif // TEST_H
void run();
What am I doing wrong? Why can I not access the ui but the rest of the function runs?

you can access UI only from Main thread.
you can use signal-slot to do that.
write your slot in main. and emit your signal from second class.
connect signal-slot in constructor main.
second class .h file:
void updateUI(QString str);
second class .cpp file:
emit updateUI("some text");
main class .h file:
void updateUI(QString str);
main class .cpp file(implementation):
void Main::updateUI(QString str)
{
// change ui here
}
main class .cpp file (in constructor):
connect(secondobj, &secondclass::updateUI, this, &mainclass::updateUI);

In header file of your cpp where you want to use the UI, add the following lines of ui.
##.h file:
class A
{
Public:
Ui::MainWindow *ui;
}
##.cpp file:
ui->label->setText(ui->button->text());

Related

Qt C++: Cannot create children for a parent that is in a different thread

Create a simple application in Qt (c ++) to encrypt a text. And I get the error: "Cannot create children for a parent that is in a different thread."
I used threads to update a text edit box in real time while entering text.
I saw other similar topics, but I did not find any solution that I could adapt to myself.
Can you please suggest me how I can solve it?
.h file
#ifndef GENERATORSHACODE_H
#define GENERATORSHACODE_H
#include <QMainWindow>
#include <thread>
QT_BEGIN_NAMESPACE
namespace Ui { class GeneratorShaCode; }
QT_END_NAMESPACE
class GeneratorShaCode : public QMainWindow
{
Q_OBJECT
public:
GeneratorShaCode(QWidget *parent = nullptr);
~GeneratorShaCode();
QString Sha512Generator(QString);
void updateOutputEditText();
std::thread GenerateCode;
private:
Ui::GeneratorShaCode *ui;
};
#endif // GENERATORSHACODE_H
.cpp file
#include "generatorshacode.h"
#include "ui_generatorshacode.h"
#include <windows.h>
#include "sha512.h"
#include <string>
#include <QtDebug>
GeneratorShaCode::GeneratorShaCode(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::GeneratorShaCode)
{
ui->setupUi(this);
GenerateCode = std::thread(&GeneratorShaCode::updateOutputEditText, this);
GenerateCode.detach();
}
GeneratorShaCode::~GeneratorShaCode()
{
delete ui;
}
QString GeneratorShaCode::Sha512Generator(QString Qstr)
{
return QString::fromStdString(sha512(Qstr.toStdString()));
}
void GeneratorShaCode::updateOutputEditText()
{
while(true)
{
ui->textEdit_Output->setText(Sha512Generator(ui->textEdit_Input->toPlainText()));
}
}
GUI thread is the main thread. You can't operate any ui controls directly within a sub thread. Usually you should use signals/slots between GUI thread and sub thread.

C++ Qt4.8 :: Pass Object to another Class - member access into incomplete type error

I am new in C++ Qt and struggling with the correct use of forward declarations and #include.
What I want to do:
I have a Qt Gui (Class Ui::Gui) where we can set values.
I want to save these values in Gui Class variables.
As soon as a button (Generate Xml) is clicked, I want to pass the object
'ui' to the XmlGeneratorClass, So i can use the values to generate a Xml.
gui.h
#ifndef GUI_H
#define GUI_H
#include <QMainWindow>
#include <QDebug>
#include "xmlgeneratorqobject.h"
namespace Ui {
class Gui;
}
class Gui : public QMainWindow
{
Q_OBJECT
public:
explicit Gui(QWidget *parent = nullptr);
~Gui();
qint8 testvalue = 1;
signals:
void transmitToXmlGen(Ui::Gui*);
private slots:
void on_pushButtonGenerateXml_clicked();
private:
Ui::Gui *ui;
XmlGeneratorQObject *xmlgenerator = new XmlGeneratorQObject();
};
#endif // GUI_H
gui.cpp
#include "gui.h"
#include "ui_gui.h"
Gui::Gui(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Gui)
{
ui->setupUi(this);
connect(this,SIGNAL(transmitToXmlGen(Ui::Gui*)),xmlgenerator,SLOT(receiveFromGui(Ui::Gui*)));
}
Gui::~Gui()
{
delete ui;
}
void Gui::on_pushButtonGenerateXml_clicked()
{
emit transmitToXmlGen(ui);
}
xmlgeneratorqobject.h
#ifndef XMLGENERATORQOBJECT_H
#define XMLGENERATORQOBJECT_H
#include <QObject>
#include <QDebug>
namespace Ui {
class XmlGeneratorQObject;
class Gui;
}
class XmlGeneratorQObject : public QObject {
Q_OBJECT
public:
explicit XmlGeneratorQObject(QObject * parent = nullptr);
private slots:
void receiveFromGui(Ui::Gui*);
};
#endif // XMLGENERATORQOBJECT_H
xmlgeneratorqobject.cpp
#include "xmlgeneratorqobject.h"
XmlGeneratorQObject::XmlGeneratorQObject(QObject *parent){}
void XmlGeneratorQObject::receiveFromGui(Ui::Gui* objectFromGui)
{
qDebug() << objectFromGui->testvalue; // ERROR member access into incomplete type 'Ui::Gui'
}
Expected result:
Access to public variables from passed gui-object should be possible
Actual result:
member access into incomplete type 'Ui::Gui'
Can you please help me learn forward declaration / include?
Is my approach in general okay?
Your xmlgeneratorqobject.cpp needs the line
#include "ui_gui.h"
This gives it the details of the ui widgets. This file is generated by the Qt build system.

Changing color of QLabel text? Accessing and modifying members of .ui file? [Qt]

I have a simple QDialog that shows a QLabel in black text. I'd like for the QLabel's text to turn red when I press the a key. I am using the designer to make the dialog. Here is my code:
myDialog.h
#include <QDialog>
#include <QWidget>
namespace Ui {
class myDialog;
}
class myDialog : public QDialog
{
Q_OBJECT
public:
explicit myDialog(QWidget* parent = 0);
~myDialog();
private:
Ui::myDialog* ui;
protected:
void keyPressEvent(QKeyEvent* event);
};
myDialog.cpp
#include "myDialog.h"
#include "ui_myDialog.h"
#include <QKeyEvent>
myDialog::myDialog(QWidget* parent) :
QDialog(parent),
ui(new Ui::myDialog)
{
ui->setupUi(this);
}
void myDialog::eventPressEvent(QKeyEvent* event)
{
if (event->key()==Qt::Key_A){
Ui_myDialog::label1->setStyleSheet(QStringLiteral("QLabel{color: rgb(170, 0, 0);}"));
} else {
qDebug << "FAIL";
}
}
myDialog::~myDialog()
{
delete ui;
}
ui_mydialog.h
/********************************************************************************
** Form generated from reading UI file 'about.ui'
** Created by: Qt User Interface Compiler version 5.5.0
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MYDIALOG_H
#define UI_MYDIALOG_H
...<snip>...
QT_BEGIN_NAMESPACE
class Ui_myDialog
{
public:
QLabel *label1;
void setupUi(QDialog *myDialog)
{
...<snip>...
label1 = new QLabel(myDialog);
label1->setObjectName(QStringLiteral("label1"));
label1->setGeometry(QRect(50, 333, 16, 20));
label1->setFont(font);
label1->setAlignment(Qt::AlignCenter);
...<snip>...
} // setupUi
...<snip>...
namespace Ui {
class myDialog: public Ui_myDialog {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MYDIALOG_H
So, here's the issue. When I build the project, a file called ui_mydialog.h gets created and is generated in the build folder. This file even says it was auto-generated by the Qt User Interface Compiler. When I try to change the stylesheet of label1 (which is declared in ui_mydialog.h) in myDialog.cpp using the line:
Ui_myDialog::label1->setStyleSheet(QStringLiteral("QLabel{color: rgb(170, 0, 0);}"));
...I get an error that says error: invalid use of non-static data member 'Ui_myDialog::label1'. This is where I'm stuck. How would I go about correctly passing label1 into the void myDialog::eventPressEvent(QKeyEvent* event) member function and modifying it?
Any help would be appreciated.
Using Ui_myDialog:: on a non-static member is incorrect.
You need to replace
Ui_myDialog::label1->setStyleSheet(QStringLiteral("QLabel{color: rgb(170, 0, 0);}"));
with
ui->label1->setStyleSheet(QStringLiteral("QLabel{color: rgb(170, 0, 0);}"));
You don't need new Ui::myDialog in 'myDialog.cpp'.
1) myDialog.h
Add #include "ui_mydialog.h"
Change Ui::myDialog* ui; to Ui::myDialog ui;
2) myDialog.cpp
Remove ui(new Ui::myDialog) in constructor.
And, then you can use ui.label1->......

no appropriate default constructor available but constructor is declared

I wanted to create a window from a mainwindow, and send it a pointer to my main window. I did it one time, and i would do it again, but the second time, I always have this error at compilation "no appropriate default constructor available"
The main window:
#include "costsimulator.h"
#include "ui_costsimulator.h"
#include "stonepricewindow.h"
CostSimulator::CostSimulator(AionEnhancingSimulator *parent) : ui(new Ui::CostSimulator)
{
ui->setupUi(this);
parentPtr = parent;
stonePrice = createStonePrice();
connect(ui->aionEnhancingSimulator, SIGNAL(clicked()), this, SLOT(showAionEnhancingSimulatorWindow()));
connect(ui->stonePriceButton, SIGNAL(clicked()), this, SLOT(showStonePriceWindow()));
}
CostSimulator::~CostSimulator()
{
delete ui;
}
void CostSimulator::showAionEnhancingSimulatorWindow()
{
this->hide();
parentPtr->show();
}
QStringList *createStonePrice()
{
QStringList *tmp = new QStringList();
tmp->push_back(QString("80-30000000"));
return (tmp);
}
void CostSimulator::showStonePriceWindow()
{
StonePriceWindow *stonepricewindow = new StonePriceWindow(this);
stonepricewindow->show();
}
QStringList *CostSimulator::getStonePrice()
{
return (stonePrice);
}
and the header:
#ifndef COSTSIMULATOR_H
#define COSTSIMULATOR_H
#include <QDialog>
#include "aionenhancingsimulator.h"
namespace Ui {
class CostSimulator;
}
class CostSimulator : public QDialog
{
Q_OBJECT
public:
AionEnhancingSimulator *parentPtr;
explicit CostSimulator(AionEnhancingSimulator *parent);
~CostSimulator();
QStringList *stonePrice;
QStringList *createStonePrice();
QStringList *getStonePrice();
void showStonePriceWindow();
public slots:
void showAionEnhancingSimulatorWindow();
private:
Ui::CostSimulator *ui;
};
#endif // COSTSIMULATOR_H
and the window that cause the problem:
#include "stonepricewindow.h"
#include "ui_stonepricewindow.h"
#include <QStringListModel>
#include <QStandardItemModel>
#include <QtGui>
StonePriceWindow::StonePriceWindow(CostSimulator *parent) : ui(new Ui::StonePriceWindow)
{
ui->setupUi(this);
displayStonePriceList(parent);
}
StonePriceWindow::~StonePriceWindow()
{
delete ui;
}
void StonePriceWindow::displayStonePriceList(CostSimulator *parent)
{
// To do
}
the header
#ifndef STONEPRICEWINDOW_H
#define STONEPRICEWINDOW_H
#include <QDialog>
#include "costsimulator.h"
namespace Ui {
class StonePriceWindow;
}
class StonePriceWindow : public QDialog
{
Q_OBJECT
public:
explicit StonePriceWindow(CostSimulator *parent = 0);
~StonePriceWindow();
void displayStonePriceList(CostSimulator *parent);
private:
Ui::StonePriceWindow *ui;
};
#endif // STONEPRICEWINDOW_H
if I had this " StonePriceWindow() {}" to the header of StonePriceWindow, I have the following error: "multiple default constructors specified" and always the "no appropriate etc .."
Thanks for any help, I can't understand why.
Sorry, but I could not add a comment on the best answer..
I had a similar problem too, it appeared that there was a mismatch between the classname of the code I created and the dialogs' objectName property value in the Qt .ui file.
I opened the .ui file in QtDesigner, and changed the objectName property value to the classname I had used in my code. Afterwards compilation was going fine.
Try adding StonePriceWindow(){} and removing the default parameter for the other constructor.
When you write code like
StonePriceWindow x;
how does compiler know whether you call the parameterless constructor or another one with default value for parent?
You need to either remove the other one, or remove the default value from it.
I found the problem.
In the StonePrinceWindow.ui, there was an obsolete name of the UI, so the auto-generated ui_stonepricewindow keep the obsolete name (even after a clean) and the compiler never find the ctor.
The solution is to change the strings
#ifndef COSTSIMULATOR_H
#define COSTSIMULATOR_H
in either of the files costsimulator.h and ui_costsimulator.h
Qt places the same #ifndef #define expression in auto generated ui_costsimulator.h

Application crashes when declaring QPushButton in header

Currently using the latest QT Creator and working on a small tutorial application. Was wanting to have a button that all the function could use and placed it in the header file:
#ifndef GAMEBOARD_H
#define GAMEBOARD_H
#include <QWidget>
#include <QtGui/QPushButton>
class QLCDNumber;
class CannonField;
class QPushButton;
class Gameboard : public QWidget
{
Q_OBJECT
public:
Gameboard(QWidget *parent = 0);
private:
QLCDNumber *remaning_shots;
QLCDNumber *hits;
CannonField *cannon_field;
QPushButton *shootb;
public slots:
void shoot();
void hit();
void missed();
void restart();
};
#endif // GAMEBOARD_H
gameboard.cpp:
#include "cannonfield.h"
#include "gameboard.h"
#include "lcdrange.h"
Gameboard::Gameboard(QWidget *parent)
: QWidget(parent) {
shootb = new QPushButton(tr("Shoot"));
And when I'm trying to run the application it just crashes before it even begins. I don't even have to use the button for anything, it crashes anyway. What am I doing wrong?
Or should I just use signals?
QPushButton *shootb = new QPushButton(tr("Shoot"));
connect(this, SIGNAL(disableShoot(bool)), shootb, SLOT(setDisabled(bool)));
And then I call it like this:
void Gameboard::missed() {
emit disableShoot(true);
}
Correct me if that's an ugly solution.