Forum: PC-Programmierung HTML Gui mit Slidern und Buttons


von chris_ (Gast)


Lesenswert?

Mittlerweile eignen sich Browser ganz als GUI-Frontend für z.B. Java 
oder Python Server.

Ich würden gerne eine Oberfläche mit Slider und Buttons machen, sie 
sollen aber frei positionierbar sein.

Hier ist ein Beispiel für die Erstellung von Slidern:
https://www.w3schools.com/howto/howto_js_rangeslider.asp

Leider werden dort die Elemente aber automatisch plaziert.

Gibt es eine Möglichkeit, beliebig viele Elemente frei zu positionieren?

von Εrnst B. (ernst)


Lesenswert?

CSS, extern als Datei oder inline:
1
<input type="range" style="position: absolute; top: 333px; left: 99px; width: 444px">

Ist aber sch***. Damit bist du auf eine Bildschirmauflösung 
festgenagelt, und das Layout kann sich nicht an PC vs. Tablet vs. 
Telefon vs. Hoch/Querformat anpassen.

: Bearbeitet durch User
von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

Danke für das Beispiel.

>Ist aber sch***. Damit bist du auf eine Bildschirmauflösung
>festgenagelt, und das Layout kann sich nicht an PC vs. Tablet vs.
>Telefon vs. Hoch/Querformat anpassen.

Ich finde das nicht so problematisch, weil man ja in das Bild 
hineinzoomen kann.

von chris_ (Gast)


Lesenswert?

Hat jemand ein Beispiel für Python, wie man die Sliderposition aus der 
Webseite übertragen kann?

von Εrnst B. (ernst)


Lesenswert?

chris_ schrieb:
> Hat jemand ein Beispiel für Python,

Puh. Würde das mit Websockets machen.
Python ist nicht meine Day-To-Day-Sprache, insofern: Besser selber 
Beispiele suchen.

Aber im Prinzip, Server-Seitig im Python:
1
import websockets
2
import asyncio
3
4
### define request_handler here...
5
6
ws_server = websockets.serve(request_handler, "localhost", 1234)
7
8
asyncio.get_event_loop().run_until_complete(ws_server)
9
asyncio.get_event_loop().run_forever()

(Wäre pur Websocket. Vermutlich macht eine Integration mit flask o.Ä. 
mehr Sinn.)

"request_handler" wird dann für jede Nachricht vom Websocket-Client 
ausgeführt.

Client-Seitig im Javascript:
1
const socket = new WebSocket("ws://localhost:1234");
2
socket.onmessage = msg=>{console.log("Antwort von Python:",msg);};
3
socket.send("Hallo Python!");
4
socket.send({"slider1":123,"slider2":456}); 
5
...


Edit: Die "websockets"-Doku ist recht ausführlich:
https://websockets.readthedocs.io/en/stable/intro.html#browser-based-example

: Bearbeitet durch User
von Nur_ein_Typ (Gast)


Lesenswert?

Εrnst B. schrieb:
> chris_ schrieb:
>> Hat jemand ein Beispiel für Python,
>
> Puh. Würde das mit Websockets machen.
> Python ist nicht meine Day-To-Day-Sprache, insofern: Besser selber
> Beispiele suchen.
>
> (Wäre pur Websocket. Vermutlich macht eine Integration mit flask o.Ä.
> mehr Sinn.)

Für Flask gibt es da das Modul flask-socketio von Miguel Grinberg: [1]. 
Funktioniert wunderbar und sehr einfach. Die andere Frage ist 
allerdings, ob es wirklich nötig oder sinnig ist, Websockets zu 
benutzen, das hängt wohl vom Bedienmodell ab: wenn lediglich eine 
einzelne Slidereinstellung möglichst in Echtzeit übertragen werden soll, 
sind Websockets sicherlich eine feine Sache. Aber wenn mehrere in 
irgendeiner Weise zusammenhängende Einstellungen geändert und dann 
zusammen übertragen werden sollen, ist eine Übertragung mit AJAX 
vermutlich die bessere Alternative.

[1] https://flask-socketio.readthedocs.io/en/latest/

von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe mal ein Pythonbeipiel genommen und etwas modifiert. Wenn der 
Slider bewegt wird, gibt Python eine Meldung aus. Ich schaffe es aber 
nicht, den Sliderwert zu übertragen.
Das Problem scheint auf der HTML-Seite zu liegen:
1
function slider3() {
2
                var value = parseInt(document.getElementById('slider3').value).toString(10);
3
                websocket.send(JSON.stringify({action: 'slider'}));
4
}

