Kategorie: yab
Zugriffe: 745

System: BeOS,Haiku,Zeta

Worum es in diesem Tutorial geht

In laufe der letzten Jahre habe ich an diversen kleineren und größeren yab Anwendungen gearbeitet. Mit diesen Jahren habe ich vieles gelernt und optimiert. Wenn ich Programmkodes von damals mit heute vergleiche sind dort große Unterschiede zu sehen.

Wenn man anfängt mit Programmieren zählt vor allen die Funktion, da wird noch nicht so viel Wert auf das Aussehen und die Hintergrundabläufe geachtet. Das ändert sich jedoch mit der Zeit. Wenn man immer wieder die selben Programmierarbeiten durchführt gewöhnt man sich schnell an diese aus Vorherigen Programmkodes zu entnehmen. Findet man eine Möglichkeit diese Abläufe zu verbessern, so finden diese schnell Einzug in den Programmieralltag.

Heute befinden sich in meinen Programmen diverse Abfragen zum Thema Programmablauf. Dabei überlasse ich ungern etwas dem Zufall. Wenn ich zum Beispiel bestimmte Verzeichnisse oder Dateien für mein Programm benötige, so überprüfe ich diese im Vorwege. Alles was fehlt wird entweder erstellt oder der Benutzer darüber informiert.

In diesem Tutorial möchte ich diese Erfahrungen nun mit Denen teilen die Interesse daran haben.


Inhalt

 




Auf einhaltlichtes Design achten

Wie man beim Essen sagt "Das Auge ist mit", so trifft das auch auf das Aussehen von Programmen zu. Hat eine Anwendung ein ansehnliches, übersichtliches Design wird des Benutzer diese gerne verwenden. Herrscht allerdings Chaos, so schreckt das den Benutzer ab. Das betrifft die Farbwahl, die Schriftart, Aufbau der Schaltflächen, Textbereiche, etc.

Allerdings ist wichtig, dass man darauf achtet das bei allen Designtechnischen Dingen nicht die Logik und Bedienungsfreundlichkeit drunter leidet. Es ist nicht immer einfach hier den richtigen Weg zu finden.

Oftmals sind es Kleinigkeiten die am Ende die größte Wirkung haben. Ich für meinen Teil verwende z.B. so gut wie nie die bei den yab Modulen eingefügten Beschriftungsbereiche, sondern erstelle sie mit DRAW TEXT und füge dann das gewünschte Modul (z.B. eine Textcontrol) hinten an.

DRAW TEXT 10,25, "Name: ", "View"
TEXTCONTROL 110,7 TO 320,17, "TC:Name", "", "", "View"


Dadurch ist die Position der im Beispiel verwendeten Textcontrol "an sich" (das Eingabefeld) nicht abhängig von dem Text davor. Somit kann man zum Beispiel mehrere Textcontrols untereinander positionieren, die alle unterschiedlich beschriftet sind, aber trotzdem alle genau an der selben vertikalen Position beginnen.


zurück zur Übersicht




Auf Auslagern in Libraries während der Programmierung verzichten

Normalerweise sollte man immer so programmieren, dass man nichts doppelt anfassen muss. Dies spart Zeit und verhindert ewiges ändern des schon bestehenden Kodes beim weiterprogrammieren. Dies ist aber immer leichter gesagt als getan, denn oftmals zwingen einen neue Optionen im Programm andere Bereiche des Kodes, im verlauf der Programmierung, erneut an zu fassen.

Daher ist es während der Programmierung nicht immer ratsam alles und jedes in Libraries auszulagern, denn ein ewiges wechseln in die anderen geöffneten Dateien kann sehr viel Zeit rauben und auch sehr unübersichtlich werden.

Ist eine Programm oder eine Programmbereich komplett fertig programmiert kann man gerne diese Bereiche auslagern.

Aber letztendlich muss das jeder für sich selber entscheiden, wie dies am besten zu handhaben ist. Für mich hat sich bewehrt, hinter allen Programmabschnitten die miteinander verwoben sind ein Kommentar zu schreiben über welchen ich mit Hilfe der Suche schnell im Kode hin und her springen kann. Die Tastenkombination "Alt + g" ist schneller gedrückt als mit der Mouse auf eine andere Datei zu wechseln.

Button 10,20 to 110,40, "Sort", "Sortieren", "View"         //sorting

case "Sort|"         //sorting

Sub Sortieren()         //sorting


zurück zur Übersicht




Benutzerfreundlichkeit


Dies sind Fragen, die man sich immer stellen sollte. Gehe dabei nie davon aus wie Du es selber siehst, denn wer ein Programm schreibt sieht darin immer eine "eigene" Logik, die nicht immer auf den Benutzer übertragbar ist.


zurück zur Übersicht




Eine gute Basis

Mit einer guten Basis ist gemeint, dass man eine bewerte und alles umfassendes Grundgerüst verwendet. Es macht wenig Sinn immer wieder von Vorne an zu fangen. Im laufe der Jahre hat sich mein Grundgerüst immer wieder etwas verändert. Nicht wirklich viel aber es hat sich bewährt. Mit meinem Grundgerüst konnte ich bisher jedes Projekt verwirklichen, daher kann ich dieses nur empfehlen:

#!/boot/home/config/bin/yab

REM Name of Program
REM Developer
REM Build Version / Date
REM yab Version

if (peek("isbound")) then
        ProgramFolder$ = peek$("directory")
else
        ProgramFolder$ = system$("pwd")
        ProgramFolder$ = left$(ProgramFolder$, len(ProgramFolder$)-1)
fi

//Program info

screenWidth = peek("desktopwidth")
screenHeight = peek("desktopheight")

//Main Window

dim part$(1)

inloop = true

while(inloop)

        msg$ = message$

        if (split(msg$, part$(), ":|") > 2) then
                PartOne$=part$(1)
                PartTwo$ = part$(2)
                PartThree$ = part$(3)
        fi
        if (split(msg$, part$(), ":|") > 3) then
                PartFour$ = part$(4)
        fi
        if (msg$ <> "") print msg$

        switch msg$

        //Cases

        default:

        end switch

        //Special Cases

        if(window count<1) inloop = false

        sleep 0.05

wend

//Subroutines

sub IfExists(filename$)
        return not system("test -e "+filename$)
end sub

zurück zur Übersicht




Ermittlung der Bildschirmauflösung

Eine Ermittlung der Bildschirmgröße kann vielerlei Vorteile haben. Zum Beispiel hat dies beim Aufbau eines Programms den optischen Vorteil, dass man mit diesen Daten das Programmfenster mittig vom Bildschirm anzeigen kann. Ein andere Anwendungsmöglichkeit ist ein Programmfenster den Bildschirmspezifischen Möglichkeiten anzupassen (z.B. für Vollbild- , Minimalansicht).

Die Bildschirmgröße zu ermitteln ist sehr einfach und benötigt nur zwei Zeilen des Programmkodes:

screen_width = peek("desktopwidth")
screen_height = peek("desktopheight")


Die Variablen screen_width und screen_height sind dabei Namen die der Entwickler selber vergeben kann. Diese Zahlenvariable kann nun für jeden Größenangabe des Programmfensters, oder natürlich auch für jedes andere Fenster, verwendet werden. Die einfachste Lösung ist dabei die Zahlenvariable durch zwei zu teilen und dann die Hälfte der gewünschten Fenstergröße abzuziehen und für die andere Position dazuzugeben.

window open screen_width/2-300, screen_height/2-200 to screen_width/2+300, screen_height/2+200, "Main Window", "Musterprogramm"


zurück zur Übersicht




GUI Elemente splittbar machen

Um eine Abfrage der Bedienung der Anwendung übersichtlicher zu machen und um GUI Elemente genauer zu definieren, kann man dessen Namen so gestalten, daß man diesen splitten kann.

Wenn man z.B. ein Button mit einem Namen versieht, der diesen als ein Button ausweist, kann man alle Buttons des Programms über eine Case abfragen:

Definition des Buttons:

BUTTON x1,y1 TO x2 ,y2, "BT:Name" , Label$, View$


Case Abfrage dazu:

case "BT:"+PartTwo$+"|"
        if(PartTwo$="Name1")then
                //Aktion bei Button 1
        elseif(PartTwo$="Name2")then
                //Aktion bei Button 2
        endif
        break


Das gleiche gilt für alle GUI Elemente. Somit hätte man dann für je ein GUI Element eine Case- Abfrage. Natürlich kann das auch am Ende unübersichtlich werden, kommt immer darauf an wie viele Abfrage dieser Art notwendig sind. Ich für meinen Teil habe mir diese Vorgehenseweise angenommen und bin damit sehr zufrieden.

Hier eine Tabelle mit meinen Kürzeln für meine GUI Elemente:

Kürzel GUI Element
AL Alert
BT Button / Button Image
BV Boxview
CV Canvas
CD Calendar
XB Checkbox
CV Canvas
CB Columnbox
DB Dropbox
FP Filepanel
LB Listbox
RB Radiobutton
SL Slider
XV Splitview
SV Stackview
SB Statusbar
TV Tabview
TE Textedit
TC Textcontrol
TB Treebox
VI View
WD Window

Man kann natürlich den Namen eines GUI Elements auch mehr als einmal aufteilen. Im Grunde genommen so oft wie es nötig und sinnvoll ist.

zurück zur Übersicht




Überprüfen auf Vorhandensein von Verzeichnissen und Dateien

Verwendet man in einem Programm feste Verzeichnisse oder verwendet externe Programme, sollte diese im Vorfeld überprüft werden. Selbst wenn man diese selber mit dem Programm zusammen ausliefert, sollte eine Überprüfung durchgeführt werden, denn man weiß nie ob jemand im System etwas verändert hat.

Beispiel: Beim Programmstart wird eine Konfigurationsdatei ausgelesen, welche alle wichtigen Informationen für die Anwendung beinhaltet. Sollte diese Datei nicht da sein kann das Programm an dieser Stelle nicht weiterlaufen, sprich es stürzt ab. Der Benutzer der Anwendung sieht keinerlei Information warum dies geschehen ist, denn das Programm wird scheinbar einfach beendet.

Nun gibt es mehrere Möglichkeiten dieses zu lösen.
Zum Beispiel könnte man ein Infofenster anzeigen mit einer Fehlermeldung, die dem Benutzer darüber informiert weshalb ein Fehler aufgetreten ist.
Schöner wäre allerdings, würde man die Konfigurationsdatei automatisch erstellen lassen, sollte diese fehlen. Aus diesem Grund liefere ich bei Verwendung einer Konfigurationsdatei diese nicht mehr mit aus, sondern lasse sie durch eine Abfrage automatisch erstellen. So ist es egal ob sie vorhanden ist oder nicht, denn selbst wenn eine Konfigurationsdatei, weshalb auch immer, auf einmal nicht mehr vorhanden sein sollte, wird eine Standard- Konfigurationsdatei neu erstellt.

Dazu bietet sich ein Lösungsweg an, der in der yabIDE eingesetzt wird. Diese verwendet eine IF- Abfrage, eine Sub- Routine und den Terminal Befehl test um die gesuchte Datei/Verzeichnis zu überprüfen:

filename$="/Pfad/zur/gesuchten/Datei oder Verzeichnis"

If(IfExists$(filename$))then
else
  Hier Programmkode für den Fall das keine Datei gefunden wurde
endif


Und die Sub- Routine im Bereich außerhalb der Mainloop:

sub IfExists(filename$)
  return not system("test -e "+filename$)
end sub


Jetzt könnte man natürlich sagen, was passiert wenn der Terminal Befehl test auf einmal entfällt in Haiku? Nun dann sollte man, wenn man auf Nummer Sicher gehen möchte, diesen auch überprüfen oder noch besser mit dem Programm mit ausliefern.


