Use variable declared in MainWindow Qt - c++

I have the following problem in Qt, I'm trying to make a chess-game and I'm encountering some problems:
In the class mainwindow I have the following function:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
scene = new ChessBoard;
QGraphicsView *view = new QGraphicsView(scene);
setCentralWidget(view);
connect(scene,SIGNAL(clicked(int,int)),this,SLOT(clicked(int,int)));
//!!!!!!!!!!
scene->setInitialPositions();
}
I have a variable scene, scene is an object of the class ChessBoard.
In the whole class mainwindow I can use the scene-variable to use functions declared in ChessBoard.
However, I have another class called game.
In game I have this function
void game::setStartBord() {
scene->setInitialPositions();
}
It simply needs to launch scene->setInitialPositions();
However, I don't have access to the 'scene-variable' there. I tried to inherit the ChessBoard and MainWindow class, tried to make scene global, but none really were a good solution.
How would I do that?
Full code is visibly here:
https://github.com/UA-Niel/chess

You can use signal and slot technique. Connect your game class object to scene object.
connect(game, &Game::mySignal, scene, &ChessBoard::setInitialPositions);
Define in your Game-Class the signal.
class Game .. {
..
signals:
void mySignal();
..
};
Then define setInitialPositions in your ChessBorard class in public slots.
class ChessBoard {
...
public slots:
<datatype> setInitialPositions();
};
Then use
emit mySignal(); from Game class
to execute setIntialPositions() in your ChessBoad class.
You need to design your code that you have access to both objects at some point. Mostly this is MainWindow because you intialize classes upon program start.
If your code does not depend on the intialized class.
You can simply do a new ChessBoard object in Game class
ChessBoard myObject;
myObject.setIntialPositions();

Related

Qt update an image in the UI through callback

I have a function streamCamera(*callback) where the callback is void callback(Image) which can be used to preview the stream in any UI framework we want.
I was able to stream with this function in a opencv imshow window
void callback(image)
{
cv::imshow("image", image);
waitKey(1);
}
while the imshow is a static function and was able to stream.
Is there anything similar i can do with Qt?
What I tried,
I have a class MainWindow which inherits QMainWindow, inside the class i have attached a QGraphicsPixmapItem pixImage into the ui with ui->graphicsView->scene()->addItem(&pixImage);
since the pixImage is not accessible to the callback function, cause the Mainwindow object is not global. I was not able to set image in the pixmap;
So i ended up doing a hack, just created a global pointer a QGraphicsPixmapItem *pixImagePtr and attached the pixImage before starting the streamCamera(*callback) and inside the callback i use the pixImagePtr to set the image GUI, and it worked.
But this hack seems like not the right way to do, so it would be helpful if some qt experts shed some light on it.
Sounds like something that should be done with signals.
Let's say you have your MainWindow and Worker class.
Worker wants to show some image inside the MainWindow, you can do it like this.
class MainWindow : public QMainWindow {
Q_OBJECT
// Other members
public slots:
void showImage(const QPixmap &pixmap) {
pixImage.setPixmap(pixmap);
}
};
class Worker : public QObject {
Q_OBJECT
public:
Worker(MainWindow* parent) : QObject{parent} {
connect(this, &Worker::pixmapChanged,
parent, &MainWindow::showImage);
}
signals:
void pixmapChanged(QPixmap pixmap);
}
From now inside Worker you should be able to use pixmapChanged signal to change MainWindow image like so.
const QPixmap pixmap = getNewPixmap();
emit pixmapChanged(pixmap);

What are `(QWidget* pobj=0)` and `(QWidget* pwgt/*=0/)` for?

