The K Desktop Environment

Weiter Zurück Inhaltsverzeichnis

10. Erweiterung der GUI

Wie wir gesehen haben, haben wir KScribble bereits die Fähigkeit gegeben, Bilder mit der Dokumentklasse zu öffnen und zu speichern, haben durch Überladen virtueller Methoden Interaktion ermöglicht, und wir haben die erste Funktionalität erreicht- wir können auch Bilder zeichnen. Aber als wir die QPen Instanz erzeugt haben, haben wir vordefinierte Werte für den Stift verwendet; die Farbe ist Schwarz und die Breite ist auf 3 Pixel eingestellt. Da Sie für gewöhnlich diese Werte ändern können wollen, müssen wir die Haupt-GUI um Funktionen, diese Werte zu setzen, erweitern, je nachdem welches Fenster gerade aktiv ist und welches Dokument damit verbunden ist. Dieses Kapitel wird Ihnen daher zeigen:

Desweiteren fügen wir eine Methode hinzu, den Inhalt des gesamten Dokuments über das Menü zu löschen.

10.1 Hinzufügen des "Stift" Menüs

Wie der Name dieses Abschnittes schon sagt, werden wir hier ein Menü zum Setzen der Stiftwerte des Dokuments hinzufügen. Menüs, die in die Menüleiste eingefügt werden, sind Instanzen von QPopupMenu, und Sie können einen Blick darauf werfen, wie die aktuelle Menüleiste aufgebaut ist, wenn Sie zur KScribbleApp Klasse, Methode initMenubar() wechseln. Sie werden sehen, daß die Menüleistenelemente in der Reihenfolge ihres Erscheinens auf der Menüleiste erzeugt wurden, aber das ist nicht notwendigerweise so. Es gibt zwei Dinge, die für das Aussehen der Menüleiste wichtig sind:

Schließlich und endlich werden wir zuerst die Menüs erzeugen müssen, indem wir den Konstruktor aufrufen. Die Klassendeklaration enthält bereits die Zeiger auf die Popupmenüs, also werden wir zuerst das "Stift" Menü hier einfügen:


kscribbleapp.h

class KScribbleApp
{
.
.
  private:
    QPopupMenu* pPenMenu;

}

Jetzt werden wir das Menü selbst erzeugen. Ändern Sie die Implementation der Methode KScribbleApp::initMenuBar() und editieren Sie die, mit dem Pfeil markierten Zeilen:


void KScribbleApp::initMenuBar()
{
..

->  ///////////////////////////////////////////////////////////////////
->  // menuBar entry pen-Menu
->  pPenMenu = new QPopupMenu();
->  pPenMenu->insertItem(i18n("&Color"), ID_PEN_COLOR);
->  pPenMenu->insertItem(i18n("&Brush"), ID_PEN_BRUSH);

    menuBar()->insertItem(i18n("&Edit"), pEditMenu);
->  menuBar()->insertItem(i18n("&Pen"), pPenMenu);
    menuBar()->insertItem(i18n("&View"), pViewMenu);


->  connect(pPenMenu, SIGNAL(activated(int)), SLOT(commandCallback(int)));
->  connect(pPenMenu, SIGNAL(highlighted(int)), SLOT(statusCallback(int)));
}

