• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Zwei Fragen zu QT

Also ich hab angefangen Qt zu lernen ,da ist mir aufgefallen, dass für die widgets immer mit new Speicher reserviert wird, aber nicht mit delete wieder freigegeben wird.
Warum muss dieser bei qt nicht wieder freigegeben werden??


Meine zweite Frage ist, müsste bei diesem Beispiel nich eine so genannte Endlosschleife auftreten, da das Signal farbeGeaendert(int,int) die methode rgbNeueFarbe(int,int) auslöst , welche wiederum die methode aktualisiereSchiebeLCD(int) aufruft und die methode aktualisiereSchiebeLCD(int) wierderum sendet das Signal farbeGeandert(int,int)
(Signal farbeGeandert(int,int)->rgbNeueFarbe(int,int)->aktualisiereSchiebLCD(int)->Signal fabeGeandert(int,int)->...).
Hier das Beispielprogramm aus meinem Buch.
Code:
#include <qapplication.h>
#include <qpushbutton.h>
#include <qslider.h>
#include <qlcdnumber.h>
#include <qlabel.h>
#include <qerrormessage.h>
//........................................................ Klasse SchiebLCD
class SchiebLCD : public QWidget {
   Q_OBJECT   // notwendig, da eigene Slots enthalten sind
public:
   SchiebLCD(int oben, int nr, QWidget *parent, const char* text)
                                                    : QWidget(parent, text) {
      nummer = nr;
        //................ Erzeugen eines Text-Labels
      QLabel* name = new QLabel( this );
      name->setText( text );
      name->setGeometry( 1, 10, 15, 30 );
        //................ Erzeugen eines Schiebebalken
      schiebbalk = new QSlider( 0, oben, // min-/max-Wert
                                1, 0,    // Schrittweite u. Startwert
                       QSlider::Horizontal, this ); // Ausrichtung u. Elternwidget
      schiebbalk->setGeometry( 20, 10, 200, 30 );
        //................ Erzeugen einer LCD-Anzeige
      lcdzahl = new QLCDNumber( 3, this ); // maximal 3 Ziffern
      lcdzahl->setGeometry( 220, 10, 60, 30 );
      lcdzahl->display( 0 );
        //................ Verbinde Schiebebalken und LCD-Anzeige
      QObject::connect( schiebbalk, SIGNAL( valueChanged( int ) ), 
                        this, SLOT( aktualisiereSchiebLCD( int ) ) );
   }
signals:
   void farbeGeaendert( int nr, int wert );
public slots:
   void aktualisiereSchiebLCD( int wert ) {
      schiebbalk->setValue( wert );
      lcdzahl->display( wert );
      QErrorMessage *meldung = new QErrorMessage(this);
      meldung->message("Test");
      emit farbeGeaendert( nummer, wert ); // Signal farbeGeaendert schicken
   }
private:
   int         nummer;
   QSlider*    schiebbalk;
   QLCDNumber* lcdzahl;
};
//...................................................... Klasse farbeRgbHsv
class farbeRgbHsv : public QWidget {
   Q_OBJECT   // notwendig, da eigene Slots enthalten sind
public:
   farbeRgbHsv( QWidget *parent ) : QWidget( parent ) { //... Konstruktor
      int i;
        //................ Initialisierungen
      for ( i=0; i<3; i++)
          rgbFarbe[i] = 0;
        //................ Erzeugen einer Farbanzeige
      farbAnzeige = new QLabel( this );
      farbAnzeige->setGeometry( 330, 30, 200, 370 );
        //................ Erzeugen von drei Schiebealken fuer RGB
      const char * rgbText[] = { "R", "G", "B" };
      for ( i=0; i<3; i++ ) {
         rgb[i] = new SchiebLCD( 255, i, this, rgbText[i] );
         rgb[i]->setGeometry( 10, 30+i*50, 300, 60 );
         QObject::connect( rgb[i], SIGNAL( farbeGeaendert( int, int ) ), 
                           this, SLOT( rgbNeueFarbe( int, int ) ) );
      }
        //................ Erzeugen von drei Schiebealken fuer HSV
      const char * hsvText[] = { "H", "S", "V" };
      for ( i=0; i<3; i++ ) {
         hsv[i] = new SchiebLCD( i==0 ? 359 : 255, i+3, this, hsvText[i] );
         hsv[i]->setGeometry( 10, 250+i*50, 300, 60 );
         QObject::connect( hsv[i], SIGNAL( farbeGeaendert( int, int ) ), 
                           this, SLOT( hsvNeueFarbe( int, int ) ) );
      }
      rgb[0]->aktualisiereSchiebLCD( 255 ); // FЭr Farbenanzeige (rot) zu Beginn
   }
public slots:
   void rgbNeueFarbe( int nr, int wert ) { //... rgbNeueFarbe
      if ( rgbFarbe[nr] != wert ) {
         int  h, s, v;
         rgbFarbe[ nr ] = wert; 
         QColor neueRgbFarbe( rgbFarbe[0], rgbFarbe[1], rgbFarbe[2] );
         farbAnzeige->setPaletteBackgroundColor( neueRgbFarbe );
         neueRgbFarbe.getHsv( &h, &s, &v );
         hsv[0]->aktualisiereSchiebLCD( hsvFarbe[0] = h );
         hsv[1]->aktualisiereSchiebLCD( hsvFarbe[1] = s );
         hsv[2]->aktualisiereSchiebLCD( hsvFarbe[2] = v );
      }
   }
   void hsvNeueFarbe( int nr, int wert ) { //... hsvNeueFarbe
      if ( hsvFarbe[nr-3] != wert ) {
         int r, g, b;
         hsvFarbe[ nr-3 ] = wert; 
         QColor neueHsvFarbe( hsvFarbe[0], hsvFarbe[1], hsvFarbe[2], QColor::Hsv );
         farbAnzeige->setPaletteBackgroundColor( neueHsvFarbe );
         neueHsvFarbe.getRgb( &r, &g, &b );;
         rgb[0]->aktualisiereSchiebLCD( rgbFarbe[0] = r );
         rgb[1]->aktualisiereSchiebLCD( rgbFarbe[1] = g );
         rgb[2]->aktualisiereSchiebLCD( rgbFarbe[2] = b );
      }
   }
private:
   QLabel    *farbAnzeige;
   int       rgbFarbe[3], hsvFarbe[3];
   SchiebLCD *rgb[3],     *hsv[3];
};
#include "farbe.moc"
//.................................................................... main
int main( int argc, char* argv[] ) {
   QApplication myapp( argc, argv );
   
   farbeRgbHsv* mywidget = new farbeRgbHsv( 0 );
   mywidget->setGeometry( 100, 100, 540, 450 );
  
   myapp.setMainWidget( mywidget );
   mywidget->show();
   return myapp.exec();
}
Wenn man es kompiliert ensteht keine Endlosschleife, aber ich vesteh nicht warum.
Ich hoffe ihr könnt mir helfen.[/code]
 