I have just started to learn QT. Can't understand how do theese constructors work. For example:
//Progress.h
#include<QtWidgets>
class QProgressBar;
class Progress:public QWidget{
Q_OBJECT
private:
QProgressBar* m_pprb;
int step;
public:
Progress(QWidget* pobj=0);
public slots:
void slotStep();
void slotReset();
//
//Progress.cpp
#include<QtWidgets>
#include"Progress.h"
Progress::Progress(QWidget* pwgt/*=0*/):QWidget(pwgt)
{
//some buttons
}
So, the question is, what happens in constructors?
What you are creating is a Progressclass which inherits from QWidget.
The QWidget class can take an parentargument, if you look at the documentation:
Constructs a widget which is a child of parent, with widget flags set to f. If parent is nullptr, the new widget becomes a window. If parent is another widget, this widget becomes a child window inside parent. The new widget is deleted when its parent is deleted.
This parentin your code is called pwgt (I would think it stands for parentWidget)
What you do, is creating a default argument for your constructor to be set automatic to 0:
Progress(QWidget* pobj=0);
Cleaner maybe would be (for convenience with Qt standard):
Progress(QWidget* parent=nullptr);
So, why do do you need the constructor to look like this?
It is the same reason, which stands for QWidget:
You can set a parent widget, but you don't have to!
The QWidget class will deal for you with this, either you set a parent or not.

Using the QGraphicsView Method Scene() to Assign a QGraphicsScene Variable

What would the syntax look like if I wanted to even use QGraphicsView::scene() in the first place? My goal is to change the scale of a pixmap in my graphics view object with sliders. I want to use QgraphicsView::scene() and QScene::itemsAt() etc. to find the original pixmap and then use QPixmap::scaled() (this I found would be the only way to ensure my cosmetic property set for the pixmap holds true). However I am having issues with the syntax of QGraphicsView::scene(). My attempt is below. I am also creating a Qt widget application for context.
QGraphicsViewScene graphicsScene = ui->PixmapView->scene();
QGraphicsPixmapItem graphicsPixmapItem = graphicsScene.itemAt(0, 0);
edit
If I was to store my QPixmap pixmap* as a member variable I am not entirely sure how to implement that where it remains in scope for my slots.
edit
static member variables?
You can make your QGraphicsPixmapItem object a member variable of your class. Then you would be able to access it from any of your class member functions.
Here is a quick example:
class MyClass : public QWidget
{
Q_OBJECT
public:
MyClass(QWidget *parent = nullptr) : QWidget(parent)
{
// create graphics view, scene, etc..
}
public slots:
void openActionTriggered()
{
...
myItem = scene->addPixmap(myPixmap); // you can create your item however you want.. this is just an example
}
void mySlot()
{
if(myItem)
{
// do something with myItem
}
}
private:
QGraphicsPixmapItem *myItem = nullptr; // myItem is a member variable of
QGraphicsScene *scene = nullptr; // I made scene a member variable so it can be accessed from any member functions
}

Must construct a QApplication before a QWidget

Everywhere only just "before QPaintDevice" questions and nowhere is my error. So, here we go.
I need an extern QWidget to be able to get access to it from outside (because I don't know any other ways to do it). Basically, I need this: Create 2 QWidgets from 1 window, go to first window and from there hide main window and show second window created by main window (although main window is not main(), it is QWidget too).
I added
extern QWidget *widget = new QWidget
everywhere and everyhow in possible ways, and I still got this message. I suppose, it means that I need to create my QApplication (in main.cpp) and only then declare any QWidgets. But then HOW can I access those QWidgets from another QWidgets?
Code is here:
https://github.com/ewancoder/game/tree/QWidget_before_QApp_problem
P.S. The final goal is to be able show and hide both gamewindow.cpp and world.cpp from battle.cpp (just regular class)
And btw, adding Q_OBJECT and #include both don't work.
Anyway, if I cannot use functions from one window to another, than what's the point? I can have one window in another, and then another in that one, and then one in that another... but I can't do anything from the last to the previous. After years on Delphi that seems strange to me.
Don't use extern or otherwise static variables which lead to creation of the widget before the QApplication is created in main. The QApplication must exist before the constructor of the QWidget is executed.
Instead of sharing the variable via extern, either make the other windows members of the main window, and then make the windows known to each other by passing around pointers, or keep them private in MainWindow and request the actions from the subwindows e.g. via signal/slots. As a generic rule, don't use global variables but class members.
In the following FirstWindow (which is supposed hide main window and secondWindow) gets the main window and the second window passed via pointers and then just calls show/hide on them directly.
int main(int argc, char **argv) {
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
In main window, have two members for the two other windows, say FirstWindow and SecondWindow:
class MainWindow : public QMainWindow {
...
private:
FirstWindow *m_firstWindow;
SecondWindow *m_secondWindow;
};
MainWindow::MainWindow(QWidget *parent) {
m_firstWindow = new FirstWindow; //not pass this as parent as you want to hide the main window while the others are visible)
m_secondWindow = new SecondWindow;
m_firstWindow->setMainWindow(this);
m_firstWindow->setSecond(m_secondWindow);
m_firstWindow->show(); //Show first window immediately, leave second window hidden
}
MainWindow::~MainWindow() {
//Manual deletion is necessary as no parent is passed. Alternatively, use QScopedPointer
delete m_firstWindow;
delete m_secondWindow;
}
FirstWindow, inline for brevity:
class FirstWindow : public QWidget {
Q_OBJECT
public:
explicit FirstWindow(QWidget *parent = 0) : QWidget(parent) {}
void setMainWindow(MainWindow *mainWindow) { m_mainWindow = mainWindow); }
void setSecondWindow(SecondWindow *secondWindow) { m_secondWindow = secondWindow; }
private Q_SLOTS:
void somethingHappened() { //e.g. some button was clicked
m_mainWindow->hide();
m_secondWindow->show();
}
private:
MainWindow* m_mainWindow;
SecondWindow* m_secondWindow;
};
Maybe not helping the former author, but others facing the problem.
I simply got this error by mistaking a debug-library with a release one. So check your linker settings, if you are sure the implementation is done right (first instancing application and then using widgets).

Qt: How to put collection of GUI-Elements into independent SubClass (with seperate *.ui file)

I'm trying to collect an often used subset of GUI-Elements together into one Subclass, which can be "included" into the real GUIs later without rewriting the given functionality (don't ask why, I wanna learn it for later use). The Subclass should use it's own *.ui-File and should be put into an QWidget resding in the real GUI. After this, it would be nice to access some methods of the Subclass from the real GUI -- like the state of a button or so.
But how do I do this right?
In the moment, my Subclass works and is instantiated in main, but cannot be accessed from the real GUI because its only declared in main.
My Subclass Header-File:
class logger : public QWidget, private Ui::loggerWidget {
Q_OBJECT
public:
logger(QWidget *parent = 0);
virtual ~logger();
// some more stuff...
}
The corresponding constructor. I had to run setupUI with "parent" instead of "this", but I'm not sure that this is correct -- anyways, it works... otherwise, the subelements from the subclass are not shown in the main-window of the real GUI.
logger::logger(QWidget *parent) : QWidget(parent){
setupUi(parent);
//ctor
}
Inside the main.cpp the main-window is constructed, which uses it's own *.ui-File (containing one widget "widget_loggerArea") aswell. Doing so, I can not access methods of "logger" from within "loggerTest":
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
loggerTest window;
logger myLog(window.widget_loggerArea);
window.show();
return app.exec();
}
I can't put the constructor of "logger" into the constructor of the main-window "loggerTest", since it will be destroyed immidiately and never enters the event-loop.
I'm sure I'm missing some concept of object-oriented programming, or the way qt handles its stuff... I would be gratefull if someone could put my nose to this ;-)
I was so stupid... using a pointer with new and delete does the job... this is so silly, I can't believe it! I'm more used to VHDL recently, this weakens my C++-karma...
So, the answer is in the real GUI class. The Constructor:
testLogger::testLogger(QMainWindow *parent) : QMainWindow(parent){
setupUi(this);
myLog = new logger(widget_loggerArea);
}
In main.cpp:
QApplication app(argc, argv);
testLogger window;
window.show();
And in constructor of logger, setupUi works with "this":
dfkiLogger::dfkiLogger(QWidget *parent) : QWidget(parent){
setupUi(this);
}
Yes, thats it... Just for completebility, maybe someone needs a similar "push in the right direction"...
EDIT: In the header of the SubClass the scope of the ui-Elements has to be updated to "public", too:
class logger : public QWidget, public Ui::loggerWidget {
Q_OBJECT
public:
logger(QWidget *parent = 0);
virtual ~logger();
}