Sie sehen, daß wir zunächst das Menü mit new QPopupMenu() erzeugen. Dann verwenden wir die insertItem Methode, zum Hinzufügen der Menüeinträge Color und Brush. Die sichtbaren Kommandos werden mit der Methode i18n() eingefügt, womit sichergestellt ist, daß Sie Ihre Applikation internationalisieren können. Als generelle Regel kann gesagt werden, daß Sie alle später sichtbaren Texte mit der Methode i18n() deklarieren sollten. Nur-Qt Programme, die Qt > 2.0 verwenden, benutzen dazu die Methode tr(), da Qt eigene Verfahren hat, Anwendungen zu internationalisieren. Das zweite Argument ist ein Makro, die ID des Menüeintrages. Diese ID ist eine Nummer, die wir mit #define in der resource.h, in der Sie auch die anderen bisher definierten ID's finden, setzen müssen. Es gibt auch den Weg, Menüs direkt einzufügen, indem Sie einen Slot mit dem gewählten Eintrag verbinden, aber das Framework dieser Anwendung verwendet ID's, um festzustellen, welche Aktion ausgewählt und markiert wurde. Deshalb muß jeder Menüeintrag, unbhängig davon, in welchem Popupmenü er erscheint, eine einzigartige Nummer besitzen, und da wir uns Nummern schlecht merken können, ist die Verwendung eines #define für die ID eine gute Lösung. Das Popupmenü wird nun ebenfalls mit insertItem() der Menüleiste hinzugefügt, und zwar mit einem Zeiger auf das Menü als zweitem Argument. Beachten Sie, daß wir das Popupmenü nach dem Edit- und vor dem Viewmenü eingefügt haben, es wird also später zwischen diesen beiden Menüs erscheinen. Was auch wichtig bei der Erstellung von Menüs ist, ist, daß sie dem Benutzer auch über Shortcuts zur Verfügung gestellt werden sollten; normalerweise sehen Sie in Menüs einen unterstrichenen Buchstaben, der zusammen mit ALT die entsprechende Funktion aufruft. Als Programmierer, müssen Sie diesen Buchstaben durch ein vorangestelltes "&" setzen, das "Pen" Menü wird also später durch drücken von ALT+P erreichbar sein. Innerhalb des Menüs kann der Benutzer auch nur den Buchstaben eingeben, um den entsprechen Menüpunkt auszuführen, Sie sollten also für die anderen Menüpunkte ebenfalls Tastaturkürzel zur Verfügung stellen. Achten Sie darauf, den Code zum Einfügen von Einträgen in Gruppen zusammenzuschreiben, die Sie überblicken können, damit Sie keine Kürzel doppelt verwenden (Dies ist auch für Ihre Übersetzer wichtig: In anderen Sprachen kommt das gewählte Kürzel vielleicht nicht im Menütext vor, der Übersetzer muß also auch wieder ein Kürzel auswählen).

In den letzten beiden Zeilen verbinden wir die Stiftmenüs mit zwei Slots: einen für das Menüsignal "aktiviert, Aktion ausführen" und einen für die Markierung des Menüeintrages. Dies ermöglicht es, eine Hilfemeldung in der Stauszeile anzuzeigen. Sie können sich die Methoden ansehen, die mit dem Menü verbunden sind. Sie enthalten Anweisungen, in denen die gesendete ID geprüft und die folgende Aktion aufgerufen wird. Was noch zu tun bleibt, ist die #define Anweisungen in die resource.h einzutragen:


 
resource.h ///////////////////////////////////////////////////////////////////
// Pen-menu entries
#define ID_PEN_COLOR                14010
#define ID_PEN_BRUSH                14020

Sie sehen, daß die Nummern für jeden Eintrag einzigartig sind. Sie müssen darauf achten, nicht zweimal dieselbe Nummer zu vergeben. Sollte es aber dennoch einmal versehentlich passieren, wird Sie der Compiler über die Redefinition informieren.

Das ist zum jetzigen Zeitpunkt alles, das Sie zum Hinzufügen eines neuen Menüs tun müssen. Die ausgeführten Aktionen sind: "Color" (Aufruf des Farbauswahldialogs) und "Brush" (Aufruf des Dialogs zum Setzen der Stiftbreite). Letzeren Dialog werden wir noch erstellen, aber zuerst werden wir im nächsten Kapitel auch die Werkzeugleiste um zwei Icons für diese Aktionen erweitern.

10.2 Hinzufügen von Knöpfen zur Werkzeugleiste