Hier der Pythonserver:
1
#!/usr/bin/env python
2
# https://websockets.readthedocs.io/en/stable/intro.html#browser-based-example
3
#!/usr/bin/env python
4
5
# WS server example that synchronizes state across clients
6
7
import asyncio
8
import json
9
import logging
10
import websockets
11
12
logging.basicConfig()
13
14
STATE = {"value": 0}
15
16
USERS = set()
17
18
19
def state_event():
20
    return json.dumps({"type": "state", **STATE})
21
22
23
def users_event():
24
    return json.dumps({"type": "users", "count": len(USERS)})
25
26
27
async def notify_state():
28
    if USERS:  # asyncio.wait doesn't accept an empty list
29
        message = state_event()
30
        await asyncio.wait([user.send(message) for user in USERS])
31
32
33
async def notify_users():
34
    if USERS:  # asyncio.wait doesn't accept an empty list
35
        message = users_event()
36
        await asyncio.wait([user.send(message) for user in USERS])
37
38
39
async def register(websocket):
40
    USERS.add(websocket)
41
    await notify_users()
42
43
44
async def unregister(websocket):
45
    USERS.remove(websocket)
46
    await notify_users()
47
48
49
async def counter(websocket, path):
50
    # register(websocket) sends user_event() to websocket
51
    await register(websocket)
52
    try:
53
        await websocket.send(state_event())
54
        async for message in websocket:
55
            data = json.loads(message)
56
            if data["action"] == "minus":
57
                STATE["value"] -= 1
58
                await notify_state()
59
            elif data["action"] == "plus":
60
                STATE["value"] += 1
61
                await notify_state()
62
            elif data["action"] == "slider":
63
                print('slider received')
64
                await notify_state()
65
            else:
66
                logging.error("unsupported event: %s", data)
67
    finally:
68
        await unregister(websocket)
69
70
71
start_server = websockets.serve(counter, "localhost", 6789)
72
73
asyncio.get_event_loop().run_until_complete(start_server)
74
asyncio.get_event_loop().run_forever()

von Nur_ein_Typ (Gast)


Lesenswert?

chris_ schrieb:
> Ich habe mal ein Pythonbeipiel genommen und etwas modifiert. Wenn der
> Slider bewegt wird, gibt Python eine Meldung aus.

Welche?

> Ich schaffe es aber nicht, den Sliderwert zu übertragen.
> Das Problem scheint auf der HTML-Seite zu liegen:
>
1
> function slider3() {
2
>                 var value = 
3
> parseInt(document.getElementById('slider3').value).toString(10);
4
>                 websocket.send(JSON.stringify({action: 'slider'}));
5
> }
6
>

Du holst Dir den eingestellten Wert des Sliders in die Variable "value", 
machst dann aber nichts damit. Probier doch anstelle von
1
{action: 'slider'}

einmal
1
{action: 'slider', 'value': value}

zu benutzen. Ansonsten ist mir nicht ganz klar, warum Du den Wert Deines 
Slider erst in eine Integer parst und dann wieder in einen String 
wandelst, gibt es dafür einen Grund? Zudem ist der Parameter der Basis 
für die toString()-Methode ohnehin per Default 10, eine explizite Angabe 
ist also nicht notwendig.

Ansonsten würde ich Dir trotz allem empfehlen, Dir die Arbeit zu 
erleichtern und entsprechende Frameworks zu benutzen, etwa Flask für 
Python und jQuery für JS -- natürlich bedingt das einen kleinen Aufwand 
für die Einarbeitung, spart Dir aber enorm viel Entwicklungszeit, wenn 
Du mehr willst als ein Minibeispiel.

von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

>{action: 'slider', 'value': value}

Danke dafür. Ich hatte das schon probiert, hatte aber 'value' nicht in 
Anführungsstrichen.

Das ursprüngliche Beispiel, welches ich genommen habe, war zu überladen. 
Im Anhang habe ich es mal auf das wesentliche reduziert.
Man kann den Slider jetzt bewegen, Python empfängt den Wert, sendet ihn 
zurück und er wird auf der Webseite in Echtzeit dargestellt.

>Ansonsten würde ich Dir trotz allem empfehlen, Dir die Arbeit zu
>erleichtern und entsprechende Frameworks zu benutzen,

