Bei Tinter start eine Initialisierungsroutine ausführen

Fragen zu Tkinter.
Antworten
kaninchen
User
Beiträge: 6
Registriert: Montag 3. März 2014, 07:58

Hallo,

ich habe jetzt schon Stunden im Internet und Onlinebüchern damit zugebracht herauszufinden wie man eine Initialisierung bei TKinter realisiert.

Mit Python habe ich noch recht wenig Erfahrung, ich komme mehr aus der Delphi und Java Welt.

Umgebung: Raspberry PI Rev. B, Python 2.7, Debian Wheezy, Projekt Heizungssteuerung

Programmauszug:

Code: Alles auswählen


#!/usr/bin/python

import os
import time

#global progstatus
#global lprogstatus

from Tkinter import *

#Definition Menu Optionen
def statusanhalten():
   progstatus = "0"   
def statusfortsetzen():
   progstatus = "1" 
def heizstatuswinter():
   heizstatus = "1" 
def heizstatussommer():
   heizstatus = "2" 
def heizstatusmanuel():
   heizstatus = "0" 
   
def hkstatusauto():
   hkstatus = "1" 
def hkstatustag():
   hkstatus = "2" 
def hkstatusnacht():
   hkstatus = "3" 
def hkstatusaus():
   hkstatus = "0" 
   
def hkvlstatusz1():
   hkvlstatus = "1" 
def hkvlstatusz3():
   hkvlstatus = "3" 
def hkvlstatusz4():
   hkvlstatus = "4" 
   
def solpumpeein():
   solpumpe = "1" 
def solpumpeaus():
   solpumpe = "0" 
def solpumpeplus():
   solpumpe = "+" 
def solpumpeminus():
   solpumpe = "-" 
def solwtpumpeein():
   solwtpumpe = "1" 
def solwtpumpeaus():
   solwtpumpe = "0"
def vtsolpufferladen():
   vtsolpufferwws = "0" 
def vtsolwwsladen():
   vtsolpufferwws = "1" 
def vtsolpufferz2():
   vtsolpufferstatus = "2" 
def vtsolpufferz3():
   vtsolpufferstatus = "3" 
def vtsolpufferz4():
   vtsolpufferstatus = "4"
def wwsladepumpeein():
   wwsladepumpe = "1" 
def wwsladepumpeaus():
   wwsladepumpe = "0"
def estabein():
   estab = "1" 
def estabaus():
   estab = "0" 

def kamimpumpeein():
   kamimpumpe = "1" 
def kamimpumpeaus():
   kamimpumpe = "0"
def d20ppumpeein():
   d20ppumpe = "1" 
def d20ppumpeaus():
   d20ppumpe = "0" 
def vtkesselvlz2():
   vtkesselvl = "2"
   ausgabe = os.popen("snmpset -v1 -c private 192.168.0.51 .1.3.6.1.4.1.32111.1.1.2.2 i 1")
def vtkesselvlz3():
   vtkesselvl = "3" 
   ausgabe = os.popen("snmpset -v1 -c private 192.168.0.51 .1.3.6.1.4.1.32111.1.1.2.2 i 0")
#Allgemeine Definitionen

#Hauptprogramm

def hauptprogramm():
   canvas.itemconfig(lprogstatus, text="Progamm gestartet")
   while (progstatus == "1"):
      canvas.itemconfig(lprogstatus, text="Progamm gestartet")
      time.sleep(2)

progstatus="1"
#   canvas.itemconfig(lprogstatus, text="Progamm angehalten") 
root = Tk()

#Menu
menubar = Menu(root)
statusmenu = Menu(menubar, tearoff=0)
statusmenu.add_command(label="Starten/Fortsetzen", command=statusfortsetzen)
statusmenu.add_command(label="Anhalten", command=statusanhalten)
statusmenu.add_separator()
statusmenu.add_command(label="Beenden", command=root.quit)
menubar.add_cascade(label="Programm", menu=statusmenu)

heizungmenu = Menu(menubar, tearoff=0)
heizungmenu.add_command(label="Winter", command=heizstatuswinter)
heizungmenu.add_command(label="Sommer", command=heizstatussommer)
heizungmenu.add_command(label="Manuel", command=heizstatusmanuel)
menubar.add_cascade(label="Heizung", menu=heizungmenu)

