adding widget dynamically in qt - c++

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()));
}

Related

Qt: how to call main window's pointer from another class?

I want to separate my roles in a game to different .cpp and .h files,
but I have trouble calling the pointer in mainwindow from another class, which I added through scene->add() in mainwindow.cpp.
It shows "player" was not declared in this scope when I run.
I know this question seems pretty basic, but I've tried my best to fix it with no results.
The following are main methods I've tried:
add MainWindow:: before player, but it shows the similar error
that mainwindow is not declared in this scope.
revise player to this pointer, and it says that class Player has no such member.
revise player to pos() pointer, it says pos() is not
declared in this scope
set class Player as friend with main window, but nothing changes
Here is the code:
main window.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
scene(new QGraphicsScene(0,0,800,600)),
timer(new QTimer)
{
ui->setupUi(this);
ui->graphicsView->setScene(scene);
player = new QGraphicsPixmapItem(QPixmap(":/img/whitedog.png").scaled(150,150));
scene->addItem(player);
player->setPos(0, 0);
timer->start(10);
}
MainWindow::~MainWindow()
{
delete ui;
}
main window.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QTimer>
#include <QKeyEvent>
#include "player.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
friend class Player;
~MainWindow();
private:
Ui::MainWindow *ui;
QGraphicsScene *scene;
QTimer *timer;
QGraphicsItem *player;
};
#endif // MAINWINDOW_H
player.cpp
#include "player.h"
Player::Player()
{
}
void Player::keyPressEvent(QKeyEvent *e)
{
switch(e->key()) {
case Qt::Key_Up:
player->setPos(player->x(), player->y()-10);
break;
}
}
player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <QKeyEvent>
#include <QGraphicsScene>
#include <QMainWindow>
#include <QGraphicsPixmapItem>
#include <QTimer>
#include "ui_mainwindow.h"
class Player
{
public:
Player();
void keyPressEvent(QKeyEvent *e);
};
#endif // PLAYER_H
You are getting confused between two different things.
You have a class Player, which I believe is the one that you want to declare in mainwindow.h but an object of class Player is not created anywhere( as far as what is shown above ).
The player currently declared in the mainwindow.h is of type QGraphicsItem and not of the Player class that you created, so you cannot expect your keyPressEvent to work on it.
You need to have a second look at your design, know the purpose of the Player class, it's responsibilities. Currently it is a simple class not inheriting from anything, did you want it to maybe inherit from QGraphicsItem.
In such a case, your class maybe could look something like this :
class Player : public QGraphicsItem
{
//Players's responsibilities.
}
And in your mainwindow.h, you can just use the instance of the Player instead of using a QGraphicsItem instance.
class MainWindow : public QMainWindow
{
...// other stuff
private:
Player *player;
}
Additional Pointers :
1 . I don't see a reason for the Player class to be a friend class in mainwindow.h, but then again it is your design.
2 . Prefer initializing the player object part in the member initialization list rather than doing it in the constructor.

Qt call Child-Window on a button click

