qt pointer und new vorteil Beispieklasse destruktor?

Alles rund um die Programmierung mit Qt
Antworten
prinzenrolle
Beiträge: 25
Registriert: 4. August 2010 18:38

qt pointer und new vorteil Beispieklasse destruktor?

Beitrag von prinzenrolle »

Hallo,
ich habe weiter unten eine kleine Beispielklasse erzeugt.
Diese Instanziert mit new ein neues Objekt der Klasse Keypad,
dessen Konstruktor rufe ich mit this auf. Brauche ich denn in einen der beiden Klasse ein destruktor? Wieso?

Wieso werden bei qt so oft Pointer benutzt,
anstatt die Objekte statisch zu erzeugen?

Was mache ich z.Bsp. wenn ich einen Timer brauche?
New oder statisch? Wie entscheide ich das?

Danke!

Auch für Stil- und Code -Verbesserung bin ich offen ;)

Code: Alles auswählen

#ifndef DISPLAYSETTINGS_H
#define DISPLAYSETTINGS_H

#include <QWidget>
#include "ui_DisplaySettings.h"

class Backlight;
class Keypad;

class DisplaySettings : public QWidget, public Ui::DisplaySettings
{
    Q_OBJECT
public:
    DisplaySettings(Backlight *light, QWidget *parent = 0);
private:
    Backlight *blight;
    int dim;
    int normal;
    int dim_after_sec;
    Keypad *pad;
    bool savedata;
private slots:
    void SaveValue(void);
    void SetDimTime(void);
    void CallPad(void);
    void BacklightSetNormal(int value);
    void BacklightSetDim(int value);
    void BacklightTestDim(void);
};

#endif // DISPLAYSETTINGS_H
die .c

Code: Alles auswählen

#include "DisplaySettings.h"
#include "ui_DisplaySettings.h"

#include <QFile>
#include <QDebug>

#include "Backlight.h"
#include "Keypad.h"

DisplaySettings::DisplaySettings(Backlight *light, QWidget *parent) :
    QWidget(parent), blight(light), dim(0), normal(0), dim_after_sec(0), savedata(false)
{

    pad = new Keypad(this);

    blight->GetValues(&normal, &dim, &dim_after_sec);

    setupUi(this);

    this->D_Normal->setValue(normal);
    this->D_Dim->setValue(dim);
    this->L_DimeAfter->setText(QString::number(dim_after_sec)+ "s");

    connect(this->B_TestDim, SIGNAL(clicked()), this, SLOT(BacklightTestDim()));
    connect(this->D_Dim, SIGNAL(valueChanged(int)), this, SLOT(BacklightSetDim(int)));
    connect(this->D_Normal, SIGNAL(valueChanged(int)), this, SLOT(BacklightSetNormal(int)));
    connect(this->B_DimeAfter, SIGNAL(clicked()), this, SLOT(CallPad()));

    connect(pad->B_Okay, SIGNAL(clicked()), this, SLOT(SetDimTime()));
    connect(pad->B_Cancel, SIGNAL(clicked()), this, SLOT(SetDimTime()));

    connect(this->B_Config, SIGNAL(clicked()), this, SLOT(SaveValue()));

}

void DisplaySettings::SaveValue(void)
{

    if(normal != this->D_Normal->value() || dim != this->D_Dim->value() || savedata){
        blight->SetValues(this->D_Normal->value(), this->D_Dim->value(), dim_after_sec);
        qDebug() << "values changed, save settings!";
    }

}

void DisplaySettings::SetDimTime(void)
{
    QPushButton *clickedButton = qobject_cast<QPushButton *>(sender());
    int pad_value = pad->GetValueInt();

    if(clickedButton == pad->B_Okay){
        if(this->dim_after_sec != pad_value){
            savedata = true;
            this->dim_after_sec = pad_value;
        this->L_DimeAfter->setText(QString::number(dim_after_sec)+ "s");
        }
    }
    pad->close();
    this->setEnabled(true);
}

void DisplaySettings::BacklightSetNormal(int value)
{
    if(!B_TestDim->isChecked())
    {
        blight->SetBacklight(value);
        this->D_Normal->setValue(value);
    }
}

void DisplaySettings::CallPad(void)
{
    this->setDisabled(true);
    pad->setEnabled(true);
    pad->B_Comma->hide();
    pad->OldValue->setText(QString::number(dim_after_sec) + "s");
    pad->clear();
    pad->show();
}

void DisplaySettings::BacklightSetDim(int value)
{
    if(B_TestDim->isChecked())
        blight->SetBacklight(value);

}

void DisplaySettings::BacklightTestDim(void)
{
    if(B_TestDim->isChecked()){
        blight->SetBacklight(this->D_Dim->value());
    }
    else{
         blight->SetBacklight(this->D_Normal->value());
    }
}
Klasse Keypad

Code: Alles auswählen

#ifndef KEYPAD_H
#define KEYPAD_H

#include <QWidget>

#include "ui_Keypad.h"