hkmenu = Menu(menubar, tearoff=0)
hkmenu.add_command(label="Automatik", command=hkstatusauto)
hkmenu.add_command(label="Tag", command=hkstatustag)
hkmenu.add_command(label="Nacht", command=hkstatusnacht)
hkmenu.add_separator()
hkmenu.add_command(label="Aus", command=hkstatusaus)
hkmenu.add_separator()
hkmenu.add_command(label="HK VL Z1", command=hkvlstatusz1)
hkmenu.add_command(label="HK VL Z3", command=hkvlstatusz3)
hkmenu.add_command(label="HK VL Z4", command=hkvlstatusz4)
menubar.add_cascade(label="Heizkreis", menu=hkmenu)

solarmenu = Menu(menubar, tearoff=0)
solarmenu.add_command(label="VRK Pumpe Ein", command=solpumpeein)
solarmenu.add_command(label="VRK Pumpe Aus", command=solpumpeaus)
solarmenu.add_command(label="VRK Pumpe+", command=solpumpeplus)
solarmenu.add_command(label="VRK Pumpe-", command=solpumpeminus)
solarmenu.add_separator()
solarmenu.add_command(label="WT Pumpe Ein", command=solwtpumpeein)
solarmenu.add_command(label="WT Pumpe Aus", command=solwtpumpeaus)
solarmenu.add_command(label="VT Puffer laden", command=vtsolpufferladen)
solarmenu.add_command(label="VT Puffer laden Z2", command=vtsolpufferz2)
solarmenu.add_command(label="VT Puffer laden Z3", command=vtsolpufferz3)
solarmenu.add_command(label="VT Puffer laden Z4", command=vtsolpufferz4)
solarmenu.add_separator()
solarmenu.add_command(label="VT WWS laden", command=vtsolwwsladen)
solarmenu.add_command(label="Ladepumpe WWS Puffer Ein", command=wwsladepumpeein)
solarmenu.add_command(label="Ladepumpe WWS Puffer Aus", command=wwsladepumpeaus)
solarmenu.add_separator()
solarmenu.add_command(label="WWS Heizstab Ein", command=estabein)
solarmenu.add_command(label="WWS Heizstab Aus", command=estabaus)
menubar.add_cascade(label="Solar/WWS", menu=solarmenu)

kaminmenu = Menu(menubar, tearoff=0)
kaminmenu.add_command(label="Pumpe Kamin Ein", command=kamimpumpeein)
kaminmenu.add_command(label="Pumpe Kamin Aus", command=kamimpumpeaus)
kaminmenu.add_separator()
kaminmenu.add_command(label="VT Kessel VL Z2", command=vtkesselvlz2)
kaminmenu.add_command(label="VT Kessel VL Z3", command=vtkesselvlz3)
menubar.add_cascade(label="Kaminofen", menu=kaminmenu)

d20pmenu = Menu(menubar, tearoff=0)
d20pmenu.add_command(label="Pumpe D20P Ein", command=d20ppumpeein)
d20pmenu.add_command(label="Pumpe D20P Aus", command=d20ppumpeaus)
d20pmenu.add_separator()
d20pmenu.add_command(label="VT Kessel VL Z2", command=vtkesselvlz2)
d20pmenu.add_command(label="VT Kessel VL Z3", command=vtkesselvlz3)
menubar.add_cascade(label="D20P", menu=d20pmenu)

root.config(menu=menubar)



# create the canvas, size in pixels
canvas = Canvas(width = 1000, height = 760)

# pack the canvas into a frame/form
canvas.pack(expand = YES, fill = BOTH)

# load the .gif image file
gif1 = PhotoImage(file = 'Hydraulik.gif')

# put gif image on canvas
# pic's upper left corner (NW) on the canvas is at x=50 y=10
canvas.create_image(0, 0, image = gif1, anchor = NW)