Das ist so ein Aufwand, den ich immer gerne scheue. Ich bin mir noch 
nicht sicher, wie weit ich diesen Versuch hier treiben will und ich 
wollte mich nicht mehrere Tage mit einem Framework beschäftigen.

Ist meine Implementierung im Anhang so einigermaßen OK?

von Nur_ein_Typ (Gast)


Lesenswert?

chris_ schrieb:
>> Ansonsten würde ich Dir trotz allem empfehlen, Dir die Arbeit zu
>> erleichtern und entsprechende Frameworks zu benutzen,
>
> Das ist so ein Aufwand, den ich immer gerne scheue. Ich bin mir noch
> nicht sicher, wie weit ich diesen Versuch hier treiben will und ich
> wollte mich nicht mehrere Tage mit einem Framework beschäftigen.
>
> Ist meine Implementierung im Anhang so einigermaßen OK?

Mir ist natürlich bewußt, daß das einen gewissen Einarbeitungsaufwand 
erfordert -- aber den hast Du ohnehin, um Dich in Python, JavaScript und 
Websockets zu fuchsen. Ein leichtgewichtiges Microframework wie Flask 
mit Flask-SocketIO und ein kleines JavaScript-Framework wie jQuery 
erhöhen Deinen Aufwand nur minimal, sorgen aber für deutlich 
aufgeräumteren Code und bieten Dir etliches an Funktionalität, welche Du 
ansonsten mühsam von Hand implementieren, testen und pflegen mußt. 
Unterm Strich verringern sie Deinen Aufwand signifikant. Zum Beispiel 
wirst Du Deine "page.html" irgendwie ausliefern müssen, das heißt: Du 
brauchst einen Webserver. Sowas ist für Entwicklungszwecke bereits in 
Flask enthalten, obendrein eine leistungsfähige Template-Engine und ein 
URL-Mapper... und ein Logging, ein sauberes Exception-Handling, ein 
Debugging und obendrein ein paar Sicherheitsfunktionen, die keiner 
selbst entwickeln, testen und pflegen wollen würde...

Dem entsprechend finde ich auch ein paar Kritikpunkte an Deinem Code, so 
werden Deine Websocket-Requests nicht ordentlich geloggt und Dein 
Exception-Handling ist kaputt. Einfach mal alles in einen try-Block zu 
packen ist auch nicht besonders sinnvoll, nur so als Hinweis: warum wird 
Dein finally-Konstrukt eigentlich nie ausgeführt, obwohl es immer 
ausgeführt werden müßte -- und zwar auch dann, wenn keine Exception 
auftritt? Bitte lies' nochmal in der Dokumentation, was finally macht 
und wozu es da ist... ;-)

von chris_ (Gast)


Lesenswert?

>Dem entsprechend finde ich auch ein paar Kritikpunkte an Deinem Code,
Das ist in Ordnung so, ich experimentiere ja gerade ein wenig mit JS un 
den Websockets.

>werden Deine Websocket-Requests nicht ordentlich geloggt

Im Beispiel-Code der original Python-Websockets von hier
https://websockets.readthedocs.io/en/stable/intro.html#browser-based-example
war ein Logging eingebaut.
1
import logging
2
...
3
logging.basicConfig()
4
...
5
                logging.error("unsupported event: %s", data)
Da mir das Beispiel für meine Zwecke überladen schien und ich nicht 
weiß, wofür ich es gebrauchen könnte, habe ich es rausgeworfen.

> und Dein
>Exception-Handling ist kaputt. Einfach mal alles in einen try-Block zu
>packen ist auch nicht besonders sinnvoll, nur so als Hinweis: warum wird
>Dein finally-Konstrukt eigentlich nie ausgeführt, obwohl es immer
>ausgeführt werden müßte -- und zwar auch dann, wenn keine Exception
>auftritt?

Falls ich keine Einrückung verschoben habe, war das so im Original von 
oben drinn.

> Bitte lies' nochmal in der Dokumentation, was finally macht
> und wozu es da ist... ;-)

Hmm ...
https://www.w3schools.com/python/ref_keyword_finally.asp
Du hast Recht, finally sollte immer ausgeführt werden.
Mir ist aber nicht ganz klar, was es im Originacode machen soll.

von chris_ (Gast)


Lesenswert?

Das Original findet sich unter
"Synchronization example"
hier
https://websockets.readthedocs.io/en/stable/intro.html#browser-based-example

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.