Wenn Sie neue Kommandos über Knöpfe in der Werkzeugleiste zur Verfügung stellen möchten, können Sie dies leicht mit der initToolbar() Methode der App Klasse tun. Hier entscheiden wir uns, je einen Knopf für die beiden Menüeinträge im Stiftmenü hinzuzufügen, aber diese Knöpfe brauchen Icons. Sie können sie entweder im KDE Verzeichnis "toolbar" finden, oder, wenn keins der Icons zu der Aktion paßt, sie selbst erzeugen. KIconEdit ist gut dafür geeignet Icons zu erstellen, also werden wir sie zuerst erzeugen. Wählen Sie "Neu" aus dem KDevelop Dateimenü, gehen Sie auf den Linux/KDE Tabulator und wählen Sie dann "Icon" als Dateityp. Das erste Icon nennen wir "pencolor.xpm". Nun müssen wir sagen, wo das Icon erzeugt werden soll. Drücken Sie den Verzeichnisauswahlknopf und wechseln Sie in das Verzeichnis mit Ihren KScribble Quelldateien. Dort erzeugen Sie ein neues Verzeichnis "toolbar". Wechseln Sie in dieses Verzeichnis und drücken Sie "OK". Das neue Icon wird erzeugt und automatisch mit KIconEdit innerhalb von KDevelop geöffnet. Zeichnen Sie etwas, daß dem Benutzer den Sinn des Knopfes zeigt, speichern Sie das Pixmap und wählen Sie dann den LFV / RFV in KDevelop. Wählen Sie das Icon mit der rechten Maustaste aus und gehen Sie im Popupmenü auf "Eigenschaften". Sie sehen, daß das Icon der Distribution hinzugefügt wurde, damit es aber später von Ihrem Programm gefunden werden kann, müssen Sie das Installationsziel ebenfalls angeben. Markieren Sie die "installieren" Option und geben Sie dann darunter ein:

$(kde_datadir)/kscribble/toolbar/pencolor.xpm

Damit wird das Pixmap im data Verzeichnis der KDE Dateisystemhierarchie installiert, in der jede Anwendung ihr Unterverzeichnis mit zusätzlich benötigten Dateien hat. Icons müssen in einem Unterverzeichnis namens toolbar abgelegt werden, damit der icon loader die Pixmaps für Ihr Programm finden kann.

Wenn Sie damit fertig sind, wiederholen Sie die gleichen Schritte für das Icon zum Setzen der Stiftweite. Nennen Sie dieses Icon "penwidth.xpm".

Nun müssen wir nur noch Knöpfe auf der Werkzeugleiste erzeugen; fügen Sie dazu die markierten Zeilen Ihrem Code hinzu:


void KScribbleApp::initToolBar()
{
..
    toolBar()->insertButton(BarIcon("editcopy"), ID_EDIT_COPY, true, i18n("Copy"));
    toolBar()->insertButton(BarIcon("editpaste"), ID_EDIT_PASTE, true, i18n("Paste"));
    toolBar()->insertSeparator();
->  toolBar()->insertButton(BarIcon("pencolor"), ID_PEN_COLOR, true, i18n("Color") );
->  toolBar()->insertButton(BarIcon("penwidth"), ID_PEN_BRUSH, true, i18n("Width") );
->  toolBar()->insertSeparator();
    toolBar()->insertButton(BarIcon("help"), ID_HELP_CONTENTS, SIGNAL(clicked()),
..
}

Wir verwenden an dieser Stelle die Methoden von KToolBar um die Knöpfe einzufügen. Das erste Argument, BarIcon(), veranlaßt die Methode, das Icon für den Knopf zu laden. Was etwas ungewöhnlich erscheint ist, daß wir uns nicht um die Dateierweiterung zu kümmern brauchen. Das bevorzugte Format unter KDE 2 ist *.PNG, aber es funktioniert auch mit xpm's ( Sie könnten ImageMagick für die Konvertierung der Icons nach PNG verwenden, oder, zu einem späteren Zeitpunkt,KScribble !).

Das zweite Argument ist wiederum die ID. Die Kommandos werden dann automatisch aktiviert, da toolBar() bereits mit denselben Methoden verbunden ist wie die Menübar, über das Signal activated(). Das dritte Argument steht für "erreichbar" wenn wahr, "deaktiviert" wenn falsch; da die Knöpfe verfügbar sein sollen, setzen wir es auf wahr. Schließlich setzen wir noch eine Kurzinfo für die Knöpfe, die wir wieder in i18n() einschließen, um die Internationalisierung zu ermöglichen.

Nun sind Sie für's erste fertig. Die GUI ist, zumindest visuell, erweitert. Sie können KScribble wieder kompilieren und ausführen und sich anschauen, wie es aussieht- natürlich haben die neuen Elemente in der Menü- und in der Werkzeugleiste noch keine Funktion- dies wird sich aber im nächsten Abschnitt ändern. Sie werden vielleicht auch bemerken, daß die Icons, die wir hinzugefügt haben, nicht angezeigt werden. Dies liegt daran, daß wir KScribble nicht installiert haben, und so werden sie nicht gefunden. Alle anderen Icons werden bereits mit den KDE Bibliotheken geliefert, deshalb sind sie schon sichtbar.

10.3 Erzeugen des Dialogs für die Stiftweite

Da wir schon die Menüleisten- und Werkzeugleistenkommandos erstellt haben, müssen wir jetzt unseren ersten Dialog für das Setzen der Stiftweite erzeugen. Dazu wählen Sie "Neu" aus dem Dateimenü und dann "Qt/KDE Dialog". Geben Sie als Dialognamen kpenbrushdlg ein, die Erweiterung wird automatisch angehängt. Wählen Sie "OK" und der Dialogeditor öffnet ein leeres Widget, das den Hintergrund für unseren Dialog bilden wird. Wenn wir einen Dialog entwerfen, müssen wir uns überlegen, was der Benutzer wirklich braucht; in unserem Fall brauchen wir ein Label, das beschreibt, was geändert wird, eine Spinbox mit auf und ab Knöpfen zum Setzen der Stiftweite und drei weitere Knöpfe: einen zum Zurücksetzen der Weite, einen zum Abbrechen des Dialogs und einen zum Übernehmen des neuen Wertes - den "OK" Knopf. In dieser Reihenfolge werden wir die Elemente auch hinzufügen, was wichtig ist, weil der Fokus der Tabulatortaste der Reihenfolge folgt, in der die Widgets erstellt werden. D.h., wenn Sie mit dem "OK" Knopf anfangen, bringt uns das Drücken der Tabtaste zuerst zur Spinbox und dann zum "Cancel" Knopf - was so nicht erwartet wird. Der Tabfokus sollte den Elementen von oben nach unten und von links nach rechts folgen, also müssen wir den Dialog auch in dieser Reihenfolge erstellen. Um Elemente zum Dialog hinzuzufügen, wählen Sie den Widgets Tabulator im linken Panel. Dort werden alle verfügbaren Widgets durch Icons repräsentiert, damit Sie Ihren Dialog erstellen können. Ein Druck auf ein Widget Icon erzeugt das neue Element in der linken, oberen Ecke des Hauptwidgets. Von dort können Sie es mit der Maus zu der Position ziehen, an der Sie das Element haben wollen. Desweiteren können Sie die Einstellungen für das gewählte Widget im "Widgeteigenschaften" Panel auf der rechten Bilschirmseite vornehmen.

Das Label: Wählen Sie QLabel aus dem Widgettabulator und plazieren Sie es an Position x:50, y:20. Dann gehen Sie zum "General" Abschnitt in den Widgeteigenschaften. Ändern Sie den Text der Eigenschaft "Text" von "Label:" nach "Pen Width:". Passen Sie die Breite in x-Richtung dem Text des Labels an, ein Wert von 120 sollte reichen. Sie können dies entweder mit der Maus machen, oder den Wert im "Geometry" Abschnitt eingeben.

Die Spinbox: Wählen Sie QSpinbox und plazieren Sie sie rechts neben dem eben erstellten Label. Setzen Sie den Variablennamen im Abschnitt "C++ Code" auf "width_spbox". Die Minimal- und Maximalwerte sind 1 und 100, was für unsere Stiftweite ausreichen sollte.

Die Knöpfe: Schließlich brauchen wir noch unsere drei Knöpfe. Der linke Knopf soll der Standardknopf sein. Erzeugen Sie einen QPushbutton und plazieren Sie ihn an einer günstigen Stelle unten im Dialog, setzen Sie den Variablennamen auf "default_btn" und den Text auf "Default". Machen Sie das gleiche mit dem "OK" Knopf, Variablenname "ok_btn" und dem "Cancel" Knopf, Variablenname "cancel_btn". Setzen Sie die Knopftexte auf "&OK" und "&Cancel".

Wenn Sie mit Ihrem Layout zufrieden sind, wählen Sie "Alle Quellen erzeugen" aus dem "Erstellen" Menü, geben Sie als Klassennamen "KPenBrushDlg" ein und wählen Sie QDialog. Nachdem Sie "OK" gedrückt haben, werden die Quellen für Ihren Dialog erzeugt und dem Projekt hinzugefügt. Sie können nun wieder zur Editoransicht in KDevelop zurückkehren und wir können den Code hinzufügen, der benötigt wird, damit der Dialog auch etwas macht.

10.4 Verbinden und Einstellen

Nachdem wie nun die GUI des Dialogs erstellt haben, müssen wir den Köpfen noch die Funktionalität geben, und Mittel zur Verfügung stellen, die Werte der Spinbox zu holen und zu setzen, weil wir wollen, daß der Dialog den aktuellen Wert anzeigt, wenn er aufgerufen wird, und wir möchten den eingestellten Wert auslesen, wenn der "OK" Knopf gedrückt wird.

In der erzeugten Klasse KPenBrushDlg können Sie neben dem Konstruktor und dem Destruktor noch die Methode initDialog() finden. Diese Methode implementiert die gesamte GUI Konstruktion, deshalb müssen wir uns darum nicht mehr kümmern, sondern können direkt die üblichen Verbindungen für unsere Knöpfe erstellen. Fügen Sie die markierten Zeilen in den Konstruktor des Dialogs ein:


KPenBrushDlg::KPenBrushDlg(int curr, QWidget *parent, const char *name) : QDialog(parent,name,true){
        initDialog();

->      connect(default_btn, SIGNAL(clicked()), this, SLOT(slotDefault()));
->      connect(ok_btn, SIGNAL(clicked()), this, SLOT(accept()));
->      connect(cancel_btn, SIGNAL(clicked()), this, SLOT(reject()));
}

Dies implementiert die Funktionalität für die Knöpfe, für den Fall, daß sie gedrückt werden. Als erstes stellen wir den Standardknopf so ein, daß er den Slot slotDefault() ausführt. Dieser Slot, in dem wir den Standardwert für die Spinbox direkt setzen, muß noch implementiert werden.

Der zweite connect() Aufruf verbindet den "OK" Knopf mit dem Slot accept(), der von QDialog bereitgestellt wird, genauso wie der reject() Slot, den wir mit dem "Cancel" Knopf verbinden. "Cancel" wird sowohl den Dialog schließen, als auch den resultierenden Wert setzen, den wir später, wenn wir die Methode implementieren, die den Dialog aufruft, dazu verwenden werden, herauszufinden ob der neu eingestellte Wert verwendet oder die ganze Aktion abgebrochen werden soll.

Jetzt werden wir die beiden Methoden zum Setzen und holen der Spinbox-Werte hinzufügen:


void setCurrent(int curr){ width_spbox->setValue(curr); }
int width() { return width_spbox->value(); };

Fügen Sie diese Methoden in der Klassendeklaration mit dem Modifizierer "public" ein, da wir die Werte setzen und holen wollen, wenn der Dialog angezeigt wird. Die Methode setCurrent() wird zum Setzen des aktuellen Stiftwertes verwendet, die width() Methode liefert den Wert zurück, den die Spinbox hat, wenn der Benutzer "OK" drückt.

Schließlich müssen wir noch die Methode slotDefault() implementieren:


//kpenbrushdlg.h:
//method declaration:

public slots:
  void slotDefault();

//kpenbrushdlg.cpp:
//method implementation:

void KPenBrushDlg::slotDefault()
{
  width_spbox->setValue(3);
}

Dies setzt den Standardwert für die Stiftbreite auf 3 Pixel.

Wir sind nun mit unserem ersten Dialog fertig und können uns den anderen Klassen der Anwendung zuwenden, um noch einiges zu adaptieren und Methoden zu implementieren, die den Dialog aufrufen.

10.5 Aufrufen der Dialoge

Wie Sie sich vielleicht schon denken können, bedeutet das Aufrufen der Dialoge nicht nur, daß wir den Dialog zur Auswahl der Stiftgröße implementieren werden, sondern auch, daß wir eine Methode zur Auswahl der Stiftfarbe hinzufügen. Doch eins nach dem anderen. Als erstes erzeugen Sie eine Methode slotPenBrush() in der Klasse KScribbleApp:


void KScribbleApp::slotPenBrush()
{
  slotStatusMsg(i18n("Setting brush width..."));

  // get one window with document for a current pen width
  QWidgetList windows = pWorkspace->windowList();
  KScribbleView* m = (KScribbleView*)windows.at(0);
        KScribbleDoc* pDoc = m->getDocument();
  int curr_width=pDoc->penWidth();

  // create the dialog, get the new width and set the pen width for all documents
  KPenBrushDlg* dlg= new KPenBrushDlg(this);
  dlg->setCurrent(curr_width);
  if(dlg->exec()){
    int width=dlg->width();
        for ( int i = 0; i < int(windows.count()); ++i )
        {
        m = (KScribbleView*)windows.at(i);
        if ( m )
        {
                pDoc = m->getDocument();
        pDoc->setPenWidth(width);
        }
        }
  }
  slotStatusMsg(i18n("Ready."));
}

Hier müssen wir zuerst auf die Fensterliste zugreifen und den Zeiger auf ein Dokument holen - das ein Dokument eines beliebigen Fensters sein kann, da alle Dokumente die gleiche aktuelle Stiftweite haben sollten. Dann legen wir eine Integervariable curr_width an, welche die aktuelle Stiftweite speichert.

Jetzt können wir den Dialog aufrufen, indem wir eine dlg Instanz von KPenBrushDlg erzeugen. Dann setzen wir die aktuelle Stiftweite durch einen Aufruf der Methode dlg->setCurrent(), die wir ja dem Dialog hinzugefügt haben. Durch Aufruf von dlg->exec() zeigen wir den Dialog an. Die if() Anweisung stellt sicher, daß der folgende Code nur ausgeführt wird, wenn das Accept Flag gesetzt ist - das bedeutet, der Code wird ausgeführt, wenn der Benutzer den "OK" Knopf gedrückt hat.

Davon ausgehend, daß der Benutzer den Wert geändert und "OK" gedrückt hat, müssen wir in allen Dokumenten die neue Stiftweite einstellen. Dazu verwenden wir die for() Schleife und setzen in jedem Dokument die entsprechende Variable, die wir zuvor mit dlg->width() geholt haben.

Wir haben die Methode setPenWidth() noch nicht in der Dokumentklasse implementiert, also werden wir das jetzt nachholen:



kscribbledoc.h:

public:
  void setPenWidth( int w ){ pen.setWidth( w ); }

Was noch fehlt, damit überhaupt eine Aktion ausgeführt wird, ist die Methoden hinzuzufügen, die aufgerufen werden sollen, wenn die Menüpunkte aktiviert oder die Knöpfe in der Werkzeugleiste gedrückt werden. Dazu müssen wir die ID's im Slot commandCallback() eintragen, der die entsprechenden Methoden auswählt und ausführt:


void KScribbleApp::commandCallback(int id_)
{
  switch (id_)
  {
    case ID_PEN_BRUSH:
      slotPenBrush();
      break;

    case ID_PEN_COLOR:
      slotPenColor();
      break;
....
  }
}

Diese Erweiterung fügt auch die Methode slotPenColor() zum Setzen der Stiftfarbe in die Liste der auszuführenden Methoden ein. Diese Methode werden wir nun implementieren:


void KScribbleApp::slotPenColor()
{
  slotStatusMsg(i18n("Selecting pen color..."));

  QColor myColor;
  int result = KColorDialog::getColor( myColor, this );
  if ( result == KColorDialog::Accepted )
  {
    QWidgetList windows = pWorkspace->windowList();
    KScribbleDoc* pDoc;
    KScribbleView* m;
    for ( int i = 0; i < int(windows.count()); ++i )
    {
      m = (KScribbleView*)windows.at(i);
      if ( m )
      {
        pDoc = m->getDocument();
        pDoc->setPenColor(myColor);
      }
    }
  }
  slotStatusMsg(i18n("Ready."));
}

Wenn wir uns den Code ansehen, erkennen wir, daß wir eine weitere neue Methode von KScribbleDoc verwenden, um die Farbe des Stifts zu setzen. Diese Methode müssen wir ebenfalls implementieren:


kscribbledoc.h:

    /** sets the pen color */
    void setPenColor( const QColor &c ){ pen.setColor( c ); }

Denken Sie daran, die Deklarationen für slotPenBrush() und slotPenColor() auch einzufügen, damit Ihre Klasse KScribbleApp sie überhaupt kennt.

Nun sind Sie fertig. Lassen Sie uns zusammenfassen, was wir in diesem Kapitel getan haben:

Mit dieser Struktur steht Ihnen ein allgemeiner Weg zur Verfügung, Ihre Anwendung um weitere Funktionalität zu erweitern und Einstellungen zu manipulieren, die das Verhalten des Dokumentes und die Interaktion mit den Ansichten beeinflussen.

Weiter Zurück Inhaltsverzeichnis