canvas.create_line(668,485,755,485,width=3,fill="blue")
canvas.create_line(668,470,668,486,width=3,fill="blue")
canvas.create_line(402,471,669,471,width=3,fill="blue")
canvas.create_line(400,396,400,609,width=3,fill="blue")
canvas.create_line(242,608,401,608,width=3,fill="blue")
canvas.create_line(400,420,469,420,width=3,fill="blue")
canvas.create_line(295,593,295,609,width=3,fill="blue")
canvas.create_line(10,608,89,608,width=3,fill="blue")
canvas.create_line(10,609,10,275,width=3,fill="blue")
canvas.create_line(10,276,17,276,width=3,fill="blue")
canvas.create_line(30,276,525,276,width=3,fill="blue")
canvas.create_line(524,276,524,323,width=3,fill="blue")
canvas.create_line(524,321,627,321,width=3,fill="blue")
canvas.create_line(675,321,688,321,width=3,fill="blue")
canvas.create_line(729,320,749,320,width=3,fill="blue")
canvas.create_line(244,529,354,529,width=3,fill="blue")
canvas.create_line(353,283,353,530,width=3,fill="blue")
canvas.create_line(353,267,353,273,width=3,fill="blue")
canvas.create_line(353,227,353,257,width=3,fill="blue")
canvas.create_line(353,191,353,217,width=3,fill="blue")
canvas.create_line(266,191,524,191,width=3,fill="blue")
canvas.create_line(266,118,266,191,width=3,fill="blue")
canvas.create_line(524,118,524,191,width=3,fill="blue")
canvas.create_line(253,118,267,118,width=3,fill="blue")
canvas.create_line(508,118,525,118,width=3,fill="blue")
canvas.create_line(483,118,492,118,width=3,fill="blue")
canvas.create_line(228,118,238,118,width=3,fill="blue")

#Ventil Solar WT/WWS
vwt1=canvas.create_line(787,319,863,319,width=3,fill="grey")
vwt2=canvas.create_line(863,320,863,428,width=3,fill="grey")
vwt3=canvas.create_line(863,413,939,413,width=3,fill="grey")
vwws1=canvas.create_line(959,413,977,413,width=3,fill="grey")
vwws2=canvas.create_line(977,413,977,543,width=3,fill="grey")
vwws3=canvas.create_line(977,543,813,543,width=3,fill="grey")
#Solarpumpean/aus
psolrl1=canvas.create_line(949,402,949,385,width=3,fill="grey")
psolrl2=canvas.create_line(949,343,949,321,width=3,fill="grey")
psolrl3=canvas.create_line(949,293,949,221,width=3,fill="grey")
psolvl1=canvas.create_line(783,56,783,125,width=3,fill="grey")
psolvl2=canvas.create_line(782,126,835,126,width=3,fill="grey")
psolvl3=canvas.create_line(834,126,834,514,width=3,fill="grey")
psolvl4=canvas.create_line(835,515,813,515,width=3,fill="grey")
psolvl5=canvas.create_line(834,263,786,263,width=3,fill="grey")
#Pumpe SolarWT
psolwt1=canvas.create_line(21,263,752,263,width=3,fill="grey")
psolwt2=canvas.create_line(21,263,21,481,width=3,fill="grey")
psolwt3=canvas.create_line(21,481,32,481,width=3,fill="grey")
psolwtz4_1=canvas.create_line(44,493,44,529,width=3,fill="grey")
psolwtz4_2=canvas.create_line(43,529,89,529,width=3,fill="grey")
psolwtz23_1=canvas.create_line(44,474,44,398,width=3,fill="grey")
psolwtz23_2=canvas.create_line(44,399,54,399,width=3,fill="grey")
psolwtz3_1=canvas.create_line(64,410,64,444,width=3,fill="grey")
psolwtz3_2=canvas.create_line(64,442,89,442,width=3,fill="grey")
psolwtz4_1=canvas.create_line(64,387,64,362,width=3,fill="grey")
psolwtz4_2=canvas.create_line(64,363,89,363,width=3,fill="grey")
#PumpeHK
phk1=canvas.create_line(460,385,469,385,width=3,fill="grey")
phk2=canvas.create_line(412,385,433,385,width=3,fill="grey")
phk3=canvas.create_line(374,385,389,385,width=3,fill="grey")
phk4=canvas.create_line(374,311,374,385,width=3,fill="grey")
phk5=canvas.create_line(178,312,394,312,width=3,fill="grey")
vhkvlz1=canvas.create_line(165,323,165,332,width=3,fill="grey")
vhkvlz34_1=canvas.create_line(165,302,165,291,width=3,fill="grey")
vhkvlz34_2=canvas.create_line(165,291,303,291,width=3,fill="grey")
vhkvlz34_3=canvas.create_line(302,291,302,423,width=3,fill="grey")
vhkvlz3_1=canvas.create_line(244,435,291,435,width=3,fill="grey")
vhkvlz4_1=canvas.create_line(314,435,324,435,width=3,fill="grey")
vhkvlz4_2=canvas.create_line(324,435,324,530,width=3,fill="grey")
#Kamin
d20prl1=canvas.create_line(188,118,206,118,width=3,fill="grey")
d20prl1=canvas.create_line(152,118,160,118,width=3,fill="grey")

