Buchempfehlung
MySQL kurz & gut
MySQL kurz & gut
Das preiswerte Taschen- buch stellt MySQL-rele- vante Inhalte systematisch und knapp dar, sodass es sich optimal zum Nach- schlagen beim Pro- grammieren eignet. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Tutorial

Einführung in die GUI-Programierung mit FLTK

von MitgliedLothar SchirmSeite 1 von 1

(Siehe auch: Englisches Tutorial / English tutorial: Introduction to GUI Programming with FLTK [EN])

Inhalt

1. Was ist FLTK?
2. Download und Installation
3. Ein erstes Programm
4. Widgets
4.1 Fl_Button
4.2 Fl_Input und Fl_Output
4.3 Fl_Text_Editor und Fl_Text_Display
4.4 Fl_Browser
4.4.1 Eine Listbox
4.4.2 Eine Tabelle in einen Browser schreiben
4.5 Fl_Chart
4.6 Fl_Choice
4.7 Fl_Menu_Bar, flFileChooser, flMessageBox
4.8 Weitere Standarddialoge (Common dialogs)


1. Was ist FLTK?

FLTK (Fast Light Toolkit) ist eine leicht zu handhabende C++ GUI-Bibliothek für
Linux und Windows. Siehe Homepage Externer Link!http://www.fltk.org. Es gibt hierzu auch einen Wrapper für FreeBasic im englischen FreeBasic-Forum. Hier die Projektseite:

"FLTK C for FreeBasic" von D.J.Peters
(Externer Link!http://www.freebasic.net/forum/viewtopic.php?f=14&t=24547)

Dort ist auch ein Link für den Download der Dokumentation angegeben. Im Download des Wrappers sind zahlreiche Codebeispiele enthalten, die die Einarbeitung sehr erleichtern.

Außer grafischen Benutzeroberflächen lassen sich auch Grafiken mit entsprechenden
Zeichenbefehlen erzeugen. Ebenso kann OpenGL verwendet werden. Grafikprogrammierung mit FLTK ist jedoch nicht Gegenstand dieses Tutorials. Hierzu möchte ich auf die Codebeispiele im Wrapper verweisen.

Es gibt zu FLTK auch einen GUI-Designer (FLUID). Dieser erzeugt jedoch C++ Code,
so dass er für FreeBasic nicht verwendet werden kann.


2. Download und Installation

Siehe Beschreibung auf der Projektseite.


3. Ein erstes Programm

Wir beginnen mit einem einfachen Programm: Ein Fenster mit einem Text ("Willkomen bei FLTK!") und einem Button. Wenn der Button gedrückt wird, soll auf das Konsolenfenster eine Testausgabe erfolgen: "Button wurde gedrückt!"

Der Code hierzu ist sehr einfach:

#Include "fltk-c.bi"

'Fenster und Widgets:
Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Box Ptr Box_text
Dim Shared As Fl_Button Ptr Button_Click


Sub Create_Window_Main()
'Fenster mit Button:

    Window_Main = Fl_WindowNew(300, 200, "Button-Test")
    Box_text = Fl_BoxNew (100, 80, 100, 20, "Willkommen bei FLTK!")
    Button_Click = Fl_ButtonNew(100, 160, 100, 20, "Click me!")

End Sub


Sub Button_Click_Event Cdecl (widget As FL_Widget Ptr)
'Callback-Funktion für Button

  Print "Button wurde gedrueckt!"

End Sub


'Hauptprogramm:
Create_Window_Main()
Fl_WidgetSetCallback0(Button_Click, @Button_Click_Event)
Fl_WindowShow(Window_Main)
Fl_Run

End

Hier ein Screenshot:

Fenster mit Button

Nun zum Code: Was heißt das alles?

In der ersten Zeile binden wir die Headerdatei fltk-c.bi ein.

Danach kommt die Definition des Fensters mit seinen Elementen (Boxen, Buttons,
darüber hinaus auch Texteingabefelder usw.). Alle diese Elemente werden in FLTK
als Widgets bezeichnet. In FLTK werden alle Fenster und die Widgets als Pointer
übergeben, ebenso Strings (als ZString Pointer), siehe Beispiele ab 4.2.

Ich habe mir angewöhnt, die Definition für jedes Fenster in einer eigenen Sub
zu verpacken, obwohl das nicht zwingend notwendig ist. In den kleinen
Beispielprogrammen des Wrappers ist dies generell nicht der Fall. Es steigert
aber meines Erachtens die Übersichtlichkeit des Codes, insbesondere bei größeren
Projekten mit mehreren Fenstern. Man kann dann auch mit dem Function-Browser
der IDE leicht die Fensterdefinitionen wiederfinden.

Im Code haben wir für den Text ein Widget Fl_Box verwendet. Dies ist einfach
ein rechteckiger Bereich mit einem Text.

Nennen wir das Fenster "Window_Main", die Box "Box_text" und den Button "Button_Click". Diese werden mit "Dim Shared" als globale Variablen vom Typ FL_Window Ptr, Fl_Box Ptr bzw. Fl_Button Ptr deklariert, so dass wir in den Callback-Funktionen (siehe unten) auf diese zugreifen können. Beispiele zu Callback-Funktionen folgen in diesem Tutorial.

Die Fensterdefinition für unser Fenster "Window_Main" erfolgt in einer Sub, die wir
"Create_Window_Main" nennen. Innerhalb der Sub benötigen wir drei Funktionen:

Function Fl_WindowNew(w as integer, h as integer, title as const zstring ptr = 0) as Fl_Window ptr
Function Fl_BoxNew(x as integer, y as integer, w as integer, h as integer, label as const zstring ptr=0) as Fl_Box ptr
Function Fl_ButtonNew(x as integer, y as integer, w as integer, h as integer, label as const zstring ptr = 0) as Fl_Button ptr


Die Parameterübergabe, wie in den Funktionen "Fl_BoxNew" oder "Fl_ButtonNew",
ist für alle Widgets immer die selbe:

Name des Widgets
x, y = Position der linken oberen Ecke des Widgets (Pixelkoordinaten)
w = Breite des Widgets in Pixeln
h = Höhe des Widgets in Pixeln
label = Beschriftung.

Beispiele für andere Widgets folgen unten.

Nach der Sub "Create_Window_Main" kommt unsere Callback-Funktion für den
Button_Click. Wir nennen sie Button_Click_Event. Wichtig ist das Cdecl und der
Übergabeparameter vom Typ Fl_Widget Ptr. In die Callback-Funktion schreiben wir rein, was unser Programm tun soll, wenn der Button_Click gedrückt wird.

Das Hauptprogramm ist dann sehr kurz. Zunächst wird unsere Sub "Create_Window_Main" aufgerufen. Dann erfolgt mit Fl_WidgetSetCallback0 die Verknüpfung des Buttons "Button_Click" mit der Callback-Funktion. Mit Fl_WindowShow zaubern wir unser Fenster auf den Bidschirm. Bei Programmen mit mehreren Fenstern ist Fl_WindowHide von Nutzen, damit können wir ein Fenster wieder vom Bildschirm verschwinden lassen. Mit Fl_Run läuft das Programm, bis das Fenster über den Schließen-Button in der Titelleiste oder über das Kontextmenü des Fensters in der Taskleiste geschlossen wird.

Fl_WidgetSetCallback0 sieht wegen der Null am Ende etwas seltsam aus, das ist
aber kein Druckfehler. Es gibt in FLTK nämlich die Möglichkeit, verschiedene
Typen von Callback-Funktionen zu erzeugen. Man kann mit Fl_WidgetSetCallback1Arg, Fl_WidgetSetCallback oder Fl_WidgetSetCallbackArg an die Callback-Funktion in verschiedener Weise zusätzlich Parameter übergeben. Beispiele hierzu finden sich im Download des Wrappers so wie auch in diesem Tutorial.

Das obige Programm muss natürlich wegen der Print-Anweisung in der Callback-
Funktion als Konsolenprogramm compiliert werden. Das gilt auch für die nachfolgenden Beispiele, soweit sie den Print-Befehl beinhalten.

Zusätzlich zum FLTK-GUI können wir auch mit "ScreenRes" das normale Grafikfenster
öffnen und mit den normalen FreeBasic-Befehlen hier unsere Grafiken erzeugen.

Das ist das schöne an GUI-Bibliotheken wie FLTK, GTK+, WX-C u.a: Wir können nach wie vor das Konsolenfenster (vorzugsweise für Testausgaben/zum Debuggen) und das Grafikfenster in der gewohnten Weise benutzen, bekommen aber ein GUI gratis dazu.


4. Widgets

FLTK stellt verschiedenen Klassen von Widgets zur Verfügung.

Die Klasse Fl_Button unterstützt verschiedene Arten von Buttons, z.B. normale
Buttons (siehe oben), Togglebuttons, Checkbuttons, Radiobuttons u.a.

Die Widgets Fl_Input, Fl_Output, Fl_Text_Editor, Fl_Text_Display und Fl_Help_View ermöglichen Ein- und Ausgabe von Text in einfacher oder auch anspruchsvollerer Form.

Die Klasse Fl_Valuator beinhaltet z.B. Scrollbars (Fl_Scrollbar) und Sliders (Fl_Slider).

Die Klasse Fl_Menu_ ermöglicht die Erstellung von Menüs (Fl_Menu_Bar) und beinhaltet auch Comboboxen (Fl_Choice).

Die Klasse Fl_Browser_ ermöglicht die Darstellung von Listen und Tabellen sowie
die Erstellung von Listboxen mit Einfach- oder Mehrfachauswahl.

Benutzeroberflächen können z.B. durch Scrollaereas (Fl_Scroll), Tabs (Fl_Tabs) oder Tiles (Fl_Tile) übersichtlich strukturiert werden.

FLTK stellt auch Standarddialoge (common dialogs) zur Verfügung, z.B. Messageboxen, Inputboxen, Dateiauswahl oder Farbauswahl.

Im Rahmen dieses Tutorials kann nicht auf alle diese Widgets eingegangen werden.
Die wichtigsten werden im folgenden erklärt und ihre Verwendung mit ein paar kleinen
Anwendungsbeispielen gezeigt. Für weitere Einzelheiten wird auf die Codebeispiele
im Download hingewiesen sowie auf die Dokumentation und die Header-Datei fltk-c.bi.


4.1 Fl_Button

Die Klasse Fl_Button umfasst folgende Widgets:

Fl_Light_Button: aktiviert ein "Licht" (kleines Quadrat links im Button, wenn er angeklickt wird. Der Fl_Check_Button ist eine Unterklasse davon
Fl_Radio_Button: Radiobutton (Option Button)
Fl_Repeat_Button: erzeugt fortlaufende Callbacks, so lange er gedrückt wird
Fl_Return_Button: reagiert auf Mausklick oder auf die Return-Taste (Enter-Taste)
Fl_Toggle_Button: Togglebutton

Beispiel für einen einfachen Button siehe oben.

Hier ein Beispiel für Fl_Toggle_Button, Fl_Radio_Round_Button und Fl_Check_Button (ein Fl_Radio_Round_Button hat links einen Kreis, der den "aktiven" Zustand des Buttons mit einer Markierung anzeigt, während der einfache Fl_Radio_Button nur wie ein Togglebutton funktioniert):

#Include "fltk-c.bi"

'Widgets
Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Toggle_Button Ptr Button_toggle
Dim Shared As Fl_Group Ptr Group_radio
Dim Shared As Fl_Radio_Round_Button Ptr Button_radio_red, Button_radio_yellow, Button_radio_green
Dim Shared As Fl_Check_Button Ptr Button_check
Dim Shared As Fl_Button Ptr Button_close


Sub Create_Window_Main()
'Hauptfenster mit Buttons

    Window_Main = Fl_WindowNew(200, 250, "Test Buttons")
    Button_toggle = Fl_Toggle_ButtonNew(20, 20, 100, 20, "Togglebutton")

    Group_radio = Fl_GroupNew(10, 70, 120, 90, "Wähle eine Farbe:")
    Fl_GroupBegin(Group_radio)
        Button_radio_red = Fl_Radio_Round_ButtonNew(20, 80, 100, 20, "rot")
        Button_radio_yellow = Fl_Radio_Round_ButtonNew(20, 110, 100, 20, "gelb")
        Button_radio_green = Fl_Radio_Round_ButtonNew(20, 140, 100, 20, "grün")
    Fl_GroupEnd(Group_radio)

    Button_check = Fl_Check_ButtonNew(20, 170, 100, 20, "Checkbutton")
    Button_close = Fl_ButtonNew(20, 200, 100, 20, "Beenden")

End Sub


Sub Buttons_Event Cdecl (widget As Fl_Widget Ptr, arg As Any Ptr)
'Callbackfunktion für alle Buttons

    Select Case arg
        Case Button_toggle
            Print Fl_ButtonGetValue(Button_toggle)
        Case Button_radio_red
            Print "rot"
        Case Button_radio_yellow
            Print "gelb"
        Case Button_radio_green
            Print "grün"
        Case Button_check
            Print Fl_ButtonGetValue(Button_check)
        Case Button_close
            End
    End Select

End Sub


'Hauptprogramm:

Create_Window_Main()

Fl_WidgetSetCallbackArg(Button_toggle, @Buttons_event(), Button_toggle)
Fl_WidgetSetCallbackArg(Button_radio_red, @Buttons_event(), Button_radio_red)
Fl_WidgetSetCallbackArg(Button_radio_yellow, @Buttons_event(), Button_radio_yellow)
Fl_WidgetSetCallbackArg(Button_radio_green, @Buttons_event(), Button_radio_green)
Fl_WidgetSetCallbackArg(Button_check, @Buttons_event(), Button_check)
Fl_WidgetSetCallbackArg(Button_close, @Buttons_event(), Button_close)

Fl_WindowShow(Window_Main)
Fl_Run

End

Hier der Screenshot des laufenden Programms:

Verschiedene Buttons

Wir haben jetzt also einen Togglebutton, drei Radiobuttons, einen Checkbutton und einen Button zum Schließen des Fensters und Beenden des Programms. Die drei Radiobuttons müssen wir in einer Gruppe zusammenschließen, da es sich hier um eine Auswahl "eins aus drei" handeln soll. Das geschieht mit Hilfe eines Widgets Fl_Group und den Befehlen Fl_GroupBegin und Fl_GroupEnd.

Jetzt könnten wir wie im Einführungsbeispiel für jeden Button eine eigene Callbackfunktion schreiben. Wir wollen uns aber das Leben vereinfachen und nur eine Callbackfunktion für alle sechs Buttons schreiben. Das geht mit Fl_WidgetSetCallbackArg statt Fl_WidgetSetCallback0, denn hier können wir zusätzlich einen Pointer an die Callbackfunktion übergeben, z.B. einen Pointer auf das betreffende Widget. Dann können wir in die Callbackfunktion für jedes in Frage kommende Widget hineinschreiben, was passieren soll. Den Zustand eines Buttons (1 oder 0) können wir mit Fl_ButtonGetValue abfragen (siehe im Beispiel beim Togglebutton oder beim Checkbutton). Bei den Radiobuttons ist es anders gemacht, aber auch dort könnte man Fl_ButtonGetValue verwenden. Beim normalen Button (Fl_Button) macht das natürlich wenig Sinn.


4.2 Fl_Input und Fl_Output

Das Widget Fl_Input ist ein einzahliges Texteingabefeld mit einer Eingabeaufforderung, so ein bisschen wie der Befehl "Input" in FreeBasic. Das Widget Fl_Output sieht genau so aus, kann aber nur Text darstellen. Es gibt auch Ein- und Ausgabefelder für mehrzeilige Texte (Fl_Multiline_Input und Fl_Multiline_Output).

Beispiel: ein Programm mit einem Fl_Input und einem Fl_Output sowie einem Button. Durch Drücken des Buttons soll der Text aus dem Fl_Input in das Fl_Output kopiert werden.

#Include "fltk-c.bi"

'Fenster und Widgets:
Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Input Ptr Input_text
Dim Shared As Fl_Output Ptr Output_text
Dim Shared As Fl_Button Ptr Button_Copy


Sub Create_Window_Main()
'Fenster mit Widgets:

    Window_Main = Fl_WindowNew(300, 200, "Button-Test")
    Input_text = Fl_InputNew(100, 50, 180, 20, "Texteingabe:")
    Output_text = Fl_OutputNew(100, 80, 180, 20, "Textausgabe:")
    Button_Copy = Fl_ButtonNew(100, 150, 100, 20, "Kopieren")
    Fl_Input_SetValue(Input_text, "Editiere mich!")

End Sub


Sub Button_Copy_Event Cdecl (widget As FL_Widget Ptr)
'Callback-Funktion für Button

  Dim As String text

  text = *Fl_Input_GetValue(Input_text)
  Fl_Input_SetValue(Output_text, text)

End Sub


'Hauptprogramm:
Create_Window_Main()
Fl_WidgetSetCallback0(Button_Copy, @Button_Copy_Event)
Fl_WindowShow(Window_Main)
Fl_Run

End


Lassen wir das Programm laufen, erhalten wir folgendes Bild:

Textein- und Ausgabefeld

Wir können den Text "Editiere mich!" verändern und mit Drücken des Buttons
"Kopieren" in das Textausgabefeld kopieren.

Nun zum Code. Dieser ist eine Erweiterung des einführenden Beispiels. Der "Button_Click" wurde in "Button_Copy" umbenannt. In die Deklaration der Widgets und in die Sub "Create_Window_Main" wurden die neuen Widgets mit den Namen "Input_text" und "Output_text" zusätzlich aufgenommen. Die Syntax ist eigentlich selbsterklärend. Mit Fl_Input_SetValue wurde das Texteingabefeld mit einem editierbaren Text vorbelegt.

Nun zur Callback-Funktion. Mit "text = *Fl_Input_GetValue(Input_text)" wird der
Text aus dem Eingabefeld Input_text ausgelesen. Man beachte das Sternchen! Die Funktion Fl_Input_GetValue liefert nämlich nur einen Pointer auf einen ZString zurück. Mit dem Sternchen davor wird der Wert dieses ZString ausgegeben (Pointer-Dereferenzierung, siehe FB Referenz BefehlsreferenzeintragStern). Mit Fl_Input_SetValue wird der Text in das Ausgabefeld eingetragen, obwohl es sich um ein Fl_Output Widget handelt. Einen Befehl "Fl_Output_SetValue" gibt es nicht, da Fl_Input in der Klassenhierarchie der Widgets oberhalb von Fl_Output angeordnet ist.

Die Klasse Fl_Input beinhaltet folgende Widgets:

Fl_File_Input: zeigt einen Pfadnamen in einem Texteingabefeld an
Fl_Float_Input: erlaubt nur die Eingabe von Gleitkommazahlen
Fl_Int_Input: erlaubt nur die Eingabe von Dezimalziffern
Fl_Secret_Input: zur verdeckten Passworteingabe, es werden nur Platzhalter angezeigt
Fl_Output: siehe oben


4.3 Fl_Text_Editor und Fl_Text_Display

Das Widget Fl_Text_Editor ist ein Widget zur Eingabe von Text, wobei der Text
vertikal und horizontal mit Scrollbalken gescrollt werden kann, falls die
Textdarstellung größer ist als das Texteingabefeld.

Auch hier wieder ein Codebeispiel:

#Include "fltk-c.bi"

'Fenster und Widgets:
Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Text_Editor Ptr Editor_text
Dim Shared As Fl_Text_Buffer Ptr Buffer_text
Dim Shared As Fl_Button Ptr Button_Copy


Sub Create_Window_Main()
'Fenster mit Widgets:

    Window_Main = Fl_WindowNew(300, 300, "Editor-Test")
    Editor_text = Fl_Text_EditorNew (10, 10, 280, 200)
    Button_Copy = Fl_ButtonNew(100, 230, 100, 20, "Kopieren")

    'Texteditor mit einem Text vorbelegen:
    Buffer_text = Fl_Text_BufferNew()
    Fl_Text_DisplaySetBuffer(Editor_text, Buffer_text)
    Fl_Text_BufferSetText(Buffer_text, "Üb immer Treu und Redlichkeit bis an dein selig Ende")

End Sub


Sub Button_Copy_Event Cdecl (widget As FL_Widget Ptr)
'Callback-Funktion für Button

  Dim As String text

  text = *Fl_Text_BufferGetText(Buffer_text)
  Print text

End Sub


'Hauptprogramm:
Create_Window_Main()
Fl_WidgetSetCallback0(Button_Copy, @Button_Copy_Event)
Fl_WindowShow(Window_Main)
Fl_Run

End

Das Programm erzeugt das folgende Fenster:

Text-Editor

Der vorbelegte Text kann editiert werden. Wenn man auf den Button "Kopieren" drückt, wird der Text kopiert und auf das Konsolenfenster ausgegeben.

Im Code erscheint als neues Widget der Texteditor mit dem vorbelegten Text
"Üb immer Treu und Redlichkeit bis an dein selig Ende". Leider lässt sich das Widget
Fl_Text_Editor nicht direkt beschreiben, nur über einen Textbuffer, der als
Fl_Text_Buffer extra erzeugt und dem Texteditor zugeordnet werden muss. Dies
geschieht mit Hilfe der Funktionen Fl_Text_BufferNew und Fl_Text_DisplaySetBuffer ("Fl_Text_EditorSetBuffer" gibt es nicht - Stichwort "Klassenhierarchie der Widgets", siehe oben). Dann kann der Textbuffer mit Fl_Text_BufferSetText beschrieben oder mit Fl_Text_BufferGetText ausgelesen werden (Sternchen: Pointer-Dereferenzierung, siehe oben).

Wenn man nur Text anzeigen will, ohne dass er geändert werden soll, verwendet man
das Widget Fl_Text_Display. Die Syntax zur Deklaration (Fl_Text_DisplayNew anstatt Fl_Text_EditorNew), Erstellung des Textbuffers und Beschreiben sowie Auslesen des Textbuffers entspricht völlig der beim Fl_Text_Editor.

Will man Text mit Zeilenumbruch in einen Textbuffer schreiben, so setzt man an
die Stellen des Zeilenumbruchs Chr(10) ein:

Fl_Text_BufferSetText(Buffer_text, "Ich ging im Wald so für mich hin" + Chr(10) +_
"und nichts zu suchen, das war mein Sinn."


4.4 Fl_Browser

Ein Fl_Browser zeigt eine Liste von Strings an, die gescrollt werden kann. Zur Klasse Fl_Browser gehören folgende Widgets:

Fl_File_Browser: zeigt eine Liste von Dateinamen an, optional mit Icons
Fl_Hold_Browser: eine Listbox, aus der ein Eintrag ausgewählt werden kann,
wobei die Auswahl mit einem blauen Balken markiert bleibt, wenn die Maus losgelassen wird
Fl_Multi_Browser: eine Listbox mit Mehrfachauswahl
Fl_Select_Browser: eine Listbox, aus der ein Eintrag ausgewählt werden kann,
wobei die Auswahl nicht markiert bleibt, wenn die Maus losgelassen wird


4.4.1 Eine Listbox


Beispiel für eine Listbox mit einem Hold_Browser:

#Include "fltk-c.bi"

'Fenster und Widgets:
Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Hold_Browser Ptr Browser_Auswahl


Sub Create_Window_Main()
'Fenster mit Widgets:

    Dim As Integer i

    Window_Main = Fl_WindowNew(200, 200, "Hold_Browser")
    Browser_Auswahl = Fl_Hold_BrowserNew(10, 10, 180, 160, "Listen-Auswahl")
    For i = 1 To 20
        Fl_BrowserAdd(Browser_Auswahl, "Eintrag Nr." + Str(i))
    Next

End Sub


Sub Browser_Auswahl_Event Cdecl (widget As FL_Widget Ptr)
'Callback-Funktion für den Browser

    Dim As Integer i
    Dim As String text

    i = Fl_BrowserGetValue(Browser_Auswahl)
       text = *Fl_BrowserGetText(Browser_Auswahl, i)
       Print i
       Print text

End Sub


'Hauptprogramm:
Create_Window_Main()
Fl_WidgetSetCallback0(Browser_Auswahl, @Browser_Auswahl_Event)
Fl_WindowShow(Window_Main)
Fl_Run

End

Hier der zugehörige Screenshot, dieses mal mit Testausgabe auf das Konsolenfenster:

Listbox

Wie man im Code sieht, werden dem Browser mit Fl_BrowerAdd zeilenweise die
Einträge zugefügt. Falls wir den Browser neu beschreiben wollen, können wir seinen
Inhalt mit Fl_BrowerClear löschen. Beispiel:

Fl_BrowserClear(Browser_Auswahl)

Die Nummer des mit der Maus ausgewählten Eintrages können wir mit Fl_BrowserGetValue abfragen, und den zugehörigen Text mit Fl_BrowserGetText (siehe Callbackfunktion im Code).


4.4.2 Eine Tabelle in einen Browser schreiben

Einen Browser können wir grundsätzlich zur Erstellung beliebiger Listen und auch
Tabellen verwenden. Wenn wir eine Tabelle in den Browser schreiben wollen, müssen
wir vorher die Anzahl der Spalten und deren Breite (in Pixeln) festlegen. Das geht
mit Fl_BrowserSetColumnWidths. Diese Sub ist wie folgt definiert:

Sub Fl_BrowserSetColumnWidths(br As Fl_Browser Ptr, arr As Const Integer Ptr)

br ist der Pointer auf den Browser. arr ist ein Pointer auf ein Array, dessen
Elemente die Spaltenbreiten angeben. Das Array muss nullterminiert sein, dass heißt,
das letzte Element muss 0 sein! Außerdem muss es vom Typ "Const Integer" sein,
also global deklariert.

Die Einträge in den Browser erfolgen in der schon bekannten Weise mit Fl_BrowerAdd, wobei die Spalten durch Chr(9) getrennt werden. Wir können mit Fl_BrowserSetColumnChar auch andere Trennzeichen wählen:

Sub Fl_BrowserSetColumnChar(br as Fl_Browser ptr, c as ubyte)

Für c müssen wir den ASCII-Code des gewünschten Zeichens einfügen. Das ist sehr
praktisch, wenn wir z.B. eine mit Excel erzeugte CSV-Datei darstellen wollen,
dann setzen wir für c Asc(";") ein.

Hier als Beispielcode eine Funktionstabelle:

#Include "fltk-c.bi"

Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Browser Ptr Browser_Tabelle
Dim Shared As Integer col(3) = {80, 80, 80, 0}
Dim As Single x


Sub CreateWindow_Main
    'Fenster mit Widgets:

    Window_Main = Fl_WindowNew(300, 300, "Tabelle")
    Browser_Tabelle = Fl_BrowserNew(10, 10, 280, 280)
    Fl_BrowserSetColumnWidths(Browser_Tabelle, @col(0))

End Sub


'Hauptprogramm

CreateWindow_Main()
Fl_WindowShow(Window_Main)

'Funktionstabelle für x^2 und Sqr(x) schreiben:
Fl_BrowserAdd(Browser_Tabelle, "x" + Chr(9) + "x^2" + Chr(9) + "Sqr(x)")
For x = 0 To 100
    Fl_BrowserAdd(Browser_Tabelle, Str(x) + Chr(9) + Str(x^2) + Chr(9) + Str(Sqr(x)))
Next

Fl_Run

End

Hier der Screenshot:

Tabelle


4.5 Fl_Chart

Da wir gerade bei Funktionstabellen sind: Man kann mit Fl_Chart auch
Funktionsverläufe grafisch einfach darstellen oder sonstige einfache Diagramme.

Beispiel: Eine Sinuskurve

#Include "fltk-c.bi"

Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Chart Ptr Chart_Sinus

Dim As Integer i
Dim As Single x, dx
Const Pi = 4 * Atn(1)

Sub CreateWindow_Main()
    'Fenster mit Diagramm

    Window_Main = Fl_WindowNew(400, 240, "Chart")
    Chart_Sinus = Fl_ChartNew   (10, 10, 380, 200, "Zeitache = 4 * pi")
    Fl_WidgetSetType(Chart_Sinus, FL_CHART_LINE)

End Sub


'Hauptprogramm

CreateWindow_Main()
Fl_WindowShow(Window_Main)

'Sinuskurve ins Diagramm eintragen:
dx = 4 * pi / 100
For i = 0 To 100
    x = i * dx
    Fl_ChartAdd(Chart_Sinus, Sin(x), "", FL_RED)
Next

Fl_Run

End

Screenshot:

Chart

Unser Widget nennen wir "Chart_Sinus" (siehe Code). Mit Fl_WidgetSetType können wir den Typ des Diagramms festlegen, z.B.:
FL_CHART_BAR: Balkendiagramm
FL_CHART_LINE: Liniendiagramm
FL_CHART_PIE: Kreisdiagramm (Tortendiagramm)

Mit Fl_ChartAdd werden nacheinder die darzustellenden Werte eingetragen. Der
zweite Parameter gibt den einzutragenden Zahlenwert ein, der dritte eine hierzu
gehörende Beschriftung (optional) und der letzte Wert die Farbe. Die Farbkonstanten
FL_RED, FL_GREEN, FL_BLUE usw. sind in der Headerdatei fltk-c.bi deklariert.


4.6 Fl_Choice

Das Widget Fl_Choice ist eine Combobox. Hier ein Beispiel:

#Include "fltk-c.bi"

Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Choice Ptr Choice_Liste


Sub Create_Window_Main()
'Hauptfenster

    Dim As Integer i

    Window_Main = Fl_WindowNew  (200, 240, "Combobox")
    Choice_Liste = Fl_ChoiceNew (60, 20, 120, 20, "Auswahl:")
    For i = 0 To 10
        Fl_Menu_Add(Choice_Liste, "Auswahl Nr. " + Str(i))
    Next
    Fl_ChoiceSetValue(Choice_Liste, 0)

End Sub


Sub Choice_Liste_Event Cdecl (widget As Fl_Widget Ptr)
'Callbackfunktion

    Print Fl_ChoiceGetValue(Choice_Liste)

End Sub


'Hauptprogramm

Create_Window_Main()
Fl_WidgetSetCallback0(Choice_Liste, @Choice_Liste_Event)
Fl_WindowShow(Window_Main)
Fl_Run

End

Der zugehörige Screenshot:

Combox

Der Code ist so ähnlich wie beim Beispiel der Listbox. Da jedoch der Fl_Choice
eine Unterklasse von F-Menu_ ist, geschieht das Hinzufügen von Daten nicht mit "Fl_ChoiceAdd", sondern mit Fl_Menu_Add. Mit Fl_ChoiceSetValue wird der Index des zunächst im Fenster der Combobox anzuzeigenden Eintrages angegeben.


4.7 Fl_Menu_Bar, flFileChooser, flMessageBox

Mit Fl_Menu_Bar können wir ein klassiches Menü erzeugen. Beispiel:

#Include "fltk-c.bi"

'Deklaration der Callback-Funktionen - die kommen unten:
Declare Sub Neu Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
Declare Sub Oeffnen Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
Declare Sub Speichern Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
Declare Sub Beenden Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
Declare Sub Info Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)

Dim Shared As Fl_Window Ptr Window_Main
Dim Shared As Fl_Menu_Bar Ptr Menu


Sub CreateWindow_Main()
'Fenster mit Menü

    Window_Main = Fl_WindowNew  (300, 200, "Menü-Test")
    Menu = Fl_Menu_BarNew(0, 0, 300, 30)
    Fl_Menu_Add(Menu, "Datei/Neu",, @Neu())
    Fl_Menu_Add(Menu, "Datei/Öffnen",,@Oeffnen())
    Fl_Menu_Add(Menu, "Datei/Speichern",,@Speichern())
    Fl_Menu_Add(Menu, "Datei/Beenden",,@Beenden())
    Fl_Menu_Add(Menu, "Hilfe/Info",,@Info())

End Sub


'Callback-Funktionen:

Sub Neu Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
    Print "Neue Datei"
End Sub

Sub Oeffnen Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
    'Eine Datei auswählen zum öffnen:
    Dim As ZString Ptr file
    file = flFileChooser("Datei öffnen", "*.bas" + Chr(9) + "*.txt", ExePath(), 1)
    If file<>0 Then Print "Ausgewählte Datei: " + *file
End Sub

Sub Speichern Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
    Print "Datei speichern"
End Sub

Sub Beenden Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
    End
End Sub

Sub Info Cdecl (widget As Fl_Widget Ptr, userdata As Any Ptr)
    'Info anzeigen:
    flMessageBox("Programm-Information", "Menü-Testprogramm")
End Sub


'Hauptprogramm:

CreateWindow_Main()
Fl_WindowShow(Window_Main)
Fl_Run

End

Hier der Screenshot:

Menu

Die Menü-Einträge werden auf sehr einfache Weise mit Fl_Menu_Add erzeugt. Der dritte Parameter kann optional eine Shortcut-Taste für den betreffenden Menüeintrag sein, z.B. FL_CTRL+Asc("b") für "Beenden". Der vierte Parameter verknüpft den Menü-Eintrag mit der zugehörigen Callbackfunktion. Diese muss im Gegensatz zu den bisherigen Beispielen als zweiten Parameter einen Pointer auf userdata enthalten, da mit Fl_Menu_Add eine Verknüpfung mit einer Sub vom Typ Fl_Callback hergestellt wird statt mit einer Sub vom Typ Fl_Callback0 (wie bisher).

Bei den Callbackfunktionen in diesem Beispiel lernen wir auch zwei Standarddialoge kennen: einen flFileChooser und eine flMessageBox.

Der flFileChooser ist ein Dialog zur Dateisuche. Die Syntax ist eigentlich
selbsterklärend, bis auf den letzten Parameter. Dieser hat folgende Bedutung:
1 = relativer Pfad
0 = absoluter Pfad

Die flMessageBox ist eine einfache Messagebox mit nur einem "Close"-Button.

Hier die zugehörigen Screenshots:

flFileChooser:

FileChooser_en

flMessagebox:

Messagebox


4.8 Weitere Standarddialoge (Common dialogs)

(0hne Screenshots)

Braucht man eine Messagebox, bei der der Benutzer eine Entscheidung treffen kann
(z.B. "Ja", "Nein", "Abbrechen"), also bis zu drei Buttons, so nimmt man einen flChoice.

Beispiel für die Verwendung eines flChoice:

Dim As Integer result

result = flChoice("Wollen Sie das Programm wirklich beenden?", "Ja", "Nein", "Vielleicht")

Select Case result
    Case 0
        End
    Case 1
        '.....
    Case 2
        flMessageBox("Was soll das?", "Sie müssen sich schon entscheiden!")
End Select

Weitere Standarddialoge sind der flColorChooser und flInput.

Der flColorChooser ermöglicht eine Farbwahl mit verschiedenen Einstellungen. Soll die Auswahl und die Ausgabe in RGB-Werten von 0 bis 255 erfolgen, ist dies die Syntax:

Dim As UByte r, g, b
flColorChooser("Wählen Sie eine Farbe", r, g, b, FL_COLORCHOOSER_BYTE)
Print "Gewählte Farbe (r, g, b): ", r, g, b

Die Werte r, g und b können als Vorauswahl im Bereich 0 bis 255 vorgewählt werden.
FL_COLORCHOOSER_BYTE bedeutet, dass diese Werte als Byte-Werte (0 bis 255)
im Colorchooser angezeigt und editiert werden können. Mit anderen Flags sind auch
Anzeigen als Dezimalzahlen im relativen Wertebereich von 0 bis 1 möglich oder
Hexadezimalwerte.

flInput ist ein Fenster mit einer Eingabemöglichkeit, z.B.:

Dim As String s
s = *flInput("Geben Sie Ihren Namen ein:", "Otto Mustermann")
Print s

(in diesem Beispiel kann "Otto Mustermann" editiert werden.)




 

Zusätzliche Informationen und Funktionen
  • Das Tutorial wurde am 21.10.2014 von MitgliedLothar Schirm angelegt.
  • Die aktuellste Version wurde am 09.06.2016 von MitgliedLothar Schirm gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen