Seite 1 von 1

[gelöst]Problem mit Gültigkeitsbereich

Verfasst: 11. November 2007 22:49
von qtNiko
hallo,

ich stehe irgendwie auf dem Schlauch. Der Compiler meldet einen Fehler, der auf ein Problem des Gültigkeitsbereiches hinweist, und ich weiß wirklich nicht warum.
meine Konfiguration: Suse Linux 10.1, Eclipse 3.1.1 mit CDT3.0.2, QT4.2.3

1. mit Qt Designer einen Dialog erzeugt, objectName: fParams
der Dialog enthält ein QTableWidget namens fParam_list

2. uic erzeugt aus der ui-Datei paramview.ui die Datei ui_paramview.h, die verkürzt auf das wesentliche, so aussieht:

Code: Alles auswählen

class Ui_fParams
{
public:
    ...
    QTableWidget *fParam_list;
    ...
    void setupUi(QDialog *fParams)
    {
    ... }
}

namespace Ui {
    class fParams: public Ui_fParams {};
}
dazu mein h-File fParams.h, in dem eine Subclass mit einfacher Vererbung definiert wird:

Code: Alles auswählen

...
#include <QDialog>
#include "ui_paramview.h"

class fParameter : public QDialog
{ 
	Q_OBJECT
	
	public:
	  fParameter(QWidget *parent=0);
	  QStringList paramNames;
	private:
	  Ui::fParams uifP;
        ...
}
und schließlich fParams.cpp:

Code: Alles auswählen

...
#include "fParams.h"

fParameter::fParameter(QWidget *parent) : QDialog(parent) { 
	uifP.setupUi(this);
	...
	paramNames << "param1" << "param2" << "param3" << "param4" << "param5" 
			   << "param6" << "param7" << "param8" << "param9" << "param10";
	
	uifP.fParam_list->setVerticalHeaderLabels(&paramNames);   //<- hier kommt der Fehler
        ...
}
Bei der letzten Zeile von fParams.cpp meldet nun der Compiler:

error: no matching function for call to ‘QTableWidget::setVerticalHeaderLabels(QStringList*)’

Das Hauptfenster, wo ich diesen Dialog aufrufen möchte, wird durch eine Klasse 'SimuDesign' dargestellt. Dort kommt eine ähnliche Fehlermeldung. Zunächst aber der Code:
Um den Dialog aufzurufen, enthält die Klassendefinition für SimuDesign im h-File des Hauptfensters :

Code: Alles auswählen

...
void on_pushButtFParam_clicked();  // autoconnect
...
fParameter *fParList;   //
...
Im cpp-File des Hauptfensters SimuDesign rufe ich durch Klicken auf einen Button den entsprechenden Slot auf:

Code: Alles auswählen

...
void SimuDesign::on_pushButtFParam_clicked() {
	fParList.exec();      //<- hier kommt der Fehler
}
In der letzten Zeile (fParList.exec() ) meldet der Compiler:
error: request for member ‘exec’ in ‘((SimuDesign*)this)->SimuDesign::fParList’, which is of non-class type ‘fParameter*’

Das verstehe ich nicht. fParList ist doch im h-file als type 'fParameter' definiert, oder was?

Hat jemand Tipps, um den Knoten zu lösen?
Ich wäre sehr dankbar dafür.

Verfasst: 11. November 2007 22:55
von qtNiko
hi,

ich muss noch schnell nachschicken, dass die Datei, in der die Klasse SimuDesign definiert wird, natürlich ein
#include "fParams.h"
enthält.

Verfasst: 12. November 2007 17:21
von solarix
Zu dem 2. Problem:

Code: Alles auswählen

 fParameter *fParList; 
[...]
 fParList.exec();      //<- hier kommt der Fehler 
Das Ding ist ein Pointer(!) der Klasse fParameter.... reicht das als Antwort? :wink:

Zu dem 1. Poblem:
Ich bin nicht sicher ob dir die Idee hinter der UI-Generator-Klasse (in deinem Fall "Ui_fParams") klar ist.. die Klasse soll dir eine Oberfläche (z.B. Dialog oder Widget..) initialisieren... nichts weiter. Ausser der "setupUi()"-Methode brauchst du da also gar nichts weiter. Die Klasse erstellt alle Widgets (Knöpfe, Tabelle, Bildchen und all das farbige Zeugs). Die Anwendung ist also wie folgt:

Code: Alles auswählen

...
#include "fParams.h"
#include "ui_paramview.h"

fParameter::fParameter(QWidget *parent) : QDialog(parent) {
   Ui::fParams uifP; 
   uifP.setupUi(this); // ab jetzt ham mer die GUI und brauchen uifP nicht mehr..
   ...
} 
Wie also weiter? Im Designer hast du nun z.B. allen Elementen Namen gegeben. Über diese Bezeichnungen ermittelst du nun die Pointer auf die Instanzen dieser Elemente. Ich gehe also z.B. davon aus, dass du da ein QTableWidget drauf hast:

Code: Alles auswählen

fParameter::fParameter(QWidget *parent) : QDialog(parent) {
   Ui::fParams uifP; 
   uifP.setupUi(this); 
   QTableWidget *table = findChild<QTableWidget*>("Tabellenname");
   Q_ASSERT(table); // Beenden falls keine Tabelle vorhanden..
   
  paramNames << "param1" << "param2" << "param3" << "param4" 
     << "param5" << "param6" << "param7" << "param8"
     << "param9" << "param10";
   
   table->setVerticalHeaderLabels(paramNames); 
} 
Des weiteren darfst du nicht

Code: Alles auswählen

table->setVerticalHeaderLabels(&paramNames); // call by address
schreiben, weil da ne Referenz, nicht eine Adresse benötigt wird (ersichtlich am Funktionsprototypen in der Trolltech-Doku)

