KDE Anwendungs Tutorials: Definition der Dokumente

Weiter Zurück Inhaltsverzeichnis

### 8. Definition der Dokumente

Der erste Schritt beim Erstellen einer Applikation, die auf dem Document-View Modell basiert, sollte immer sein, sich zu überlegen, welche Arten von Daten die Anwendung verwalten muß. Dies entscheidet, wie die View Klasse aussehen wird, aber insbesondere, wie die Dokumentklasse Daten in und aus Dateien lesen und schreiben wird und welche Methoden angeboten werden, um die Daten zu manipulieren. Da KScribble eine einfache Zeichenanwendung sein wird, die mit graphischen Daten umgeht, werden wir die Qt Klasse `QPixmap` dazu verwenden, unsere Daten zu speichen während wir editieren. `QPixmap` bietet auch einfache Methoden, Bilder in und aus Dateien zu lesen und zu schreiben, so daß die Serialisation mit zwei Zeilen erreicht werden kann, eine zum Lesen und eine zum Schreiben. Weiterhin müssen wir einen Stift definieren, der in ein Dokument schreibt, seine Breite und Farbe einstellen und der View Klasse ermöglichen, den Stift anzusprechen - tatsächlich wollen Sie, daß die Ansicht die Zeichenmethoden anbietet, aber das Dokument als zentrales Element für alle Ansichten, muß das Original des Stiftes besitzen, da sonst verschiedene Ansichten desselben Dokuments verschiedene Stifte verwenden würden!

Daher fügen wir zur Definition der Arbeitsweise unserer Dokumentklasse eine Instanz von `QPixmap` und eine von `QPen` hinzu und editieren die Methoden `newDocument()`, `openDocument()` und `saveDocument()`.

### 8.1 Hinzufügen der Instanzen

Öffnen Sie die Datei `kscribbledoc.h` durch Auswahl in einer der Baumansichten oder durch einen Klick in der Klassenansicht über `KScribbleDoc`. Dann fügen Sie die mit -> markierten Zeilen aus dem folgenden Codeausschnit hinzu:

    ->  #include <qpixmap.h>
    ->  #include <qpen.h>

        class KScribbleDoc
        {

    ->      protected:

    ->        QPen currentPen(){ return pen;};

    ->              int penWidth()
    ->                      { return pen.width(); }

          public slots:
            void updateAllViews(KScribbleView *sender);

            protected:

    ->              QPixmap buffer;

          private:
    ->              QPen pen;
            /** the modified flag of the current document */
            bool modified;

Wie Sie sehen, haben wir pen und buffer, sowie `currentPen()` und `penWidth()` hinzugefügt. Da pen als private deklariert ist, bieten wir ein Möglichkeiten sowohl auf den Stift selber, als auch auf die Stiftbreite zuzugreifen. Da diese bereits in der Klassendeklaration implementiert sind, müssen wir sie nicht der Implementationsdatei hinzufügen, der wir uns nun zuwenden.

### 8.2 Initialisierung des Dokuments

Wählen Sie die Methode `newDocument()` in der `KScribbleDoc`-Klasse um zur Methodendeklaration zu springen. Hier fügen wir nur eine, mit dem Pfeil markierte Zeile ein:

      kscribbledoc.cpp

      bool KScribbleDoc::newDocument()
      {
        /////////////////////////////////////////////////
        // TODO: Add your document initialization code here
    ->  pen=QPen( Qt::black, 3 );
        /////////////////////////////////////////////////
        modified=false;
        return true;
      }

Dies initialisiert den Stift mit der Farbe Schwarz und einer Weite von drei Pixeln; die `QPen` Klasse hat noch einige weitere Konstruktoren, aber dieser hier reicht für unsere Zwecke.

### 8.3 Implementierung der Serialisation

Was noch zu tun ist, ist zu definieren, wie wir unsere Bilder öffnen und speichern wollen. Dies wird in den entsprechenden Methoden erledigt:

        bool KScribbleDoc::openDocument(const QString &filename, const char *format /*=0*/)
        {

            QFile f( filename );
    ->     //if ( !f.open( IO_ReadOnly ) )
    ->     //       return false;
         /////////////////////////////////////////////////
         // TODO: Add your document opening code here
    ->     if(!buffer.load( filename, "PNG" ))
    ->      return false;
         /////////////////////////////////////////////////
    ->     //f.close();

        bool KScribbleDoc::saveDocument(const QString &filename, const char *format /*=0*/)
        {
          QFile f( filename );
    ->     // if ( !f.open( IO_WriteOnly ) )
    ->     //       return false;

          /////////////////////////////////////////////////
          // TODO: Add your document saving code here
    ->      if(!buffer.save( filename, "PNG" ))
    ->              return false;
          /////////////////////////////////////////////////

    ->      //f.close();

Fügen Sie wieder die Zeilen mit dem Pfeil Ihrem Code hinzu. Was wir getan haben, ist die Zeilen, in denen `Dateiname` geöffnet wird, auszukommentieren, weil dies automatisch von den Laden- und Speichermethoden von `QPixmap` erledigt wird, die wir stattdessen hinzufügen. Andere Dokumente mögen Dateien öffnen und deren Inhalt ( Textzeilen oder was auch immer) lesen, weshalb die `QFile` Methoden schon im Frame enthalten sind.Da `save()` und `load()` bei Erfolg einen Boolschen Wert zurückliefern, Geben wir false zurück, wenn nicht, so daß der Rest der Anwendung einen Returnwert erhält und Warnungen ausgibt, wenn die Operation nicht erfolgreich war. Die `load()` und `save()` Methoden sind nun schon in `QPixmap` enthalten. Sie benötigen den Dateinamen und das Format als Argument; die Quellen rufen die Dokument Methoden jedoch noch nicht mit dem Format auf. Wenn nur ein Format verwendet wird, reicht es, dieses hier zu setzen, andere Methoden könnten das Format zum Beispiel ermitteln - aber wir werden später noch einmal darauf zurückkommen. Für jetzt verwenden wir "PNG" als Format; sehen Sie unter `QImageIO` nach, um mehr über Bildformate zu erfahren.

Nun sind wir fast mit der Definition unserer Dokumentstruktur fertig. Der `QPixmap` Puffer dient uns als Speicher für unser Originalbild, während wir daran arbeiten. Der Stift ist gültig für alle Ansichten, die mit dem Dokument verbunden sind. Beachten Sie, daß die Initialisierung des Stiftes in `newDocument` erfolgt. Diese Methode wird immer intern nach dem Konstruktor aufgerufen, Sie sollten also dort die Instanzinitialisierungen vornehmen, wie wir es mit dem Stift gemacht haben.

Im nächsten Kapitel werden wir uns der View Klasse widmen, um zu definieren, wie die Ansicht mit dem Benutzer kooperieren soll und wie sie auf das Dokument zugreift, und dann sind wir bereit zu zeichnen !

Weiter Zurück Inhaltsverzeichnis