Use this outside of constructor - c++

MainWindow::MainWindow(QWidget *parent, GraphicalUI *graphicalUI) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QLabel *label = new QLabel("Label", this);
label->setPixmap(graphicalUI->textures["background"]);
label->setStyleSheet("background-color: black;");
}
void buildWindow(Level *level, GraphicalUI *graphicUI) {
QGridLayout layout = QGridLayout(this);
}
The problem here is found in the buildWindow() function. Obviously I cannot just use
QGridLayout(this). But I want the MainWindow to be the parent of my QGridLayout.
How do I do this? Also, the buildWindow function is going to be called externally.

this is an implicit argument to all member functions. Which means it is available in all member functions not just the constructor. It's just a pointer to the current object.
Since the buildWindow function is not a member function of MainWindow(which I do not recommend) you can pass the address of the MainWindow instance to buildWindow function. By default MainWindow is instantiated in the main.cpp file when you create a new GUI project in Qt Creator.
like:
void buildWindow(Level *level, GraphicalUI *graphicUI, MainWindow* window) {
QGridLayout* layout = new QGridLayout(window);
}
But:
In your code:
void buildWindow(Level *level, GraphicalUI *graphicUI) {
QGridLayout layout = QGridLayout(this);
}
variable layout is a local variable in the scope of this function. When your code reaches the end of function (closing brackets), your QGridLayout layout object is destroyed. In order to avoid this, you should use pointers and the new keyword.
QGridLayout *layout = new QGridLayout(this);
now leyout is just a pointer to a QGridLayout object. This object is destroyed if you call delete layout; manually or the parent object (in this case your mainwindow object) get's destroyed.
But now the problem is you can't access this QGridLayout later on from other functions because the pointer layout will be lost at the end of this function. I recommend using a class member variable like:
private:
QGridLayout *layout;
in your header file and initialize if inside your function like:
void MainWindow::buildWindow(Level *level, GraphicalUI *graphicUI) {
layout = new QGridLayout(this);
}
Make sure you don't use the layout pointer before calling this function.

void MainWindow::buildWindow(Level *level, GraphicalUI *graphicUI) {
QGridLayout* layout = new QGridLayout(this);
}
Thats the solution.
The function is also required to exist in the header of the class.

Related

Using QList<QGraphicsItem*>

I am using a developer defined QGraphicsScene pointer from the "dialog/mainwindow" class called wavesScene to return a QList of QGraphicsItem*'s using QGraphicsScene::items. Something seems to be wrong with my syntax, it says that the list "graphicsItemList" is never used/declared.
Here is my code, any ideas as to how I would properly implement this methodology
relevant code inside mainwindow/segyView.h
QGraphicsScene *wavesScene;
Constructor code *I think, may be called something different
SEGYView::SEGYView(QWidget *parent)
:QMainWindow(parent),
ui(new Ui::SEGYView)
{
ui->setupUi(this);
wavesScene = new QGraphicsScene(this);
ui->PixmapView->setScene(wavesScene);
}
Code inside slider_value_changed() slot
QList<QGraphicsItem*> graphicsItemList(wavesScene->items());
QGraphicsPixmapItem pixmapItem(graphicsItemList.at(0));
QPixmap wavesPixmap = pixmapItem.pixmap();
QPixmap wavesPixmapScaled = wavesPixmap.scaled((newSliderValue*INITIAL_WAVES_PIXMAP_X_SIZE), 1250);
pixmapItem.setPixmap((wavesPixmapScaled));
wavesScene->addItem(&pixmapItem);
relevant code inside actionOpen on triggered() slot
wavesScene->addItem(pixmapGraphicsItem);
ui->PixmapView->setScene(wavesScene);
Error is "graphicsItemList" was not declared in this scope
QGraphicsPixmapItem* pixmapItem = graphicsItemList.at(0);
^

Make a QHBoxLayout accesible in an Instance of a QWidget

I want to Subclass a QWidget...
Widget::Widget(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ImgWidget)
{
// Is this the right place or does it need to be outside like: Widget::layout...
QHBoxLayout *hLayout = new QHBoxLayout;
...
hLayout->addWidget( someWidget );
this->setLayout(hLayout);
}
...and then in an instance i would like to add a widget to the layout like
Widget *widget = new Widget();
...
widget->hLayout->addWidget( someOtherWidget );
The equivalent in Python would be done by the 'self' keyword like self.layout = QHBoxLayout() but i think it cant be done with the this keyword
But more general... What is the best way to do this in C++ because i used it a lot with pyqt
Any QWidget can provide access to the layout via the layout function.
Widget* widget = new Widget();
QLayout* layout = widget->layout();
I don't know why you want to externally modify the layout of the widget but at this point you need knowledge of that actual layout type. With knowledge of the layout type you can cast and use it.
QHBoxLayout* hLayout = qobject_cast<QHBoxLayout>(layout);
Implement a function addSubWidget ( QWidget* aubWidget ), the rest of the code is ok, and make hLayout private. Or batter, use the layout function with a cast, like #James sugested.
In c++ it is just recomended, not mandatory to use this->hLayout to be sure you do notshadow it with a local variable with the same name.

Qt Update QPixmapItem in QGraphicsScene