... irgendwas verstanden?

Verfasst: 12. November 2007 22:09
von qtNiko
hallo,

danke für die Antwort. Jetzt komme ich weiter!

zu Problem 2: ich bin zerknirscht :cry: aber einem Anfänger sei es noch einmal verziehen

zu Problem 1:
Ich habe es nach deinem Beispiel gemacht, und das Programm wird fehlerfrei compiliert!
Leider gibt es noch irgend ein Problem, denn beim Starten stürzt es ab - das kommt als nächstes dran.

Jetzt noch mal zu Problem 1:
Ein "findChild" ist mir bis jetzt noch nicht untergekommen. Ich habe mich an einem Beispiel im Qt-Assistent orientiert. Dort heißt es unter Qt Designer Manual, "Using forms and components, The Single Inheritance Approach", im h-File zur Definition der abgeleiteten Klasse:

Code: Alles auswählen

...
private:
     Ui::ImageDialog ui;
...
Und dann im cpp-File der Constructor:

Code: Alles auswählen

...
ImageDialog::ImageDialog(QWidget *parent)
     : QDialog(parent)
 {
     ui.setupUi(this);

     ui.colorDepthCombo->addItem(tr("2 colors (1 bit per pixel)"));
     ui.colorDepthCombo->addItem(tr("4 colors (2 bits per pixel)"));
     ui.colorDepthCombo->addItem(tr("16 colors (4 bits per pixel)"));
     ui.colorDepthCombo->addItem(tr("256 colors (8 bits per pixel)"));
     ui.colorDepthCombo->addItem(tr("65536 colors (16 bits per pixel)"));
     ui.colorDepthCombo->addItem(tr("16 million colors (24 bits per pixel)"));

     connect(ui.okButton, SIGNAL(clicked()), this, SLOT(accept()));
...
Hier wird ui (bei mir uifP) weiterverwendet, um eine ComboBox namens colorDepthCombo zu füllen. Diese ComboBox

Verfasst: 12. November 2007 22:23
von qtNiko
hallo,

danke für die Antwort. Jetzt komme ich weiter!

zu Problem 2: ich bin zerknirscht :cry: aber einem Anfänger sei es noch einmal verziehen

zu Problem 1:
Ich habe es nach deinem Beispiel gemacht, und das Programm wird fehlerfrei compiliert!
Leider gibt es noch irgend ein Problem, denn beim Starten stürzt das Programm ab - das kommt als nächstes dran.

Jetzt noch mal zu Problem 1:
Ein "findChild" ist mir bis jetzt noch nicht untergekommen. Ich habe mich an einem Beispiel im Qt-Assistent orientiert. Dort heißt es unter Qt Designer Manual, "Using forms and components", "The Single Inheritance Approach", im h-File zur Definition der abgeleiteten Klasse:

Code: Alles auswählen

class ImageDialog : public QDialog
 {
     Q_OBJECT

 public:
     ImageDialog(QWidget *parent = 0);

private:
     Ui::ImageDialog ui;        // analog dazu habe ich es auch gemacht
}
Und dann im cpp-File der Constructor:

Code: Alles auswählen

ImageDialog::ImageDialog(QWidget *parent)
     : QDialog(parent)
 {
     ui.setupUi(this);

     ui.colorDepthCombo->addItem(tr("2 colors (1 bit per pixel)"));
     ui.colorDepthCombo->addItem(tr("4 colors (2 bits per pixel)"));
     ...
     connect(ui.okButton, SIGNAL(clicked()), this, SLOT(accept()));
     ... 
}
Hier wird ui (bei mir uifP) weiterverwendet, um eine ComboBox namens colorDepthCombo zu füllen, ohne ein findChild. Diese ComboBox wurde vorher (einige Lektionen vorher) mit dem Designer erstellt. Wenn in diesem Beispiel die ComboBox mit ui.colorDepthCombo->... funktioniert, warum dann nicht in meinem Programm?

Natürlich gibt es immer mehrere Wege. Zunächst bin ich auch froh, überhaupt einen funktionierenden zu finden, aber ich würde doch gerne verstehen, was an meinem Weg falsch war. Oder ist gar das Beispiel fehlerhaft?

Verfasst: 12. November 2007 22:28
von qtNiko
Entschuldigung,

das Doppelposting war ein Versehen.
Ich wollte nur einige Tabs in den Text einfügen ...

Verfasst: 12. November 2007 22:47
von solarix
zu Problem 2: ich bin zerknirscht .. aber einem Anfänger sei es noch einmal verziehen
Jain... das sind C Grundkenntnisse.. ich rate dir dringend, das Kapitel über Pointer (vermutlich 1 oder 2) deines Lieblings-C-Buches zu lesen... oder Google zu benutzen...

Nochmals zu Problem 1:
Wenn das so im Manual deiner Qt-Version steht, dann arbeite ruhig damit (im Qt 4.3 Manual fehlt dieser Code jedoch...). Ich halte findChild trotztdem für schöner, weil du die Elemente in der GUI umbennennen kannst und im Code nur eine einzige Stelle zu ändern brauchst...

Wie dem auch sei: in diesem Fall nehm ich die Aussage zurück und behaupte, dass dein Compiler dir sagen möchte, dass er die Funktion

Code: Alles auswählen

QTableWidget::setVerticalHeaderLabels(QStringList*)
nicht finden kann, weil du da einen Pointer angegeben hast und von Qt eine Referenz verlangt wird:

Code: Alles auswählen

void QTableWidget::setVerticalHeaderLabels ( const QStringList & labels )
Aber das geht in die gleiche Richtung wie Problem #2.. lies zuerst nach was Pointer und Referenzen sind..

hth
solariX