Hi, ich bin auch neu dabei und hoffe ich liege richtig. Also ...

Dein 1. Problem:

Also ich weiß net ob ich da richtig liege und in wie fern es dir hilft, aber mit includieren von Q_Object wird das verwalten und abarbeiten der Zeigerelemente automatisch erleigt. Du solltest aber auch vom Programm her die Elemente selbst auflösen können.

Dann dein 2. Problem:

Mit der Connect Funktion verbindst du einen Signal mit einem Slot. Die Connect Funktion selber ist soviel ich weiß in qobejct defeniert. So viel ich weiß übernimmt das Steuerelement, das selber von qwidget abgeleitet ist und das wiederum von qobject das aufnehmen von signalen. über qobject wird bei einem signal dann über die connect funktion die funtion also der slot aufgerufen. Ich gehe aber davon aus das das Steuelement auf die Ereignisse reagiert und nicht abtastet.

Ich gebe aber keine Garantie auf meine Antowrt, da ich auh noch nicht lang dabei bin

Viel Spaß weiterhin byby :0)
 
Schreib deinen Quellcode mal in code Klammern, nicht mit Quote

Das dürfte der Formatierung zu gute kommen ;)
 
Problem zwei hab ich jetzt selber rausgefunden.
Ich hab diese if anweisung die ganze Zeit übersehen:
Code:
if ( rgbFarbe[nr] != wert )

Zu Problem1:
Heißt das, dass ich obkecte die von qobject abgeleitet sind mit delete nicht löschen muss??.
 
Das heißt es solange du die Anweisung Q_OBJECT mit einbindest. Dann wird beim Destruktor automatisch das Löschen vorgenommen.