if progstatus=="1" : 
   lprogstatus=canvas.create_text(0, 10, anchor=W, text="Status: gestartet")
else : 
   lprogstatus=canvas.create_text(0, 10, anchor=W, text="Status: angehalten") 


#canvas.itemconfig(line1, fill="blue")
# run it ...

mainloop()
Im Prinzip geht es um diesen Teil:

Code: Alles auswählen

if progstatus=="1" : 
   lprogstatus=canvas.create_text(0, 10, anchor=W, text="Status: gestartet")
else : 
   lprogstatus=canvas.create_text(0, 10, anchor=W, text="Status: angehalten") 
Beim Programmstart möchte ich das die Variable progstatus den Wert "1" erhält, so das die IF-Anweisung durchlaufen wird. Wenn ich jedoch im Menu den Menupunkt "Anhalten" klicke, soll progstatus auf "0" gesetzt werden.

In Java ist das kein Problem, da ich die Var progstatus deklarieren, und auch gleichzeitig den Wert "1" übergeben kann.

Wie mache ich dies in Python, bzw, wie kann ich einen Programmteil nur einmalig beim Programmstart durchlaufen lassen, damit ich bestimmte Startzustände einstellen kann?

Vielen Dank

LG kaninchen
BlackJack

@kaninchen: Das würde man in Python genau so machen wie in Java: Eine Klasse schreiben die solche Zustände als Attribut speichert.

Diese ganzen Zeichenketten als Werte sind unschön. Python ist „strongly typed” und nicht „strinlgy typed”. ;-)

Und genau wie in Java würde man in einem sauberen Programm die Programmlogik und die GUI trennen. Also erst einmal einen Typ schreiben, der die zu steunernde Anlage modelliert. Und dann erst eine GUI, die dieses Modell verwendet.

Sternchenimporte und ``global`` sollte man vermeiden. Das schafft nur unübersichtliche Programme wo man nicht mehr so leicht sieht wo eigentlich welcher Wert her kommt und wo er überall potentiell verändert werden kann. Bei `Tkinter` ist zum Beispiel ein ``import Tkinter as tk`` üblich.
kaninchen
User
Beiträge: 6
Registriert: Montag 3. März 2014, 07:58

Hallo,

erst mal Danke für die schelle Reaktion.

Das Problem an der Sache mit der Klasse ist die Parameterübergabe.
Die ganzen Linien die gezogen werden und auch alle Messwerte, das sind über 50 Werte, müssen an die Klasse doch jedes mal übergeben werden. Deshalb sind für mich globale Variablen hier sinvoll, das diese in verschiedenen Klassen immer wieder abgefragt und verändert werden.
Den ganzen Linien werden ja nach Messwert andere Farben zugeordnet, ebenso alle Messwertanzeigen die aktuellen Messwerte aus der Datenbank bzw. direkten Abfrage der Messmodule. Bei den Messwertanzeigen bin ich noch am überlegen, mit welchem Widget ich diese realisieren werde.

Zum veranschaulichen hier mal das Hydraulikbild, welches ich als Hintergrund einblende, und die Verbindungen (die ganzen Linien) zwischen den Heizungsteilen herstelle.

Bild

Das andere ist, das ich den ganzen Programmablauf auch mal anhalten und wieder fortsetzen will, ohne das Programm neu starten zu müssen.

Vielen Dank

LG kaninchen
BlackJack

@kaninchen: Ich verstehe das Problem nicht? Warum kannst Du die Werte nicht als Parameter übergeben? Wo willst Du die überhaupt übergeben? Warum denkst Du 50 einzelne Werte irgendwo übergeben zu müssen? Das wird doch hoffentlich sinnvoll zu Objekten gruppiert.

Globale Variablen sind so gut wie nie sinnvoll. Nicht wenn man ein wartbares, leicht nachvollziehbares Programm haben möchte. Gerade wenn die in verschiedenen Klassem abgefragt und geändert werden, verliert man doch ganz schnell den Überblick was wo benötigt und manipuliert wird.
kaninchen
User
Beiträge: 6
Registriert: Montag 3. März 2014, 07:58

Hallo,

und nochmals Danke!

Ob der Programmierstiel nun "sauber" ist oder nicht, löst leider mein Problem nicht. Ich komme noch aus der logischen und nicht aus der objektorientierten Programmierung, und finde es für mich so wesentlich einfacher. Auch mit globalen Variablen lässt es sich für mich einfacher umsetzen, da jeder Sensor, jede Pumpe, jedes Ventil überall gleich benannt wird und es im gesammten Programm zur Verfügung steht.

In Java war es einfach, durch den Deklarationsteil, Variablen einen Namen und einen Anfangszustand zu geben. Dies scheint ja bei Python in TKinter nicht möglich zu sein.

Eine brauchbare und verständliche Anleitung wie ich diesen Deklarationsteil in Python realisieren kann habe ich bis jetzt noch nicht gefunden.

Für mich erschliesst es sich auch nicht, wie die TKinter Klasse aus einem, ich nenne es mal normalen Pythonprogramm aufgerufen wird, und wie von dort auf die Objekte der Klasse zugegriffen wird und dann auch die Grafik aktualisiert und angezeigt wird.

Die Werte werden teilweise von einem Logger, der auch in Python von mir geschrieben ist in eine MySQL DB geschrieben, und werden auch aus diesem Programm ausgelesen, aufgearbeitet und in die DB geschoben. Ebenfalls werden die Relais für die Steuerung von dem hier beschriebenen Programm geschaltet, und die "Linienführung" farblich dann angepasst und die Werte eingetragen.

Vielen Dank

LG kaninchen
BlackJack

@kaninchen: Wenn Du das in Python programmieren willst, also *mit* der Sprache und nicht *gegen* die Sprache, dann kommst Du nicht um OOP herum. Spätestens bei GUI-Programmierung geht es einfach nicht ohne.

Such Dir am besten eine Programmiersprache die Deinen bevorzugten Programmierstil besser unterstützt. Mit Python wirst Du nicht glücklich werden.
kaninchen
User
Beiträge: 6
Registriert: Montag 3. März 2014, 07:58

Hallo,

solche Antworten müssen doch nicht sein, vor allem nicht von einem Moderator.

Anstatt mal einen Lösungsansatz zu bringen, einem vorzuschlagen man solle was anderes zum Programmieren nehmen hilft keinem!

Ich lerne halt mal anders als Andere. Delphie, Java und C++ sind auch OOP, da hat man allerdings einen Dekarationsteil.

Vieleicht hat ja jemand anderes einen Lösungsansatz für mich, wie mann eine Deklaration in Python ansatzmäßig realisieren kann. Dann komme ich schon mal weiter.

Vielen Dank

LG kaninchen
BlackJack

@kaninchen: Das war eine ernst gemeinte und IMHO hilfreiche Antwort. Den Programmierstil den Du verwenden möchtest kann man nur *gegen* die Sprache durchsetzen. Es wäre also sinnvoller eine Sprache zu verwenden die es einfacher macht globale Variablen zu verwenden, damit Du Dich mehr mit dem eigentlichen Problem und dessen Lösung, als mit der Sprache auseinandersetzen kannst. Da Wheezy auf dem Raspberry Pi letztlich eine ganz normale, vollwertige, und aktuelle Linux-Distribution ist, gibt es auch genug Auswahl an Programmiersprachen. Unter anderem auch die drei von Dir genannte: FreePascal (Delphi), Java, und C++.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Das erinnert mich an ein Kommentar eines etwas älteren Entwicklers: "Hmm, dieses OOP scheint ein interessantes Konzept zu sein, das schaue ich mir vielleicht mal genauer an." Das war 2007 ...

