Seite 1 von 1

Compiler mag QFile nicht, oder?

Verfasst: 8. Juni 2007 01:12
von qtNiko
Ich stehe vor einem Rätsel :(

Meine Anwendung besteht aus einem Hauptfenster, das mit QtDesigner4 erstellt wurde, und den Dateien ipcsimu.h sowie ipcsimu.cpp (weitere Dateien spielen hier keine Rolle).
Der Inhalt in verkuerzter Form (relevante Zeilennr. eingefuegt):
ipcsimu.h:

Code: Alles auswählen

...
#include "ui_ipcsimu.h"
...

class ipcSimuDesign : public QMainWindow, private Ui::ipcSimu_Qt4
{
	Q_OBJECT
	...  diverse Definitionen
	
	private:
	...
35:	QFile swkonfigDatei, refmodDatei;
	// diese Dateivariablen werden später in ipcsimu.cpp gebraucht
};
Beim Compilieren erhalte ich folgenden Fehler:

ipcsimu.h:35: error: 'QFile' does not name a type
make: *** [ipcsimu_main.o] Fehler 1

Ich kann mit der Fehlermeldung nichts anfangen. Was bedeutet es, dass er einen Typ nicht benennen kann? In Beispielen in meinem Qt-Buch gibt es genau solche Definitionen zu Hauf.
Falls es interessiert, wie die in Zeile 35 definierten Dateivariablen verwendet werden, hier die ipcsimu.cpp (woanders kommen sie nicht vor):

Code: Alles auswählen

#include <QtGui>
#include <iostream>
#include <QFile>
#include "ipcsimu.h"
...  u.a. constructor, der einen Slot 'steuerAblauf()' definiert

void ipcSimuDesign::steuerAblauf(int buttNr)  {
	...
		// Dateien initialisieren, d.h. aus oberste Einträge aus den ComboBoxen:
		QString fileMiss="fehlende Dateien:";
		swkonfigDatei.setFileName(comboBox_swkonfig->currentText());
		if (!swkonfigDatei.open(QIODevice::ReadOnly)) fileMiss += " SW-Konfig,";
		refmodDatei.setFileName(comboBox_refmod->currentText());
		if (!refmodDatei.open(QIODevice::ReadOnly)) fileMiss += " Refmod,";
		...
		if (fileMiss.length()>18) {
			if (fileMiss.endsWith(",")) fileMiss=fileMiss.remove(fileMiss.length(),1);
		    QMessageBox::warning(this, tr("IPC-Simulation"), fileMiss, QMessageBox::Ok);
		}
	...
}
Ich hatte auch schon Fehlermeldungen in ipcsimu.cpp bei den Zeilen, wo die Dateivariablen swkonfigDatei und refmodDatei vorkommen, die sinngemäß bedeuteten, dass swkonfigDatei und refmodDatei keine Klassendefinitionen seien.
Das muss dann ein Folgefehler aus der Zeile 35 von ipcsimu.h gewesen sein.
Mittlerweilen meldet der Compiler aber nur noch für ipcsimu.h, Zeile 35, einen Fehler, ohne dass ich wüsste, auf welche Änderung hin die weiteren Fehlermeldungen verschwunden sein könnten - ich arbeite unter Suse Linux10.1 mit Eclipse und CDT.

Liegt der Fehler wirklich in der Zeile, wo der Fehler gemeldet wird, oder kann er von woanders herkommen? aber woher?

Verfasst: 8. Juni 2007 06:33
von Christian81
Was nützt es <QFile> im Source einzubinden wenn du es im Header benötigst?

Verfasst: 8. Juni 2007 08:50
von qtNiko
Das verstehe ich jetzt nicht.

Ich habe doch QFile in der Header-Datei, ipcsimu.h, innerhalb der Klassendefinition definiert, so wie diverse andere Objekte und Variablen auch. Die als Code gezeigten Stellen sind die einzigen, wo die Namen swkonfigDatei, etc. vorkommen.
Verwendet werden die im Headerfile definierten Datei-Objekte dann später im Source, in ipcsimu.cpp.

Verfasst: 8. Juni 2007 08:56
von Christian81
Ich würde sagen Basic C.
Wenn ich eine Klasse/Struktur verwenden will, muss ich auch den Header einbinden in dem die Klasse/Struktur definiert ist... woher soll der Compiler sonst wissen was er damit machen soll?

Verfasst: 9. Juni 2007 00:47
von qtNiko
High, jetzt ist es mir klar geworden: es fehlte ein #include <QFile>

Danke für die Hilfe, aller Anfang ist schwer :(

Nachdem das Programm nun erzeugt wird, taucht ein neues Problem auf.

Meine Anwendung enthält einen TextViewer zur Darstellung von ASCII-Dateien. Die Klassendefinition steht in textview.h:

Code: Alles auswählen

...
#include "ui_textview.h"	/* enthaelt alle noetigen includes */

class TextViewer : public QWidget, public Ui::TextView
{
	Q_OBJECT
	
	public:
	TextViewer(QWidget *parent=0);
	
	private slots:
	...
Der TextViewer wurde mit QtDesigner4 erstellt und besteht aus einem Widget, das folgendes enthält:
TextEdit für Textdarstellung,
CheckBox zur Auswahl Zeilenumbruch oder nicht
PushButton zum Beenden

Der Aufruf des TextViewer sieht so aus (aus Beispielen zusammengestellt):

Code: Alles auswählen

	...
	TextViewer *viewFile = new TextViewer(this);	/* neuer TextEditor */
 	viewFile->show();
 	if (...)) {  /* alles auf einmal lesen und ausgeben */
 		readText = inText.readAll();
 		viewFile->textDisplay->insertPlainText(readText);
	...
Im Designer sieht alles so aus, wie erwartet, aber beim Programmlauf erscheint nicht das gesamte Fenster des TextView mit o.g. Inhalt, sondern nur der Inhalt allein, also TextEdit, CheckBox und PushButton ohne das Fenster drumherum! Man sieht auch den ausgegebenen Text, aber wo bleibt das Widget selber mit Rahmen und Titelzeile?

Ein Effekt im Designer wird mir langsam lästig:
Wenn ich z.B. eine existierende Form laden will, dann sehe ich im Datei-Öffnen-Dialog zunächst die Verzeichnisnamen in voller Länge. Gehe ich aber eine Stufe tiefer in ein Verzeichnis, dann werden die Namen bei 8-10 Zeichen, je nach vorkommenden Buchstaben, abgeschnitten und '...' angehängt.
Schalte ich jedoch zwischendurch das Dateifilter auf *.*, dann sind die Namen wieder in voller Länge da.
Ich finde im Designer keine Einstellungsmöglichkeit für Namenslängen.
Was kann man da machen?

Verfasst: 9. Juni 2007 08:17
von upsala
Könnte es sein, daß du keine Layouts verwendest oder das dein Widget zu klein für seinen Inhalt ist?

Verfasst: 10. Juni 2007 00:02
von qtNiko
Ich habe beim TextViewer die CheckBox und den PushButton zusammen mit einigen horizontal spacer in einem horizontalen Layout und diese dann mit dem TextEdit in einem vertikalen Layout zusammengefasst.
Dies hatte ich schon so eingerichtet. Jetzt habe das Widget extra größer gemacht, sodass um die genannten Teile sogar noch ein kleiner Rand frei bleibt, aber mit dem gleichen Ergebnis. An der Größe kann es kaum liegen, da der TextEdit innerhalb des TextViewer den Text bei Nutzung der ScrollBars komplett anzeigt.

Allerdings hänge ich noch an einem Problem. Ich habe kleine Dateien, die mit readAll() in einen QString eingelesen und im TextViewer mit insertPlainText() dargestellt werden - ok.
Es gibt aber eine ziemlich große ASCII-Datei (mehrere MB) mit langen Zeilen von ca. 1200 Zeichen, die ich zeilenweise jeweils mit readLine() einlesen und ebenfalls mit insertPlainText() darstellen möchte. Hierbei bleibt das ganze Programm ohne Fehlermeldung stecken und reagiert auf nichts mehr.

Aber, die Frage nach Verwendung von Layouts macht mich stutzig. Ist es denn erforderlich, Layouts zu verwenden?
Meine Anwendung, aus der heraus ich den TextViewer aufrufe, besteht aus einer sehr umfangreichen Benutzerschnittstelle gänzlich ohne Layouts.
Muss man denn alles in Layouts packen?

Verfasst: 10. Juni 2007 00:28
von upsala
Dann häng mal das ui-File an.

Schon mal über die Verwendung eines Debuggers nachgedacht?

Wenn du keine Layouts verwendest, wie positionierst du deine Widgets dann?

Verfasst: 12. Juni 2007 00:15
von qtNiko
Uff, habe gerade einen Umzug hinter mir. Daher so lange keine Antwort.

Nun, das Positionieren mach ich alles im QtDesigner. Bisher sieht mein Hauptfenster auch immer so aus, wie erwartet, das Fenster des Textviewers allerdings nicht.
Wie gewünscht, hängt das ui-File im Attachment.

Debuggen würde ich tatsächlich gerne. Mit Eclipse unter Suse Linux10.1 habe ich es bisher leider noch nicht hinbekommen. Das wird auch noch eine Baustelle :?

Verfasst: 12. Juni 2007 15:34
von upsala
Selektier mal das TextView-Widget und weis diesem ein Layout zu.

Verfasst: 13. Juni 2007 23:31
von qtNiko
Im QtDesigner lässt sich das Hauptfenster des TextView nicht markieren, um es in ein Layout einzufügen. Aber ich habe mir mal das File ui_textview.h angesehen, und dabei fielen mir einige Dinge auf. Zunächst der Code:

Code: Alles auswählen

...  #ifndef und diverse #includes

class Ui_TextView
{
public:
    QWidget *layoutWidget;
    QVBoxLayout *vboxLayout;
    QTextEdit *textDisplay;
    QHBoxLayout *hboxLayout;
    QSpacerItem *spacerItem;
    QCheckBox *chBoxZeilenumbr;
    QSpacerItem *spacerItem1;
    QPushButton *pButtonOK;
    QSpacerItem *spacerItem2;

    void setupUi(QWidget *TextView)
    {
    TextView->setObjectName(QString::fromUtf8("TextView"));
    layoutWidget = new QWidget(TextView);
    layoutWidget->setObjectName(QString::fromUtf8("layoutWidget"));
    layoutWidget->setGeometry(QRect(1, 1, 591, 451));
    vboxLayout = new QVBoxLayout(layoutWidget);  < ----------------------------------- ist das so richtig?
    vboxLayout->setSpacing(6);
    vboxLayout->setMargin(0);
    vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
    textDisplay = new QTextEdit(layoutWidget);
    textDisplay->setObjectName(QString::fromUtf8("textDisplay"));
    textDisplay->setLineWrapMode(QTextEdit::NoWrap);
    textDisplay->setReadOnly(true);
    textDisplay->setAcceptRichText(false);

    vboxLayout->addWidget(textDisplay);

    hboxLayout = new QHBoxLayout();
    hboxLayout->setSpacing(6);
    hboxLayout->setMargin(0);
    hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
    spacerItem = new QSpacerItem(81, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

    hboxLayout->addItem(spacerItem);

    chBoxZeilenumbr = new QCheckBox(layoutWidget);
    chBoxZeilenumbr->setObjectName(QString::fromUtf8("chBoxZeilenumbr"));

    hboxLayout->addWidget(chBoxZeilenumbr);

    spacerItem1 = new QSpacerItem(121, 25, QSizePolicy::Expanding, QSizePolicy::Minimum);

    hboxLayout->addItem(spacerItem1);

    pButtonOK = new QPushButton(layoutWidget);
    pButtonOK->setObjectName(QString::fromUtf8("pButtonOK"));
    pButtonOK->setCheckable(true);
    pButtonOK->setDefault(true);

    hboxLayout->addWidget(pButtonOK);

    spacerItem2 = new QSpacerItem(91, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

    hboxLayout->addItem(spacerItem2);


    vboxLayout->addLayout(hboxLayout);

--------------------------> nach diversen Beispielen fehlt hier ein Statement: layoutWidget->setLayout(vboxLayout);
    retranslateUi(TextView);

    QSize size(599, 463);
    size = size.expandedTo(TextView->minimumSizeHint());
    TextView->resize(size);


    QMetaObject::connectSlotsByName(TextView);
    } // setupUi

    void retranslateUi(QWidget *TextView)
    {
    TextView->setWindowTitle(QApplication::translate("TextView", "Form", 0, QApplication::UnicodeUTF8));
    textDisplay->setDocumentTitle(QApplication::translate("TextView", "Text Display", 0, QApplication::UnicodeUTF8));
    chBoxZeilenumbr->setText(QApplication::translate("TextView", "Zeilenumbruch am Fenster", 0, QApplication::UnicodeUTF8));
    pButtonOK->setText(QApplication::translate("TextView", "OK, Beenden", 0, QApplication::UnicodeUTF8));
    Q_UNUSED(TextView);
    } // retranslateUi

};

namespace Ui {
    class TextView: public Ui_TextView {};
} // namespace Ui
Dieser Code wurde vom uic erzeugt. Ist das alles so richtig, und fehlt da nicht ein layoutWidget->setLayout(vboxLayout);