Forum: PC-Programmierung Qt4 Frage zu einem Beispiel


von Stephan (Gast)


Lesenswert?

Hi,
ich arbeite mich gerade in Qt4 ein und habe diese Beispiel zum erstellen 
von 'Dynamic Language' gefunden. (aus einem Buch)
1
void MainWindow::ErstelleSprachMenu(QString sprache)
2
{
3
    SprachMenu = new QMenu(this);
4
    SprachActGroup = new QActionGroup(this);
5
6
    connect(SprachActGroup, SIGNAL(triggered(QAction *)),
7
        this, SLOT(SpracheWechseln(QAction *)));
8
9
    QDir dir(MyPath);
10
    QStringList fileNames = dir.entryList(QStringList("*.qm"));
11
12
    QString locale;
13
    QString language;
14
    QTranslator translator;
15
16
    for (int i = 0; i < fileNames.size(); ++i)
17
    {
18
        locale = fileNames[i];
19
        locale.remove(0, locale.indexOf('_') + 1);
20
        locale.truncate(locale.lastIndexOf('.'));
21
22
        translator.load(fileNames[i], MyPath);
23
24
        language = translator.translate("MainWindow", sprache.toAscii().constData());
25
26
        QAction *action = new QAction(tr("&%1 %2")
27
            .arg(i + 1).arg(locale), this);
28
29
        action->setCheckable(true);
30
        action->setData(locale);
31
32
        SprachMenu->addAction(action);
33
        SprachActGroup->addAction(action);
34
35
        if (language == sprache)
36
            action->setChecked(true);
37
    }
38
}

Jetzt zu meine Frage:
1
       QAction *action = new QAction(tr("&%1 %2")
2
            .arg(i + 1).arg(locale), this);
Hier wird ja der neue Eintrag generiert, wer ist jetzt für das löschen 
der hier erstellten Einträge verantwortlich?

Beim C++ Builder von Borland hatte ich mir damals ein Array erstellt das 
ich in der Hand hatte (mit new Erstellt und mit delete Zerstört!).

Wie ist das hier?
Werden die Einträge gelöscht wenn ich 'SprachMenu' zerstöre?

Beim Builder konnte man den CodeGuard laufen lassen, dann war man sicher 
das auch alles seine Ordnung hatte!

Ich hoffe Ihr könnt mir helfen, denn in der Doku kann ich dazu nichts 
finden.
Danke.
mfg
Stephan

von Stephan M. (stephanm)


Lesenswert?

Stephan schrieb:
> Jetzt zu meine Frage:
>
1
>        QAction *action = new QAction(tr("&%1 %2")
2
>             .arg(i + 1).arg(locale), this);
3
>
> Hier wird ja der neue Eintrag generiert, wer ist jetzt für das löschen
> der hier erstellten Einträge verantwortlich?

Nee, da wird eine QAction erstellt. Der Menueintrag wird implizit beim 
Aufruf von QMenu::addAction() erstellt und intern von QMenu verwaltet.

> Wie ist das hier?
> Werden die Einträge gelöscht wenn ich 'SprachMenu' zerstöre?

Die Menueinträge werden beim Zerstören von SprachMenu gelöscht, die 
erzeugten QAction-Objekte erst beim Zerstören von MainWindow.

Wenn man mal die Dokumentation der Basisklassen und der Grundlagen des 
Frameworks anschaut (s.u.), dann findet man dort ausreichend Hinweise 
darauf, wie Qt mit dem Thema "Object ownership" umgeht. Grundregel: 
QObjects, die als Kinder anderer QObjects erzeugt werden (daher die 
ganzen Konstruktoren der Form QClazz::QClazz(Foo f, QObject *parent = 
NULL)) sind "owned objects" des Elternobjektes, d.h. ihr Lebenszyklus 
ist an den des Elternobjekts gekoppelt.

> Beim Builder konnte man den CodeGuard laufen lassen, dann war man sicher
> das auch alles seine Ordnung hatte!

valgrind?

> Ich hoffe Ihr könnt mir helfen, denn in der Doku kann ich dazu nichts
> finden.

Qt Doku -> Core Features -> Object Model -> Object Trees and Object 
Ownership.

Stephan

von Stephan (Gast)


Lesenswert?

Ok Danke für die Info.

Aber der Parent wäre doch demnach nicht 'SprachMenu' sondern 'this' also 
'MainWindow'! richtig?

Kannst du mir noch einen Tip geben, warum das dann nicht beim setzten 
des Parent von Hand nicht geht. Das verstehe ich noch nicht ganz.
1
int main()
2
 {
3
     QPushButton quit("Quit");
4
     QWidget window;
5
6
     quit.setParent(&window);
7
     ...
8
 }

Wenn er die Kinder kennt warum löscht er Sie hier nicht in der richten 
Reihenfolge??????
- Wenn window seine Kinder löscht (hier alles io) und danach quit 
löschen will(was nicht mehr geht), weiß er doch das er es schon gelöscht 
hat, oder?
- es gibt doch hier nur eins?

Stephan

PS: Ich versuche noch die passende Gegenstück zum QAction in der vcl-Lib 
von Borland zufinden (bzw andersrum), ich dachte mit TMenuItem läge ich 
da schonmal nicht ganz so falsch.

Gute Nacht.

von Stephan M. (stephanm)


Lesenswert?

Stephan schrieb:
> Aber der Parent wäre doch demnach nicht 'SprachMenu' sondern 'this' also
> 'MainWindow'! richtig?

Parent der QActions ist die 'aufrufende' MainWindow-Instanz.

Witzigerweise erzeugst Du in dem Code ja auch noch ne QActionGroup und 
machst nachher ein QActionGroup::addAction(...) - warum nicht wie folgt:

MainWindow::MainWindow(...) : ... {
  QActionGroup *group = new QActionGroup(this);
  ...
  QAction *action = new QAction(..., group);
}

> Kannst du mir noch einen Tip geben, warum das dann nicht beim setzten
> des Parent von Hand nicht geht. Das verstehe ich noch nicht ganz.
> [...]
>
> Wenn er die Kinder kennt warum löscht er Sie hier nicht in der richten
> Reihenfolge??????

Ich verstehe nicht wirklich worauf Du hinaus willst. Was geht nicht und 
wer ist der "er" in "Wenn er seine Kinder kennt"...?

> - Wenn window seine Kinder löscht (hier alles io) und danach quit
> löschen will(was nicht mehr geht), weiß er doch das er es schon gelöscht
> hat, oder?
> - es gibt doch hier nur eins?

Kannst Du die Frage nochmal stellen bitte? :-)

> PS: Ich versuche noch die passende Gegenstück zum QAction in der vcl-Lib
> von Borland zufinden (bzw andersrum), ich dachte mit TMenuItem läge ich
> da schonmal nicht ganz so falsch.

QActions selbst sind keine GUI-Elemente, sie sind wiederverwendbare 
Bausteine, die sich an viele GUI-Elemente andocken lassen:

QMenu::addAction()
QToolBar::addAction()
QSonstwas::addAction()

Die Trennung zwischen QAction und den GUI-Komponenten macht die 
Behandlung von User-Eingaben in Qt recht flexibel und einfach.

Stephan

von Rolf Magnus (Gast)


Lesenswert?

> Kannst du mir noch einen Tip geben, warum das dann nicht beim setzten
> des Parent von Hand nicht geht.

Äh, was?

> int main()
>  {
>      QPushButton quit("Quit");
>      QWidget window;
>
>      quit.setParent(&window);
>      ...
>  }
>
>
> Wenn er die Kinder kennt warum löscht er Sie hier nicht in der richten
> Reihenfolge??????

Du hast den QPushButton als lokales Objekt, also nicht mit new angelegt. 
Ein delete DARF darauf NIEMALS gemacht werden. Aber Qt weiß das nicht. 
Es bekommt nur einen Zeiger und muß davon ausgehen, daß das Objekt mit 
new angelegt wurde. Da das nicht der Fall ist, wird obiger Code mit 
hoher Wahrscheinlichkeit zum Absturz führen, sobald window versucht, das 
Objekt per delete zu löschen.

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.