@kaninchen: Black Jack hat mit seinen Ausführungen vollkommen Recht. Gegen eine Sprache zu Programmieren, was du hier massiv versuchst, is absolut kontraproduktiv. Du musst diverse Umwege gehen, kannst nicht alle Features nutzen und bei so einem Programmierstil kannst du aus der Community keine Hilfe erwarten. Das möchte sich niemand antun. Es muss doch einen Grund geben, warum du gerade mit Python arbeiten willst. Die Wahl einer neuen Sprache macht doch nur dann Sinn, wenn man sich damit höhere Effizient und sauberere Programme verspricht. Sonst lohnt ein Umstieg den ganzen Aufwand doch nicht.
Das Leben ist wie ein Tennisball.
BlackJack

@kaninchen: Vielleicht wäre ja Perl etwas für Dich. Auch eine dynamisch typisierte Programmiersprache. Datenbankanbindungen und Tk für die GUI gibt es dort auch.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Als Finanz"berater" bei einer Bank werden wir sicher nicht mehr eingestellt: "Wir haben hier nichts für Sie, gehen Sie doch besser zur Konkurrenz."
Das Leben ist wie ein Tennisball.
kaninchen
User
Beiträge: 6
Registriert: Montag 3. März 2014, 07:58

Hallo,

macht den Unsinn hier zu, oder besser löscht es raus, und meinen Accout auch löschen.

Das hier bringt nichts.
BlackJack

@kaninchen: Ich versuchs noch mal mit Perl:

Code: Alles auswählen

use strict;
use Tk;

my $counter = 0;

my $main_window = MainWindow->new;
my $counter_label = $main_window->Label(-text => $counter)->pack;
$main_window->Button(
    -text => '+1',
    -command => sub {
        $counter++;
        $counter_label->configure(-text => $counter);
    }
)->pack;
MainLoop;
Genau so wie `$counter` kannst Du problemlos beliebig viele Variablen deklarieren die aus Unterfunktionen ohne weiteres verwendet und neu zugewiesen werden können.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi kaninchen

Willkommen in unserem Forum. Habe hier etwas aus deinem Skript für ein Studium zusammengebaut. Das Skript habe ich auf ein Minimum reduziert. Natürlich gibt es diverse Varianten das Skript zu gestalten. Hier meine Variante die du noch um die fehlenden Teile ergänzen musst:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import os
import sys
import textwrap
from functools import partial
try:
    import Tkinter as tk
    import tkFont as tk_font
except ImportError:
    import tkinter as tk
    from tkinter import font as tk_font

OS_LINUX = 'posix'
OS_WINDOWS = 'nt'
OS_MAC = 'mac'
OS_PLATFORM = os.name   # Actual operating system

APP_WIN_XPOS = 0
APP_WIN_YPOS = 0
APP_WIN_WIDTH = 800
APP_WIN_HEIGHT = 200
APP_BACK_GND = "#d1d19d"
APP_FONT = dict(family="Aral", size=10, weight="normal")

PANEL_WIDTH = 1000
PANEL_HEIGHT = 760
PANEL_COLOR = 'gray' #'steelblue'

COORDS_STATUS_LABEL = (10, 40)
TAG_PG_STATUS = 'prg_status'

HEIZSTATUS_MANUELL = 0
HEIZSTATUS_WINTER = 1
HEIZSTATUS_SOMMER = 2

MAIN_MENU = ["Programm", "Heizung"]

MENU = {
    "Programm": {
        "tearoff": False,
        "submenu": [
            "Starten/Fortsetzen",
            "Anhalten",
            "Separator",
            "Beenden"
            ]
        },
        
    "Heizung": {
        "tearoff": False,
        "submenu": [
            "Winter",
            "Sommer",
            "Manuell"
            ]
        },
      }

LINES = [
    [(668,485,755,485), 3, "blue"],
    [(668,470,668,486), 3, "blue"],
    [(402,471,669,471), 3, "blue"],
    [(400,396,400,609), 3, "blue"],
    [(242,608,401,608), 3, "blue"],
    [(400,420,469,420), 3, "blue"],
    [(295,593,295,609), 3, "blue"],
    [(10,608,89,608), 3, "blue"],
    [(10,609,10,275), 3, "blue"],
    [(10,276,17,276), 3, "blue"],
    [(30,276,525,276), 3, "blue"],
    [(524,276,524,323), 3, "blue"],
    [(524,321,627,321), 3, "blue"],
    [(675,321,688,321), 3, "blue"],
    [(729,320,749,320), 3, "blue"],
    [(244,529,354,529), 3, "blue"],
    [(353,283,353,530), 3, "blue"],
    [(353,267,353,273), 3, "blue"],
    [(353,227,353,257), 3, "blue"],
    [(353,191,353,217), 3, "blue"],
    [(266,191,524,191), 3, "blue"],
    [(266,118,266,191), 3, "blue"],
    [(524,118,524,191), 3, "blue"],
    [(253,118,267,118), 3, "blue"],
    [(508,118,525,118), 3, "blue"],
    [(483,118,492,118), 3, "blue"],
    [(228,118,238,118), 3, "blue"]
    ]