I am new in Qt. And I am trying to open anther window from myMyMainWindow . I can't catch, what I am doing wrong with this situation. Don't want you guys to solve my problem, just say to please, what I am doing wrong.
So I have got a MainWindow.h( look at this comment, think you don't need to understand the whole proccess of it):
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
#include <QDialog>
#include <QMainWindow>
#include <QPushButton>
#include <QLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "timer.h"
class MyMainWindow: public QMainWindow
{
Q_OBJECT
private:
QPushButton *timer_Button;
QPushButton *StopWatch;
QPushButton *Close;
T_timer *myTimer;
public:
MyMainWindow(QWidget *parent);
public slots:
void Open_Timer_Window(); // Slot for opening a new window
};
#endif // MYMAINWINDOW_H
My MyMainWindow.cpp file:
#include "MyMainWindow.h"
MyMainWindow::MyMainWindow(QWidget *parent=0): QDialog(parent)
{
// just creating Buttons
timer_Button = new QPushButton ("Timer");
Close=new QPushButton("Close");
QHBoxLayout *Up=new QHBoxLayout;
Up->addWidget(timer_Button);
QHBoxLayout *Down=new QHBoxLayout;
Down->addWidget(Close);
QVBoxLayout *Main=new QVBoxLayout;
Main->addLayout(Up);
Main->addLayout(Down);
// the main part
connect(Close,SIGNAL(clicked()),this,SLOT(close()));
connect(timer_Button,SIGNAL(clicked()),this,SLOT(Open_Timer_Window()));// call `Slot of Open_Timer_Window()`
setLayout(Main);
setWindowTitle("Smart Watch");
}
void MyMainWindow::Open_Timer_Window()
{
myTimer = new T_timer(0);
myTimer->show();
}
So, I think I should show you the Second window, might be there is a mistake:
The header:
#include <QPushButton>
#include <QDialog>
#include <QHBoxLayout>
#include <QVBoxLayout>
class T_timer : public QDialog
{
Q_OBJECT
private:
QPushButton Start;
QPushButton Stop;
public:
T_timer(QWidget *parent=0);
};
And .cpp:
#include "timer.h"
T_timer::T_timer(QWidget *parent=0): QDialog(parent)
{
Start=new QPushButton ("Start");
Stop=new QPushButton ("Stop");
QHBoxLayout *Up=new QHBoxLayout;
Up->addWidget(Start);
Up->addWidget(Stop);
setLayout(Up);
}
Totally, I have got my MainWindow on the screen and after click a button timer , I haven't got an action.Help me please, if you can. Thanks.
It's a typo in your code. You need to read an output from your application to understand reasons.
connect(timer_Button,SIGNAL(click()clicked()),this,SLOT(Open_Timer_Window()));
I propose you to use Qt5 syntax.
I donĀ“t know why you're using QLayout in this case, I'd advise taking a look at this post: here
But to solve you problem try change you code to this:
connect(Close, SIGNAL(clicked(bool)), this, SLOT(close()));
connect(timer_Button, SIGNAL(clicked(bool)),this,SLOT(Open_Timer_Window()));
void MainWindow::Open_Timer_Window() {
Dialog dlg;
dlg.setModal(true);
dlg.show();
dlg.exec();
}
OBS: Change Dialog to your window.

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.
}

How to open a new QDailog window when an element in the menu bar is clicked in Qt C++

Material class has a mainwindow with a menu bar. When i click one of the elements in the menu bar i want to open the Fiction Qdialog window.
material.h
#ifndef MATERIALS_H
#define MATERIALS_H
#include <QMainWindow>
#include "materialinner.h"
class FictionSection;
namespace Ui {
class Materials;
}
class Materials : public QMainWindow, public MaterialInner
{
Q_OBJECT
public:
explicit Materials(QWidget *parent = 0);
~Materials();
private:
Ui::Materials *ui;
FictionSection *fiction;
};
#endif // MATERIALS_H
materials.cpp
#include "materials.h"
#include "ui_materials.h"
#include "fictionsection.h"
#include <QDebug>
#include <QMessageBox>
Materials::Materials(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Materials)
{
ui->setupUi(this);
// connect(ui->ficti,SIGNAL(textChanged(const QString &)),this,SLOT(displaySearch()));
}
Materials::~Materials()
{
delete ui;
}
void Materials::on_actionFiction_section_triggered()
{
this->hide();
fiction = new FictionSection();
fiction->show();
}
fictionsection.h
#ifndef FICTIONSECTION_H
#define FICTIONSECTION_H
#include <QDialog>
#include "materials.h"
namespace Ui {
class FictionSection;
}
class FictionSection : public QDialog, public Materials
{
Q_OBJECT
public:
explicit FictionSection(QWidget *parent = 0);
~FictionSection();
private:
Ui::FictionSection *ui;
};
#endif // FICTIONSECTION_H
When i compile it gives an error which is
Request for member 'show' is ambiguous.
Please help me to solve this. Thank you in advance.
The problem is that your FictionSection class inherits from both QDialog and Materials, but your Materials class also inherits from QMainWindow. Both QMainWindow and QDialog have a virtual show() method (inherited from QWidget), which causes the ambiguity. In other words: do you intend to call QMainWindow::show's implementation or QDialog::show's implementation? No one knows.
To solve this, you should use inheritance properly. Inherit from either QMainWindow or QDialog, but not both.
You need to understand why it is that you're inheriting the way you are (which is wrong) and improve the logic of the relationship between your classes to avoid problems like this one.
Also, class names should be singular, so Materials should be Material. If it needs to handle multiple things, then it could be MaterialManager or something similar.

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.