:0) Mit Lösung 2 lag ich aber nciht Falsch oder? Sonst müsste ich meine Gedanken nähmlich auch nochmal überdenken :0)
 
JennaJamson schrieb:
Das heißt es solange du die Anweisung Q_OBJECT mit einbindest. Dann wird beim Destruktor automatisch das Löschen vorgenommen.

Ganz sicher? AFAIK werden, wenn man ein Widget mit delete löscht, auch alle childs dieses Widgets gelöscht. Das oberste Widget in einer Hierarchie muß man aber immer noch von Hand löschen, soweit ich weiß.
 
Ganz sicher? AFAIK werden, wenn man ein Widget mit delete löscht, auch alle childs dieses Widgets gelöscht. Das oberste Widget in einer Hierarchie muß man aber immer noch von Hand löschen, soweit ich weiß.

Ich hab deine Idee mal aufgegriffen. Möchtest du ein Widget löschen und es während eines Programmablaufs nicht mehr verwendet so kannst du es löschen, aber nach dem beenden eines Programms bleiben keine Reste übrig. Also alle Zeigerelemente werden gelöscht.
Automatisch verwaltet und gelöscht. Türlich kannst du es auch vorzeitig löschen das stimmt. Aber mit dem Q_OBJECT solllte nach Programmende alles gelöscht werden.

Mal eine andere Frage : Was heißt AFAIK? Bin nicht so der Helle tut mir leid. byby :0)

Du kannst es aber rein theoretisch auch testen glaub ich. Wenn du die Speicheradresse speicherst das Programm schließt und dann mit dem nächsten Programm wieder den Zeiger mit der Adresse füllst und die Daten nciht mehr vorhanden sind, soltest du einen Fheler bekommen.
 
JennaJamson schrieb:
Ich hab deine Idee mal aufgegriffen. Möchtest du ein Widget löschen und es während eines Programmablaufs nicht mehr verwendet so kannst du es löschen, aber nach dem beenden eines Programms bleiben keine Reste übrig. Also alle Zeigerelemente werden gelöscht.
Automatisch verwaltet und gelöscht. Türlich kannst du es auch vorzeitig löschen das stimmt. Aber mit dem Q_OBJECT solllte nach Programmende alles gelöscht werden.

Nach dem Programmende werden IMMER alle Zeiger gelöscht, ob Du nun deletest oder nicht. Schlimm wird es nur, wenn der Prozeß abschmiert und Du denn Speicher nicht mehr löschen kannst. Oder wenn Dein Programm immer weiter läuft und per new neuen Kram erzeugt, ohne den alten richtig zu löschen. Irgendwann ist dann der Speicher voll und der Rechner meldet Dir ein SIGSEG

JennaJamson schrieb:
Mal eine andere Frage : Was heißt AFAIK? Bin nicht so der Helle tut mir leid. byby :0)

As Far As I Know = Soweit ich weiß

JennaJamson schrieb:
Du kannst es aber rein theoretisch auch testen glaub ich. Wenn du die Speicheradresse speicherst das Programm schließt und dann mit dem nächsten Programm wieder den Zeiger mit der Adresse füllst und die Daten nciht mehr vorhanden sind, soltest du einen Fheler bekommen.

Nein, so funktioniert das nicht. Du hast nur einen virtuellen Speicher, und wie dieser auf den physikalischen abgebildet wird, darauf hast Du keinen Einfluß. Zumal jeder Prozeß war dieselben Zeiger benutzt, diese sich aber nur auf seine eigenen Speichersegmente beziehen-
 
Es tut mir leid und danke dir dafür das du mich darauf aufmerksam gemacht hast. Ich hab es gerad nachgelesen und Q_OBJECT ist ein Makro das erst die die Funktion der erstellung von Slots zulässt. Ich entschuldige mich und hoffe der her des der es hire gepostet hat ließt das. Ich lag falsch.

Naja jetzt weiß ich es besser. Danke an haukrinn. Hab mich wohl verlesen. *schnief aber einen schönen tag noch und byby :0) *schäm
 
Ok soweit ab ich jetzt glaub ich alles verstanden.
Also ein elternloses widget muss ich von Hand löschen außer es ist das mainwidget von einem qapplication object.
Dann noch eine Frage, warum benutzt man überhaupt für widgets immer einen pointer mit zugewiesenem Speicher, anstatt einer normalen variable??
 
Oben