# Hier ein Ersatz für 'Ventil Solar WT/WWS'
VALVES = {
    'vwt1' : [(787,319,863,319), 3, "grey"],
    'vwt2' : [(863,320,863,428), 3, "grey"],
    'vwt3' : [(863,413,939,413), 3, "grey"],
    'vwws1': [(959,413,977,413), 3, "grey"],
    'vwws2': [(977,413,977,543), 3, "grey"],
    'vwws3': [(977,543,813,543), 3, "grey"],
    }

class PanelModel(object):
    
    def __init__(self, control, **options):
        self.control = control
        
        self.progstatus = False
        self.heizstatus = HEIZSTATUS_MANUELL
        
        
class PanelGUI(tk.Canvas):
    
    def __init__(self, control, **options):
        self.control = control
        self.app_win = control.win
        
        self.build_menu()
        
        tk.Canvas.__init__(self, self.control.main_frame, **options)
        
        self.flash_flag = False
        
        self.build_panel_layout()

    def build_menu(self):
        menubar = tk.Menu(self.app_win)
        for main_menu_name in MAIN_MENU:
            tearoff = MENU[main_menu_name]["tearoff"]
            menu = tk.Menu(menubar, tearoff=tearoff)
            for sub_menu_name in MENU[main_menu_name]["submenu"]:
                if sub_menu_name == "Separator":
                     menu.add_separator()
                     continue
                else:
                    menu.add_command(label=sub_menu_name, 
                        command=partial(self.menu_callback,
                        main_menu_name, sub_menu_name))
            menubar.add_cascade(label=main_menu_name, menu=menu)
        self.app_win.config(menu=menubar)
        
    def build_panel_layout(self):
        # Statusanzeige
        self.create_text(COORDS_STATUS_LABEL, text='',
            font=('Helfetica', 14, 'bold'), anchor='nw',
            tag=TAG_PG_STATUS)
        
        # Zeichne die normalen Linien
        for coords, width, fill in LINES:
            self.create_line(coords,width=width,fill=fill)
        
        # Zeichne die Ventil Solar WT/WWS Linien    
        for key in VALVES:
            coords, width, fill = VALVES[key]
            self.create_line(coords, width=width, fill=fill, tag=key)

    def menu_callback(self, main_menu, sub_menu):
        """Auswertung von Menu-Aktionen"""
        self.control.menu_callback(main_menu, sub_menu)

    def flash_valve_line(self):
        if self.flash_flag:
            self.flash_flag = False
            self.itemconfig('vwt1', fill='red')
            self.itemconfig('vwt2', fill='red')
            self.itemconfig('vwt3', fill='red')
        else:
            self.flash_flag = True
            self.itemconfig('vwt1', fill='grey')
            self.itemconfig('vwt2', fill='grey')
            self.itemconfig('vwt3', fill='grey')
            
        self.after(200, self.flash_valve_line)

        
