Forum: PC-Programmierung C++ (Qt), Objekt-Scope und Qt-Prinzip


von Ratloser (Gast)


Lesenswert?

Beim Versuch, einem QGraphicsView ein Element hinzuzufügen (Text), 
stürzt das Programm ab. Es ensteht aus der Standardanwendung (QWidget 
Projekt), die GUI enthält den/das QGraphicsView und einen QPushbutton in 
einem QWidget(centralWidget, verticalLayout) in QMainWindow.

Offenbar erzeuge/deklariere ich das QGraphicsScene nicht richtig/an 
richtiger Stelle, denn wenn der Zugriff aus dem slot des pushButtons 
erfolgt, kommt der Absturz.

Ich würde mich freuen, wenn jemand erklären kann, warum das so nicht 
funktioniert und wie man es richtig macht.


mainwindow.cpp
1
#include "mainwindow.h"
2
#include "ui_mainwindow.h"
3
4
MainWindow::MainWindow(QWidget *parent) :
5
    QMainWindow(parent),
6
    ui(new Ui::MainWindow)
7
{
8
    ui->setupUi(this);
9
10
    QGraphicsScene* scene = new QGraphicsScene( QRect(0, 0, 300, 300) );
11
    scene->addText("Hello, world!");
12
    ui->graphicsView->setScene(scene);
13
    ui->graphicsView->show();
14
}
15
16
MainWindow::~MainWindow()
17
{
18
    delete ui;
19
}
20
21
void MainWindow::on_pushButton_clicked()
22
{
23
    scene->addText("Hi there");
24
}

mainwindow.h
1
#ifndef MAINWINDOW_H
2
#define MAINWINDOW_H
3
4
#include <QMainWindow>
5
#include <QGraphicsScene>
6
7
namespace Ui {
8
class MainWindow;
9
}
10
11
class MainWindow : public QMainWindow
12
{
13
    Q_OBJECT
14
    
15
public:
16
    explicit MainWindow(QWidget *parent = 0);
17
    ~MainWindow();
18
    
19
private:
20
    Ui::MainWindow *ui;
21
    QGraphicsScene* scene;
22
23
private slots:
24
    void on_pushButton_clicked();
25
};
26
27
#endif // MAINWINDOW_H

von Karl H. (kbuchegg)


Lesenswert?

Ratloser schrieb:

> MainWindow::MainWindow(QWidget *parent) :
>     QMainWindow(parent),
>     ui(new Ui::MainWindow)
> {
>     ui->setupUi(this);
>
>     QGraphicsScene* scene = new QGraphicsScene( QRect(0, 0, 300, 300) );

logisch.
Das hier ist eine lokale Variable in dieser Funktion.
Ist die Funktion beendet, löst sich diese Variable in Luft auf.



> private:
>     Ui::MainWindow *ui;
>     QGraphicsScene* scene;

Das ist aber eine andere scene Variable und hat mit der im Konstruktor 
erzeugten nichts zu tun.

Ergo: in deinem Button Handler greifst du auf eine ganz andere Variable 
zu, als die die du im Konstruktor benutzt hast.


Tip: Genau aus diesen und ähnlichen Gründen, bekommen Member-Variablen 
gerne einen Zusatz, so dass man aus dem Variablennamen schon ersehen 
kann, ob man es mit einer Membervariablen oder mit einer funkionslokalen 
Variablen zu tun hat.
Microsoft hat in der MFC die Konvention eingeführt, dass Membervariablen 
an einem Präfix m_ zu erkennen sind. Aber auch die Konvention eines 
Postfix Underscores erfreut sich großer Beliebtheit.

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui_;
    QGraphicsScene* scene_;

private slots:
    void on_pushButton_clicked();
};



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QGraphicsScene* scene = new QGraphicsScene( QRect(0, 0, 300, 300) );
    scene->addText("Hello, world!");
    ui->graphicsView->setScene(scene);
    ui->graphicsView->show();
}

Das kann daher nicht stimmen. Denn die Variable an die du ran willst, 
(weil es eine Member Variable des Objekts ist) müsste scene_ heissen. 
Und weil es eine Member Variable ist, kann daher auch hier keine 
Variablendeklaration erfolgen. Membervariablen existieren ja schon, wenn 
der Funktions-Körper eines Konstruktors loszulegen beginnt.

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    scene_ = new QGraphicsScene( QRect(0, 0, 300, 300) );
    scene_->addText("Hello, world!");
    ui->graphicsView->setScene(scene_);
    ui->graphicsView->show();
}

von Ratloser (Gast)


Lesenswert?

Verstanden! Vielen Dank! Das dürfte eine ganze Reihe meiner Probleme 
lösen :-) Du bist der Held des Tages! :-)

von ich (Gast)


Lesenswert?

Alternativ kannst du auch ohne Member-variable, per
1
ui->graphicsView->scene()->setText("")
auf deine Szene zugreifen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.