zurück zur Übersicht




Statusbar richtig einsetzen

Wann benötigt man eine Statusbar?

Eigentlich immer dann, wenn man dem Benutzer einen Prozess anzeigen möchte. Wichtig dabei ist, dass der Benutzer nicht das Gefühl bekommt, dass das Programm stehen geblieben ist (Ein Fehler aufgetreten ist).

Daher sollte man immer bevor der Prozess gestartet ist, die Statusbar mit 5- 10 Prozent der Anzeigefläche füllen. Danach kann dann der Prozess ganz normal durchlaufen (Natürlich mit zwischenzeitiger Aktuallisierung der Statusbar).

Am Ende sollte dann die gesamte Statusbar gefüllt und mindestens 2- 3 Sekunden in diesem Zustand angezeigt werden (Fall diese dann entfernt oder zurückgesetzt wird).

Der Benutzer sollte immer genügend Zeit bekommen zu realisieren, wenn etwas beginnt und beendet wird.


zurück zur Übersicht




Verwenden von feste Schriftarten

Bei dem Versuch ein einheitliches Bild einer Anwendung zu erhalten spielt die Schrift einen erheblichen Rolle. Ist diese nicht definiert wird die Standardschrift des Systems verwendet (Einstellbar durch den Benutzer). Dadurch kann es passieren das die verwendetet Textbereiche der Anwendung bei jedem anders aussehen und optische Fehler auftreten. Zum Beispiel könnte ein vor ein Bild gesetzter Text, durch eine große Schriftgröße des Systems, auf einmal länger sein als vorgesehen, sprich der Text endet nicht vor, sondern mitten im Bild.

yab Commands: Fonts


zurück zur Übersicht




Zeilen sparen

Je umfangreicher ein Programm wird, desto mehr wächst der Wunsch den Kode kleiner und übersichtlicher zu halten.

Hier ein paar Möglichkeiten den Kode zu verjüngen:

Cases

Bei den Cases kann man zum Beispiel mehre Cases, die ein und die selbe Funktion Aufrufen, hintereinander schreiben und nur mit einem break beenden.

case "Musterprogramm:_QuitRequested|"
case "Musterprogramm:Programm:Ende|"
  window close "Musterprogramm"
  break


Abfragen

Beim Auslesen von Verzeichnissen und Dateien kann man ebenso eine Vielzahl an Zeilen einsparen. An statt jedes Mal, wenn man eine Datei oder Verzeichnis auslesen möchte, die gesamt Abfrage zu verwenden kann man diese prima in eine Sub- Routine auslagern und dann bei Bedarf aufrufen. Um die Informationen für das Auslesen zu übergeben, verwendet man dann einfach immer die selben Variablen.

Dieses Beispiel zeigt wie man beim auslesen von Verzeichnissen immer die selbe Sub- Routine und zu erhalten der benötigten Informationen gleiche Variablen verwendet.

Wir geben in der Variablen target$ das Verzeichnis an, welches ausgelesen werden soll. Dann rufen wir die Sub- Routine auf. In der Sub- Routine wird dann mit Hilfe des ls Terminalbefehls das Verzeichnis target$ ausgelesen. In dem Array SplitProfile$(1) speichern wir alle Einträge des ausgelesenen Verzeichnisses (target$) die mit einem /n (Zeilenumbruch) getrennt sind. In diesem Beispiel gebe ich nun alle Einträge des Arrays automatisch aus.

target$="/boot/home/config/meinprogramm/profiles"
readtarget()

 

sub readtarget()
  filename$=system$("ls -G -1 "+target$)
    dim SplitProfiles$(1)
      pf=0
      pfa=0
      pf = split(filename$, SplitProfiles$(), "\n")
      for pfa = 1 to pf
          print SplitProfiles$(pfa)
      next pfa
end sub


zurück zur Übersicht


 

Tutorial von Christian Albrecht (Lelldorin) Juli 2011
Bereitgestellt durch BeSly die BeOS, Haiku und Zeta Wissensbasis.