class PanelControl(object):
    
    def __init__(self, title):
        self.win = tk.Tk()
        self.win.withdraw()
        self.win.update_idletasks()
        self.app_font = tk_font.Font(**APP_FONT)
        self.global_options()
        self.win.title(title)
        self.screen_width = self.win.winfo_screenwidth()
        self.screen_height = self.win.winfo_screenheight()
        self.win.protocol("WM_DELETE_WINDOW", partial(self.close))
        self.win.config(bg=APP_BACK_GND)
 
        if OS_PLATFORM == OS_LINUX:
            pass
        if OS_PLATFORM == OS_WINDOWS:
            pass
        if OS_PLATFORM == OS_MAC:
            pass
        
        self.main_frame = tk.Frame(self.win)
        self.main_frame.pack(fill='both', expand=True)
        
        self.main_button_frame = tk.Frame(self.win)
        self.main_button_frame.pack(fill='x')
        
        self.app()
        
        button = tk.Button(self.main_button_frame, text="Beenden",
            command=self.close).pack(side='right',padx=2, pady=2)
        
        #~~ Center app window    
        self.win.update_idletasks()
        width = self.win.winfo_reqwidth()
        height = self.win.winfo_reqheight()
        self.center_win(True, width, height)

    #---- TEST APP BEGIN -----------------------------------------------
    
    def app(self):
        self.panel_model = PanelModel(self)
        
        self.panel_gui = PanelGUI(self, bg=PANEL_COLOR,
            width=PANEL_WIDTH, height=PANEL_HEIGHT,
            highlightthickness=0)
        self.panel_gui.pack()
        
        self.panel_gui.itemconfigure(TAG_PG_STATUS,
            text="Status: angehalten", fill='red')

        self.panel_gui.flash_valve_line()
        
    def menu_callback(self, main_menu, sub_menu):
        print main_menu, sub_menu
        
        # Auswertung des Menüs für 'Programm'
        if main_menu == "Programm":
            if sub_menu == "Starten/Fortsetzen":
                self.panel_model.progstatus = True
                self.panel_gui.itemconfigure(TAG_PG_STATUS,
                    text="Status: gestartet", fill='darkolivegreen')
                    
            if sub_menu == "Anhalten":
                self.panel_model.progstatus = False
                self.panel_gui.itemconfigure(TAG_PG_STATUS,
                    text="Status: angehalten", fill='red')
                    
            if sub_menu == "Beenden":
                self.close()
        
        # Auswertung des Menüs für 'Heizung' 
        if main_menu == "Heizung":
            if sub_menu == "Winter":
                self.panel_model.heizstatus = HEIZSTATUS_WINTER
                
            if sub_menu == "Sommer":
                self.panel_model.heizstatus = HEIZSTATUS_SOMMER
                
            if sub_menu == "Manuell":
                self.panel_model.heizstatus = HEIZSTATUS_MANUEL
                
    #---- TEST APP END -------------------------------------------------
        
    def center_win(self, status=False, width=APP_WIN_WIDTH,
        height=APP_WIN_HEIGHT):
        if status:
            xpos = int((self.screen_width - width) / 2)
            ypos = int((self.screen_height - height) / 2)
            app_win_geometry = (width, height, xpos, ypos)
        else:
            app_win_geometry = (width, height, APP_WIN_XPOS,
                APP_WIN_YPOS)
    
        self.win.geometry('{0}x{1}+{2}+{3}'.format(*app_win_geometry))
        
    def global_options(self):
        self.win.option_add(
            "*background", APP_BACK_GND)
        self.win.option_add(
            "*font", self.app_font)

    def run(self):
        self.win.deiconify()
        self.win.mainloop()
    
    def close(self):
        print("Do something before shutdown")
        self.win.destroy()
            
PanelControl("Meine Heizsteuerung").run()
Die Flinte nicht gleich ins Korn werfen, wenn du hier einmal torpediert wirst schliesslich haben wir uns alle vom einer tieferen Ebene langsam nach oben gearbeitet. Es lohnt sich alleweil Python & Tkinter näher kennen zu lernen.

Gruss wuf :wink:
Take it easy Mates!
kaninchen
User
Beiträge: 6
Registriert: Montag 3. März 2014, 07:58

Hallo wuf,

vielen Dank.

Ich werde mich damit befassen, und versuchen es zu verstehen. Eine Rückmeldung erhälst Du auf jeden Fall, kann aber etwas dauern.

Bestimmt, werde ich auch Rückfragen dazu haben.

Warum ich unbedingt Python verwenden will, ist die einfache Art externe Befehle abzusetzen (externe Programme aufzurufen), und die Ergebnisse mit Python zu verarbeiten.

Das ist mit Java leider nicht so einfach möglich.

Aufgeben tue ich sowieso nicht.

Vielen Dank

LG kaninchen
BlackJack

@kaninchen: Zum Aufrufen von externen Programmen sollte man übrigens das `subprocess`-Modul verwenden, das die diversen anderen Möglichkeiten ersetzt.
Antworten