Application crashes when declaring QPushButton in header - c++

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.

Related

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 Change label text from another class

i'm trying to change the label text of Class A via Class B using Qt but i can't get it working, here's my codes:
Class A:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "loldata.h"
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
LoLData *lold = new LoLData();
QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(updateData()));
QObject::connect(lold, SIGNAL(updatePlayerID(QString)), ui->label, SLOT(setText(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::updateData()
{
LoLData summoner;
summoner.getSummonerData("Snylerr");
}
Class A: (.h)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QObject>
#include <string>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void updateData();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Class B:
#include "loldata.h"
#include "mainwindow.h"
using namespace std;
int LoLData::getSummonerData(QString playerName)
{
emit updatePlayerID("playerName");
return 0;
}
Class B: (.h)
#ifndef DEF_LOLDATA
#define DEF_LOLDATA
#include <QApplication>
#include <QObject>
#include <string>
class LoLData : public QObject
{
Q_OBJECT
public:
int getSummonerData(QString playerName);
signals:
void updatePlayerID(QString playerName);
private:
};
#endif
You can see that i tried to use slots and signals but the text of the label is not changing, i saw a lot of examples on internet but i can't get them working
Thanks for your reply.
You are creating a new instance of LoLData here:
void MainWindow::updateData()
{
LoLData summoner;
summoner.getSummonerData("Snylerr");
}
This instance of LoLData named summoner is not connected to your label's setText slot.
LoLData *lold = new LoLData(); - this instance of LolData is connected to you label's setText slot.
What should yo do?
It depends on what you want to accomplish:
either connect your summoner instance to the label by inserting a QObject::connect(&summoner...) inside yourupdateData` method;
or you don't instantiate a new LolData variable and use lold inside your updateData function:
void MainWindow::updateData()
{
lold->getSummonerData("Snylerr");
}
Also in this case you have to put lold as a member variable.
In your MainWindow constructor, you connect your lold object to the setText slot.
But in updateData, you use an other object (summoner) which is not connect to anything. So when you use getSummonerData on summoner, the signal updatePlayerID is emitted nut they is no slot connected to it.

Passing the parent pointer in Qt | ERROR: no member named in QObject

I am new to qt and I am trying to create a program where the MainWindow calls a QDialog to enter some data.
The problem is that the parent() at my QDialog does not have any access to the public methods of the MainWindow in our case the
void save_city(const City *city); //public method of MainWindow
The code is actually big so here is some of the code.Thanks.
mainwindow.h
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QMainWindow>
#include <QTextStream>
#include <QVector>
#include <QDebug>
#include <QFile>
#include "dialog_add_city.h"
#include "street.h"
#include "city.h"
#include "map.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
//main Window constructor
explicit MainWindow(QWidget *parent = 0);
//main Window deconstructor
~MainWindow();
/*utility function to save the city
*the function is public so that also QDialogs
*data saves can */
//////////////
//here is the public function
void save_city(const City *city);
private slots:
private:
Map mainMap;
Ui::MainWindow *ui;
QGraphicsView view;
QGraphicsScene scene;
};
dialog_add_city.h
#ifndef DIALOG_ADD_CITY_H
#define DIALOG_ADD_CITY_H
#include <QDialog>
#include "mainwindow.h"
#include "City.h"
namespace Ui {
class Dialog_Add_City;
}
class Dialog_Add_City : public QDialog
{
Q_OBJECT
public:
explicit Dialog_Add_City(QWidget *parent = 0);
~Dialog_Add_City();
private slots:
//Add New City Button clicked-Adds an new city to our city_locations.txt
void on_PushButton_Add_New_City_clicked();
private:
Ui::Dialog_Add_City *ui;
};
#endif // DIALOG_ADD_CITY_H
dialog_add_city.cpp
#include "dialog_add_city.h"
#include "ui_dialog_add_city.h"
Dialog_Add_City::Dialog_Add_City(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog_Add_City)
{
ui->setupUi(this);
}
Dialog_Add_City::~Dialog_Add_City()
{
delete ui;
}
void Dialog_Add_City::on_PushButton_Add_New_City_clicked()
{
City *city=new City(ui->lineEdit_cityName->text(),
ui->lineEdit_X_Ko->text().toDouble(),
ui->lineEdit_Y_Ko->text().toDouble());
qDebug() << ui->lineEdit_cityName->text()
<< ui->lineEdit_X_Ko->text()
<< ui->lineEdit_Y_Ko->text();
/////////////////////////////
//HERE IS THE PROBLEM
parent()->save_city(city);
}
Any other suggestions are welcomed!
The Problem is that parent() will return a pointer the parent object as QObject.
QObject Documentation
As dreschrjm pointed out you could try to cast the object via
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
from The Meta-Object System
Suggestion: Use Qt's signal/slot mechanism to avoid a backward reference to the parent.
Declare save_city as signal in Dialog_Add_City.
Declare save_city in MainWindow as slot
Connect both where the dialog is created:
e.g.
void MainWindow::show_add_city_dialog()
{
Dialog_Add_city dialog;
connect(&dialog, &Dialog_Add_city::save_city, this, &MainWindow::save_city);
dialog.exec();
}
Replace parent()->save_city(city); in Dialog_Add_City with emit save_city(city);
Ensure that the new city object doesn't leak, I think a better design would be to create the City object elsewhere not in the dialog.
so
emit save_city(ui->lineEdit_cityName->text(),
ui->lineEdit_X_Ko->text().toDouble(),
ui->lineEdit_Y_Ko->text().toDouble());
and the slot
void MainWindow::save_city(const QString &cityName, double x, double y)
{
City *city=new City(cityName, x, y);
// do some interresting things with city.
}

QT signal-slot not received

I am trying to connect a signal from a second QMainWindow to the mainwindow. It doesn't say anything about a problem connection when the program is launched, but It doesn't work. I am not very familiar with C++ and Qt so maybe is something simple.
My code consists on a Mainwindow used as a SCADA with Start, stop, On, off buttons. In the second qmainwindow I created a terminal where you can type, start,stop... There, I would like to emit a signal to my MainWindow which is in charge of controlling the multiple threads and windows. The problem is that I cannot connect to my slot. I present here a simple overview of this two pieces of code.
Terminal. h
#ifndef TERMINAL__H
#define TERMINAL__H
#include <QMainWindow>
#include <QTextEdit>
#include <QLineEdit>
#include <QObject>
namespace Ui {
class Terminal_;
}
class Terminal_ : public QMainWindow
{
Q_OBJECT
public:
explicit Terminal_(QWidget *parent = 0);
~Terminal_();
signals:
void turnonPLC_terminal();
public slots:
void newline();
private:
Ui::Terminal_ *ui;
QTextEdit* mTerminal;
QLineEdit* mInput;
};
#endif // TERMINAL__H
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "terminal_.h"
#include "terminal_help.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Terminal_ *terminal;
public slots:
void turnon_terminal();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "terminal_.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
terminal = new Terminal_(this);
connect(terminal, SIGNAL(turnonPLC_terminal()), this, SLOT(turnon_terminal()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::turnon_terminal(){
turnonPLC=1;
}
terminal_.cpp
#include "terminal_.h"
#include "ui_terminal_.h"
#include <QDockWidget>
#include <QWidget>
#include <QLineEdit>
QString on=("on");
Terminal_::Terminal_(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Terminal_)
{
ui->setupUi(this);
mTerminal = new QTextEdit();
setCentralWidget(mTerminal);
mInput = new QLineEdit();
QDockWidget* qdw = new QDockWidget;
qdw->setWidget(mInput);
addDockWidget(Qt::BottomDockWidgetArea, qdw);
connect (mInput, SIGNAL(returnPressed()),
this, SLOT(newline()));
}
Terminal_::~Terminal_()
{
delete ui;
}
void Terminal_::newline(){
QString command = mInput->text();
if (command==on){
emit turnonPLC_terminal();
}
}
Thanks
The signal-slots part in the code works perfectly. (compiled and tested with some small modifications)
After entering "on" (not On as written in question)
Terminal_::newline() slot called, turnonPLC_terminal() is fired and finally
void MainWindow::turnon_terminal() is called.
However, there are some small details the header file is called terminal_.h, not Terminal.h turnonPLC is not defined. terminal is created by not displayed (no show-call).
I guess, there are simply some many small logic errors. Try to use debugger or trace the chain of expected calls with qDebug.

adding widget dynamically in qt

I have a small problem with adding widget to QMainWindow.
When i do it like that:
wsk_mainStatki = new mainStatki(this);
wsk_mainStatki ->setGeometry(0,0,400,300);
this->layout()->addWidget(wsk_mainStatki);
it's ok but i get warning:
QMainWindowLayout::addItem: Please use the public QMainWindow API instead
this is my game class
#include "game.h"
game::game()
{
setGeometry(200, 200, 400, 300);
setWindowTitle("Statki");
wsk_mainStatki = new mainStatki(this);
wsk_mainStatki ->setGeometry(0,0,400,300);
this->layout()->addWidget(wsk_mainStatki);
}
game header
#ifndef WIDGET1_H
#define WIDGET1_H
#include "k_plansza.h"
#include "mainStatki.h"
#include "settings.h"
#include <QApplication>
#include <QMainWindow>
class game : public QMainWindow
{
public:
game();
~game() {};
private:
mainStatki *wsk_mainStatki;
settings *wsk_settings;
};
#endif // WIDGET1_H
mainstatki class
#include "mainstatki.h"
mainStatki::mainStatki(QWidget *parent){
setupUi(this);
connect(closeButton, SIGNAL(clicked()), parent, SLOT(close()));
}
mainstatki header
#ifndef MAINSTATKI_H
#define MAINSTATKI_H
#include <QWidget>
#include "ui_mainStatki.h"
class mainStatki : public QWidget, public Ui::mainStatki
{
Q_OBJECT
public:
mainStatki(QWidget *parent);
};
#endif // MAINSTATKI_H
How it should look?
I believe it means you are not expected to manually insert stuff into the layout of a QMainWindow, but instead use methods like addToolBar, setStatusBar or setCentralWidget. The layouting of your own widgets would happen in the centralWidget.
By the way, your mainStatki constructor is missing a call to the QWidget constructor. Unless you have a good reason not to do it, your constructor should rather look like this:
mainStatki::mainStatki(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
connect(closeButton, SIGNAL(clicked()), parent, SLOT(close()));
}