I want to have an image in my main window with the buttons laid out on top of the image. I am using view, scene and pixmap item but when I try to change the pixmap item in the slot function, I crash.
Here is an example of what I have:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
//scene, view, pixitem and button are private variables in header
QGraphicsScene *scene = new QGraphicsScene(this);
QGraphicsView *view = new QGraphicsView(scene);
QGraphicsPixmapItem *pixitem = new QGraphicsPixmapItem;
pixitem->setPixmap(QPixmap(":/img/this.png"));
scene->addItem(pixitem);
QPushButton *button = new QPushButton(view);
this->connect(button,SIGNAL(clicked()),this,SLOT(slot()));
this->setCentralWidget(view);
}
void MainWindow:slot()
{
pixitem->setPixmap(QPixmap(":/img/that.png"));
}
Possible duplicate but this solution did not work for me:
Qt Update Pixmap of QGraphicsPixmapItem
You have shadowed the member variable pixitem because you are using
QGraphicsPixmapItem *pixitem = new QGraphicsPixmapItem;
The pixitem added to the scene will be reference by the local variable, not by the member variable. Just change to
pixitem = new QGraphicsPixmapItem;
In the constructor, you create the pixmap item:
QGraphicsPixmapItem *pixitem = new QGraphicsPixmapItem;
Then in the slot you call
pixitem->setPixmap(QPixmap(":/img/that.png"));
In order to compile successfully, you must have a QGraphicsPixmap* as a member of the class. Therefore, I conclude that this is NULL, or at least, invalid due to the creation of the item on the pointer in the constructor.
Assuming this is correct and you have indeed declared pixitem in the header of the class, change the creation in the constructor to: -
pixitem = new QGraphicsPixmapItem;

Do I have to delete these pointers?

This is the MainWindow class which I call and use the function show() to make it visible to the user.
class MainWindow : public QMainWindow
{
Q_OBJECT
QWidget *centralWidget;
QGridLayout* gridLayout;
QGridLayout* infoBoxLayout;
QHBoxLayout* buttonGroup;
QHBoxLayout* subCategoryLayout;
//... more widgets
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
void setupUi();
void setupConnections();
private slots:
void add();
void edit();
void remove();
void find();
void clearAll();
void screenshotDesktop();
void screenshotApp();
void currentSubCategoryChanged( const QString& );
void curretCategoryChanged( const int );
void keyPressEvent( QKeyEvent * );
};
I created for each widget (those pointers after the macro Q_OBJECT) a new object on the heap with new. However, I did not delete them anywhere in the program. Does this cause a memory leak in Qt? Or does something from Qt delete them automatically when destroying the class?
If a widget has a parent set, then Qt will handle deleting the widget.
In the case of a MainWindow, when you close it, the MainWindow and its children will be cleaned up, so pass the parent to the widget's constructor: -
QHBoxLayout* buttonGroup = new QHBoxLayout(this); // where this is the parent (MainWindow)
If you create a Widget such as this: -
QHBoxLayout* buttonGroup = new QHBoxLayout;
And haven't passed in the parent, then it will not be cleaned up and you'll have to handle that yourself.
if you add them to the gui hierarchy then they will be cleaned up when the MainWindow is deleted
this is because parents assume ownership over their children (which is set with the various adds of the gui)
so a this->add(centralWidget); will call centralWidget->setParent(this); which will let centralWidget be deleted when MainWindow is deleted
you are free to delete QObjects yourself but beware dangling pointers (QPointer will help here). though I suggest using deleteLater() to ensure no strange behavior when a pointer still lives on the stack.
for more info about the object tree see here
The automatic memory management through parent-child relationships is done by the QObject. QWidget happens to be a QObject, and it so happens that widgets that have parent widgets have the same underlying QObjects as parents.
A QObject with children automatically deletes its children in its destructor.
A QObject or a QWidget may be adopted by another object. For example, adding widgets to a layout will automatically reparent them to the widget the layout is set on. Even if a layout doesn't have a widget set on it yet, the reparenting will be done at the time you add the layout to a widget (or to a layout that has a widget set). It's pretty clever and saves a lot of typing and reduces possibilities for mistakes.
The idiomatic, minimum-typing way of adding widgets to another widget is:
MyWidget() {
QLayout * layout = new QHBoxLayout(this); // set a layout on this widget
layout->addWidget(new QLabel("foo")); // the label is reparented to this
layout->addWidget(new QPushButton("bar")); // the button is reparented to this
}

Replace THIS when moving from MainWindow to function

I have moved the following code from the MainWindow constructor to a function within the MainWindow.
void allFilters(QStringList list){
QWidget *w = new QWidget(this);
w->setFixedSize(300,200);
QVBoxLayout *vbox = new QVBoxLayout;
foreach(QString filt, list){
QCheckBox *checkbox = new QCheckBox(filt, this);
checkbox->setChecked(true);
vbox->addWidget(checkbox);
connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(cbstate(int)));
}
w->setLayout(vbox);
w->show();
}
this is now causing me problems. I assume there is an alternative but I'm unaware of what it is?
Hopefully someone can help me!
It looks like allFilters isn't a member function within MainWindow. this is only valid within non-static member functions as it points to the instance of the object.
You'll need to define it like
void MainWindow::allFilters(QStringList list)