Programm mit GUI aber ohne Desktop

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo Leute,

    ich möchte mich heute Abend mal mit der Programmierung auf dem (bzw. für den) RaspberryPi befassen. Ich würde gerne ein Programm mit GUI schreiben (der RaspberryPi soll in ein Auto als Bordcomputer verbaut werden) allerdings möchte ich dafür nicht jedes mal warten müssen, bis die Desktop Oberfläche geladen ist. Erstmal möchte ich das Programm mit einem Befehl starten können und später soll es dann automatisch gestartet werden. Ich habe mir überleg es in Python zu schreiben, da mir das am sinnvollsten erschein.

    Nun seit ihr gefragt, was denkt ihr ? Ist das was ich da vor habe so ohne weiteres möglich oder nicht ?

    Tobi

  • Aber muss ich dafür wirklich die komplette Desktop Oberfläche laden ??
    Ich hatte früher mal auf einem Debian-Server jDownloader laufen, da konnte ich einfach von der Konsole aus die GUI starten ohne Gnome oder KDE installiert zu haben.

  • Hallo Tobii5,

    eine GUI ohne X (bzw. eine andere graphischen Unterlage) ist per Definition schon mal nicht möglich.

    Entweder begnügst Du Dich mit einer alphanumerischen Bedienkonsole ( so was wie raspi-config ), dann kannst Du das, wie dbv schon sagte, per curses erledigen. Oder Du willst eine GUI (also graphische Oberfläche), dann kommst Du, wie dbv ebenfalls schon andeutete, ohne eine entsprechende "Unterlage" nicht aus.
    Ausser, Du gehörst zu den Masochisten ... dann bastelst Du Dir das selber ... aber ich glaube nicht, dass Du näher wissen willst, was da auf Dich zukommt ;)

    cheers,
    -ds-

  • Nunja, es gibt auch Textbasierte GUI's zum Beispiel über dialog bzw dialog howto

    oder einen python-dialog-wrapper , oder TkInter allerdings ist Tk eigentlich für Desktop-Umgebungen wie zB LXDE


    Ob das allerdings auch mit Touchscreens funktioniert kann ich nicht beantworten


    Vermutlich wäre es einfacher wenn du trotzdem LXDE benutzt und dann den Startvorgang beschleunigst mit zB preload oder systemd


    Da der RPI aber kein PowerManagement besitzt kannst du auch kein Ruhezustand/hibernate bzw Suspend-to-Disk benutzen :-/

    Wenn du den RPI in dein Auto klatschen willst würde ich dir ein spezielles Car Power Supply empfehlen, damit der RPI erst nach 20 Minuten sauber herruntergefahren wird (praktisch wenn du nur kurze stops machst)


  • Nunja, es gibt auch Textbasierte GUI's zum Beispiel über dialog bzw dialog howto
    oder einen python-dialog-wrapper , oder TkInter allerdings ist Tk eigentlich für Desktop-Umgebungen wie zB LXDE
    ...

    Moin meigrafd,

    kleine Korrektur:
    textbasierte GUIs gibts nicht. Das schliesst die Definition "Graphical User Interface" aus.
    Dialog, usw sind - wie ich schon erwähnt habe - alphanumerische Bedienoberflächen (TUIs).
    TkInter hat wohl "widgets" - was aber wieder darauf hindeutet, dass es auch auf X basiert.

    cu,
    -ds-

  • Danke, für die ganzen tollen Antworten :)!!
    Jetzt würde mich aber mal interessieren, was ihr mir, als vollkommenem RaspberryPi neuling, raten würdet. Wie und womit soll ich das Programm schreiben ? Was bietet sich da am ehesten an ?

    Tobi

  • Moin,

    das hatte ich hier mit dem Masochisten-Hinweis gemeint.
    /EDIT: da hatte übrigens dbv auch schon drauf hingewiesen.
    Ich glaube, der eine oder andere versteht hier was komplett falsch. Es geht nicht darum hier mit Wissen zu glänzen sondern zwischen den beiden (meinetwegen auch drei) Möglichkeiten liegen - vom Ansatz bis zur Realsisierung - Welten. Und da fände ich es schon ganz sinnvoll, wenn alle von Anfang an von der selben Zielsetzung reden.
    Ist ja schliesslich auch ein himmelweiter Unterschied, ob ich einen Drucker per USB oder paralleler Schnitstelle anschliesse.

    /Edit: zudem finde ich solche Diskussionen, zumal sie mittlerweile den Großteil dieses Threads füllen, absolut kontraproduktiv.
    Solche Einwände wie GUI <-> TUI sollen den Fragesteller dazu auffordern, seine Fragen konkreter und präziser zu formulieren damit auch was dabei rauskommt. Was er sich jetzt konkret vorgestellt hat, wissen wir nach 13 Posts immer noch nicht ...

    cu,
    -ds-

  • ich wüsste jetzt aber nicht warum der X-Unterbau die Sache vereinfachen soll ?

    für mich klingt die Fragestellung nach vordefinierte Felder wo ich reinschreibe (textbasiert) und wenn ich touche wird eine Aktion ausgelöst. IMHO wäre das eine GUI die textorientiert ist, kommt ohne bunte Icons aus, ohne screens, ohne rc oder ähnliches.

    Mich hatte bei meinem ersten GUI Programm im GEM/später win genervt das ich mich um allen shice kümmern musste (wie z.B. welcher event, ist mein Fenster oben, ist es aktiv und ist der Mauscursor innerhalb) bis endlich mein Programm dran war ! (obwohl das resource construction kit half)

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

  • Hallo Tobii5

    Darf ich Fragen wie erfahren du bist?
    Also wenn du gute Erfahrung mit C/C++ hast ist das keine große Hexerei…

    @morob65
    „es gibt eine graphische öberfläche ohne x, framebuffer programmierung. wird heute nur kaum noch verwendet.“
    Hmm, also alle mir bekannten systeme ob Android, X Window, DirectFB nutzen zuerst mal das
    Framebuffer Device bevor sie was anderes machen… Android macht immensen Gebrauch davon…
    Wenn du damit meinst dass die wenigsten die Variante in ihren Anwendungen benutzen,
    da hast du recht…


    Die Manuellen schritte sind …
    Framebuffer öffnen …
    Console umleiten …
    Input Device öffnen…
    Optional Graphics Library Initialisieren …
    Auf die Input Events hören …
    Input Device schließen …
    Console zurückstellen…
    Framebuffer schließen…
    Machen alle Fenstersysteme bei Unix in der art…

    Alternativ gibt’s da noch die DirectFB library … beinhaltet auch ein kleines fenster system …
    Die frage ist ja brauchst du ein Fenster-System?
    Oder reicht dir die ausgabe am Screen/Display?

    Hier ein Beispiel (Framebuffer mit Cairo)
    das ich für meine eigene Platform geschrieben hab...
    du musst nur "/System/Devices/fb0" durch "/dev/fb0" ersetzen...


    [font="Courier New"]

    Spoiler anzeigen

    [/font]
    [font="Courier New"]#include[/font][font="Courier New"] <stdio.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <stdlib.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <sys/mman.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <sys/ioctl.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <cairo/cairo.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <linux/types.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <linux/limits.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <linux/fb.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <unistd.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <fcntl.h>[/font]
    [font="Courier New"]#include[/font][font="Courier New"] <math.h>[/font]


    [font="Courier New"]/* Locals */[/font]
    [font="Courier New"]static[/font][font="Courier New"] cairo_t *fb_context;[/font]
    [font="Courier New"]static[/font][font="Courier New"] cairo_surface_t *fb_surface;[/font]
    [font="Courier New"]static void[/font][font="Courier New"] *fb_data;[/font]
    [font="Courier New"]static int[/font][font="Courier New"] fb_handle;[/font]
    [font="Courier New"]static int[/font][font="Courier New"] fb_height;[/font]
    [font="Courier New"]static int[/font][font="Courier New"] fb_stride;[/font]
    [font="Courier New"]static int[/font][font="Courier New"] fb_width;[/font]
    [font="Courier New"]static int[/font][font="Courier New"] fb_size;[/font]
    [font="Courier New"]static int[/font][font="Courier New"] fb_bpp;[/font]

    [font="Courier New"]/* Open the Fraembuffer Device */[/font]
    [font="Courier New"]static int[/font][font="Courier New"] OpenFramebuffer(void)[/font]
    [font="Courier New"]{[/font]
    [font="Courier New"] int handle = -1;[/font]
    [font="Courier New"] if ((handle = open("/System/Devices/fb0", O_RDWR)) < 0)[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] printf("Open Framebuffer failed!\n");[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] struct fb_fix_screeninfo fix;[/font]
    [font="Courier New"] if (ioctl(handle, FBIOGET_FSCREENINFO, &fix) < 0)[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] printf("FBIOGET_FSCREENINFO failed!\n");[/font]
    [font="Courier New"] close(handle);[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] struct fb_var_screeninfo var;[/font]
    [font="Courier New"] if (ioctl(handle, FBIOGET_VSCREENINFO, &var) < 0)[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] printf("FBIOGET_VSCREENINFO failed!\n");[/font]
    [font="Courier New"] close(handle);[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] void *data = NULL;[/font]
    [font="Courier New"] size_t length = (var.yres * fix.line_length);[/font]
    [font="Courier New"] if ((data = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, handle, 0)) == MAP_FAILED)[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] printf("Map Memory failed!\n");[/font]
    [font="Courier New"] close(handle);[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] fb_handle = handle;[/font]
    [font="Courier New"] fb_width = (int)var.xres;[/font]
    [font="Courier New"] fb_height = (int)var.yres;[/font]
    [font="Courier New"] fb_stride = (int)fix.line_length;[/font]
    [font="Courier New"] fb_size = (int)(var.yres * fix.line_length);[/font]
    [font="Courier New"] fb_bpp = (int)var.bits_per_pixel;[/font]
    [font="Courier New"] fb_data = data;[/font]

    [font="Courier New"] printf("Width: %d\n", fb_width);[/font]
    [font="Courier New"] printf("Height: %d\n", fb_height);[/font]
    [font="Courier New"] printf("Bpp: %d\n", fb_bpp);[/font]

    [font="Courier New"] return 1;[/font]

    [font="Courier New"]}[/font]

    [font="Courier New"]/* Get the Cairo Format from Framebuffer Device. */[/font]
    [font="Courier New"]static[/font][font="Courier New"] cairo_format_t GetFramebufferFormat(int bpp)[/font]
    [font="Courier New"]{[/font]
    [font="Courier New"] switch (bpp)[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] case 16:[/font]
    [font="Courier New"] return CAIRO_FORMAT_RGB16_565;[/font]
    [font="Courier New"] case 24:[/font]
    [font="Courier New"] return CAIRO_FORMAT_RGB24;[/font]
    [font="Courier New"] case 32:[/font]
    [font="Courier New"] return CAIRO_FORMAT_ARGB32;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] return CAIRO_FORMAT_INVALID;[/font]
    [font="Courier New"]}[/font]

    [font="Courier New"]/* Creates the Framebuffer Surface. */[/font]
    [font="Courier New"]static int[/font][font="Courier New"] CreateFramebufferSurface(void)[/font]
    [font="Courier New"]{[/font]
    [font="Courier New"] cairo_format_t format;[/font]
    [font="Courier New"] if ((fb_data == NULL) || (fb_width <= 0) || (fb_height <= 0))[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] printf("Invalid Framebuffer!\n");[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] format = GetFramebufferFormat(fb_bpp);[/font]
    [font="Courier New"] if (format == CAIRO_FORMAT_INVALID)[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] printf("Invalid Framebuffer format!\n");[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] fb_surface = cairo_image_surface_create_for_data((unsigned char*)fb_data, format, fb_width, fb_height, fb_stride);[/font]
    [font="Courier New"] if ((fb_surface == NULL))[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] printf("Create Surface failed!\n");[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] return 1;[/font]
    [font="Courier New"]}[/font]

    [font="Courier New"]static int[/font][font="Courier New"] DestroySurface(void)[/font]
    [font="Courier New"]{[/font]
    [font="Courier New"] return 1;[/font]
    [font="Courier New"]}[/font]

    [font="Courier New"]static int[/font][font="Courier New"] DrawText(void)[/font]
    [font="Courier New"]{[/font]
    [font="Courier New"] cairo_save(fb_context);[/font]
    [font="Courier New"] cairo_set_source_rgb(fb_context, 0.0, 1.0, 1.0); [/font]
    [font="Courier New"] cairo_set_font_size(fb_context, 30);[/font]

    [font="Courier New"] cairo_move_to(fb_context, 20, 30);[/font]
    [font="Courier New"] cairo_show_text(fb_context, "Most relationships seem so transitory");[/font]

    [font="Courier New"] cairo_move_to(fb_context, 20, 60);[/font]
    [font="Courier New"] cairo_show_text(fb_context, "They're all good but not the permanent one");[/font]

    [font="Courier New"] cairo_move_to(fb_context, 20, 120);[/font]
    [font="Courier New"] cairo_show_text(fb_context, "Who doesn't long for someone to hold");[/font]

    [font="Courier New"] cairo_move_to(fb_context, 20, 150);[/font]
    [font="Courier New"] cairo_show_text(fb_context, "Who knows how to love you without being told");[/font]

    [font="Courier New"] cairo_move_to(fb_context, 20, 180);[/font]
    [font="Courier New"] cairo_show_text(fb_context, "Somebody tell me why I'm on my own");[/font]

    [font="Courier New"] cairo_move_to(fb_context, 20, 210);[/font]
    [font="Courier New"] cairo_show_text(fb_context, "If there's a soulmate for everyone");[/font]

    [font="Courier New"] cairo_restore(fb_context);[/font]
    [font="Courier New"] return 1;[/font]

    [font="Courier New"]}[/font]

    [font="Courier New"]/* Close the Framebuffer Device */[/font]
    [font="Courier New"]static int[/font][font="Courier New"] CloseFramebuffer(void)[/font]
    [font="Courier New"]{[/font]
    [font="Courier New"] if ((fb_data != NULL))[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] munmap(fb_data, fb_size);[/font]
    [font="Courier New"] fb_data = NULL;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] if ((fb_handle >= 0))[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] close(fb_handle);[/font]
    [font="Courier New"] fb_handle = -1;[/font]
    [font="Courier New"] }[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"]}[/font]

    [font="Courier New"]/* Entry Point */[/font]
    [font="Courier New"]int[/font][font="Courier New"] main(int argc, char *argv[])[/font]
    [font="Courier New"]{[/font]
    [font="Courier New"] int count = 0;[/font]
    [font="Courier New"] fb_context = NULL;[/font]
    [font="Courier New"] fb_surface = NULL;[/font]

    [font="Courier New"] /* Open the Framebuffer */[/font]
    [font="Courier New"] if ((OpenFramebuffer() <= 0))[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] if ((CreateFramebufferSurface() <= 0))[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] fb_context = cairo_create(fb_surface);[/font]
    [font="Courier New"] if ((fb_context == NULL))[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] cairo_set_source_rgb(fb_context, 0, 0, 0);[/font]
    [font="Courier New"] cairo_set_line_width(fb_context, 1);[/font]
    [font="Courier New"] cairo_rectangle(fb_context, 20, 20, 120, 80);[/font]
    [font="Courier New"] cairo_rectangle(fb_context, 180, 20, 80, 80);[/font]
    [font="Courier New"] cairo_stroke_preserve(fb_context);[/font]
    [font="Courier New"] cairo_set_source_rgb(fb_context, 1, 1, 1);[/font]
    [font="Courier New"] cairo_fill(fb_context);[/font]

    [font="Courier New"] cairo_set_source_rgb(fb_context, 0, 0, 0);[/font]
    [font="Courier New"] cairo_arc(fb_context, 330, 60, 40, 0, 2*M_PI);[/font]
    [font="Courier New"] cairo_stroke_preserve(fb_context);[/font]
    [font="Courier New"] cairo_set_source_rgb(fb_context, 1, 1, 1);[/font]
    [font="Courier New"] cairo_fill(fb_context);[/font]

    [font="Courier New"] cairo_set_source_rgb(fb_context, 0, 0, 0);[/font]
    [font="Courier New"] cairo_arc(fb_context, 90, 160, 40, M_PI/4, M_PI);[/font]
    [font="Courier New"] cairo_close_path(fb_context);[/font]
    [font="Courier New"] cairo_stroke_preserve(fb_context);[/font]

    [font="Courier New"] cairo_set_source_rgb(fb_context, 1, 1, 1);[/font]
    [font="Courier New"] cairo_fill(fb_context);[/font]


    [font="Courier New"] cairo_set_source_rgb(fb_context, 0, 0, 0);[/font]
    [font="Courier New"] cairo_translate(fb_context, 220, 180);[/font]
    [font="Courier New"] cairo_scale(fb_context, 1, 0.7);[/font]
    [font="Courier New"] cairo_arc(fb_context, 0, 0, 50, 0, 2*M_PI);[/font]
    [font="Courier New"] cairo_stroke_preserve(fb_context);[/font]
    [font="Courier New"] cairo_set_source_rgb(fb_context, 1, 1, 1);[/font]

    [font="Courier New"] cairo_fill(fb_context);[/font]

    [font="Courier New"] while ((count <= 10))[/font]
    [font="Courier New"] {[/font]
    [font="Courier New"] DrawText();[/font]
    [font="Courier New"] sleep(1);[/font]
    [font="Courier New"] count++;[/font]
    [font="Courier New"] }[/font]

    [font="Courier New"] cairo_destroy(fb_context);[/font]
    [font="Courier New"] DestroySurface();[/font]
    [font="Courier New"] CloseFramebuffer();

    [/font]
    [font="Courier New"] return 0;[/font]
    [font="Courier New"]}


    Vielleicht kannst du damit was anfangen...
    Der einstieg ist nicht all zu leicht...
    aber die Performance spricht für sich …

    Grüße
    Andreas

    [/font]

    Einmal editiert, zuletzt von Turael (28. August 2013 um 14:20)

  • Das hört sich ja schon mal sehr gut an, allerdings habe ich keine Ahnung womit ich ein C++ Programm (müsste doch das von dir gepostete programm sein) auf dem RaspberryPi erstellen und Kompilieren kann und wie ichs dann ausführe.

  • Ich kram mal den thread wieder raus. Kanns leider nicht direkt grade am pi testen aber mit meiner Mint Installation klappts ganz gut.

    Ich nutze FreeBasic und habe mich an die gute alte QBasic zeit erinnert wo man ganz einfach mit SCREEN 1 raus aus dem Textmodus kahm. Das ganze klappt unter Linux auch ganz gut mit


    Code
    SCREEN 12
    CLS
    Circle (100,100), 100, 15
    Print "Hallo Welt"
    
    
    Sleep

    auf dem Desktop Öffnet sich beim ausführen ein kleines Fenster. Boote ich jedoch jetzt bei GRUB mit dem zusatz TEXT und lande nach dem booten in der konsole starte das ganze habe ich eine wunderbare umgebung auf dem schirm.Schwarzer Hintergrund, Weißer Kreis, Weißer Text.


    Ich denke mal es wird eine XOrg Installation vorausgestzt aber du spaarst damit auf jeden fall ein paar sekunden des bootvorganges und hast eine vollbildumgebung die du bemalen kannst

  • Ich würde einfach Python mit Qt oder TkInter verwenden. Einen X-Server starten und dann das Python Programm laufen lassen. Ich sehe keinen Grund warum das nicht funktionieren sollte.

    Gruß Thorsten

    Einmal editiert, zuletzt von surfhai (4. Dezember 2013 um 21:34)

  • Im auto gehts ja darum das das ding nicht erst 2 minuten booten muss übertrieben gesagt. Vorallem will man keinen desktop sehn wenns mal fehler gibt wie z.b. auf diversen terminals am flughafen etc

    hier mal ein kleines testprogramm :) gestartet aus dem terminal STRG+ALT+F1

    i6pgdcx8.jpg


  • Hallo erst einmal (erstes Posting)!

    Über die Suchmaschine bin ich zu Euch gekommen.
    Derzeit teste ich noch alle erdenklichen Möglichkeiten mit dem Pi.

    Demnächst möchte ich ein kleines Display über den Video Ausgang als Statusanzeige für den mpd nutzen und stellte mir die selbe Frage was die GUI angeht.

    Am Wochenende ist mir vielleicht die Idee gekommen.... ist aber noch ungetestet.

    Von der Sache her, sollte doch ein leerer Desktop ohne Panel, Icons, etc. reichen... ein schönes Hintergrundbild.... die Ausgaben des MPDs wie Titel, Album, Cover, etc. werden mit conky dargestellt.

    Somit hat man max. Flexibilität und conky ist ein Leichtgewicht.
    Die Informationen werden per mpc abgefragt. Der Rest ist conky-config und shell script.

    ....sollte funktionieren?!

    .... wenn es schon eine Desktopumgebung sein muss.


    Gruss, Jürgen

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!