class Keypad : public QWidget, public Ui::Keypad
{
    Q_OBJECT

public:
    Keypad(QWidget *parent = 0);
    ~Keypad();
    bool IsValueInt(void);
    float GetValueFloat(void);
    int GetValueInt(void);    
    void clear(void);
private slots:
    void reset(void);
    void click(void);
    void comma(void);
private:
    bool firstdigit;
};

#endif // KEYPAD_H

.c datei

Code: Alles auswählen

#include "Keypad.h"

Keypad::Keypad(QWidget *parent)
    : QWidget(parent)
{
    setWindowFlags(Qt::Window
                   | Qt::FramelessWindowHint
                   | Qt::WindowTitleHint);

    setupUi(this);

    this->move(QPoint(0,0));

    connect(B_0, SIGNAL(clicked()), this, SLOT(click()) ); //0
    connect(B_1, SIGNAL(clicked()), this, SLOT(click()) ); //1
    connect(B_2, SIGNAL(clicked()), this, SLOT(click()) ); //2
    connect(B_3, SIGNAL(clicked()), this, SLOT(click()) ); //3
    connect(B_4, SIGNAL(clicked()), this, SLOT(click()) ); //4
    connect(B_5, SIGNAL(clicked()), this, SLOT(click()) ); //5
    connect(B_6, SIGNAL(clicked()), this, SLOT(click()) ); //6
    connect(B_7, SIGNAL(clicked()), this, SLOT(click()) ); //7
    connect(B_8, SIGNAL(clicked()), this, SLOT(click()) ); //8
    connect(B_9, SIGNAL(clicked()), this, SLOT(click()) ); //9

    connect(B_Clear, SIGNAL(clicked()), this, SLOT(reset()) );
    connect(B_Comma, SIGNAL(clicked()), this, SLOT(comma()) );

    firstdigit = true;

    Line->setText("0");
}

Keypad::~Keypad()
{

}
bool Keypad::IsValueInt(void)
{
    if (!Line->text().contains(tr(",")))
        return true;
    else
        return false;
}

float Keypad::GetValueFloat(void)
{
    return Line->text().toFloat();
}

int Keypad::GetValueInt(void)
{
    return Line->text().toInt();
}

void Keypad::click(void)
{
    QPushButton *clickedButton = qobject_cast<QPushButton *>(sender());
    int digitValue = clickedButton->text().toInt();
    if( (Line->text() == "0") && (digitValue == 0.0) )
        return;

    if(firstdigit)
    {
        Line->clear();
        firstdigit = false;
    }

    Line->setText(Line->text() + QString::number(digitValue));
}

void Keypad::clear(void)
{
    Line->setText("0");
    firstdigit = true;
}

void Keypad::reset(void)
{
   Line->setText("0");
   firstdigit = true;
   //this->B_Comma->show();
}

void Keypad::comma(void)
{
    if (!Line->text().contains(tr(",")))
        Line->setText(Line->text() + tr(","));
    firstdigit = false;
    //this->B_Comma->hide();
}
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Ob du die QObjects jetzt in den Freispeicher oder den automatischen Speicherbereich legst, hängt davon ab, ob diese einen QObject-parent haben. Ein QObject löscht automatisch alle QObject-children. Wenn so ein child im automatischen Speicherbereich liegt gibt es ne double-deletion - dein Programm wird abgewürgt.

Wg. Stil: Bei nur ganz kurzem Überfliegen ist mir aufgefallen, dass du public von den Ui-Klassen erbst. Mach das nicht, erbe private, sonst haben ALLE Klassen Zugriff auf die ui-Elemente, was nicht sein sollte. Sollten einzelne Elemente öffentlich zugänglich sein, biete für diese explizit getter an.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Re: qt pointer und new vorteil Beispieklasse destruktor?

Beitrag von solarix »

prinzenrolle hat geschrieben: Brauche ich denn in einen der beiden Klasse ein destruktor? Wieso?
Auf den ersten Blick sehe ich keinen Grund für einen Destruktor. Erfahrene Entwickler machen in solchen Fällen trotzdem häufig einen (virtuellen), auch wenn der vorerst nichts tut. Beim Lesen des Codes sieht man dann einfach, dass der Entwickler der Klasse daran gedacht hat ("nein, es gibt wirklich nichts zum Aufräumen")

Die Bedeutung eines "virtuellen" Destruktors, kannst du in jedem C++-Buch nachlesen.
prinzenrolle hat geschrieben: Wieso werden bei qt so oft Pointer benutzt,
anstatt die Objekte statisch zu erzeugen?
Das ist mir zu allgemein. Innerhalb der Qt-API werden Pointer äusserst sparsam und nur wo notwendig eingesetzt. In den Examples habe ich allerdings schon unnötige Pointer gesehen. Du müsstest also schon etwas konkreter Fragen..
prinzenrolle hat geschrieben: Was mache ich z.Bsp. wenn ich einen Timer brauche?
New oder statisch? Wie entscheide ich das?
Faustregel: "Pointer nur wenn notwendig". Es gibt im Programmieren selten die Lösung und auch bei QTimern habe ich Anwendungen, wo ich Pointer nehme. Aber wenn jemand schreibt "Wie entscheide ich das?" würde ich eindeutig "statisch" empfehlen :wink:

hth!
Antworten