GTK Vew und Code trennen - Links Infos und Tutorials gesucht
Verfasst: Freitag 13. Mai 2016, 13:53
Hallo
Ich habe diverse kleine Projekte die ich mit GTK2 (pygtk Modul) angefangen habe. Bei diesen habe ich immer View und Code in einem Skript.
Nun habe ich schon oft gehört, dass man die Sicht und den Code trennen soll. Das würde ich gerne umsetzen und freue mich wenn jemand hierzu ein paar Links, Infos oder Tutorials empfehlen kann. Gleichzeitig werde ich dann einen Umstieg auf GTK3 wagen (gi.repository Modul))
Hier noch ein Beispiel eines der Skripte, ein kleines Fenster dass Paket-Sendungen aus einer Datenbank ausliest.
edit:
aus dem Thema "Trennung von Gui und Code" (viewtopic.php?t=21411)
Stichworte: "Model-View-Controller"-Konzept,
Tipps: Eine Klassen für GUI, eine für Funktionen.
In wie fern ist hier gtkmvc zu empfehlen, auch in Hinblick auf einen Wechsel auf Python 3.0 in den nächsten 1-2 Jahren ?
Bisher habe ich separaten XML Dateien vermieden, dies scheint aber wohl doch das Konzept der Zukunft zu sein?
Ich habe diverse kleine Projekte die ich mit GTK2 (pygtk Modul) angefangen habe. Bei diesen habe ich immer View und Code in einem Skript.
Nun habe ich schon oft gehört, dass man die Sicht und den Code trennen soll. Das würde ich gerne umsetzen und freue mich wenn jemand hierzu ein paar Links, Infos oder Tutorials empfehlen kann. Gleichzeitig werde ich dann einen Umstieg auf GTK3 wagen (gi.repository Modul))
Hier noch ein Beispiel eines der Skripte, ein kleines Fenster dass Paket-Sendungen aus einer Datenbank ausliest.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
sudo apt-get install python-keyring (Version >= 4 )
echo - C '''[Desktop Entry]
Comment=
Terminal=True
Name=Shipments GTK
Exec=python shipments_gtk.py
Type=Application
Icon=''' > ~/.local/share/applications/shipment_search_gtk.desktop
19.04.2016
"""
import os
import sys
import gtk
import csv
import time
import datetime
import logging
from import_2_db import load_from_mail_archives
from sqlite3 import dbapi2 as sqlite
## LOGGING
logger = logging.getLogger("ShipmentsGTK")
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(name)s(%(lineno)s) - %(levelname)s: %(message)s", datefmt='%Y.%m.%d %H:%M:%S')
logger.info("starting script ShipmentsGTK")
logger.info("Path of script: %s", (os.path.abspath(sys.argv[0]))
## CONFIG
DATABASE = os.path.join (os.path.expanduser('~'), "TOOLS/data/intraship")
class ShipmentsGTK:
def destroy(self, widget, data=None ):
logger.debug("run destroy")
gtk.main_quit()
# visibility determined by name
def visible_func(self, model, iter, data=None):
if self.searchbox.get_text():
query = self.searchbox.get_text().lower()
values = []
for n in [0, 2, 3, 4, 6, 7]:
if model.get_value(iter, n):
values.append(model.get_value(iter, n))
values = " ".join(values)
if query in values.lower():
return True
else:
return False
else:
return True
# filter function
def on_entry_refilter(self, widget):
logger.debug("run on_entry_refilter")
self.modelfilter = self.liststore.filter_new()
self.treeview.set_model(self.modelfilter)
self.modelfilter.set_visible_func(self.visible_func, self.searchable_row_content)
self.modelfilter.refilter()
# download new data
def download(self, widget):
logger.debug("run download")
load_from_mail_archives()
base.load_from_db()
def onSelectionChanged(self, widget, data=None):
logger.debug("run onSelectionChanged")
selection = self.treeview.get_selection()
selection.set_mode(gtk.SELECTION_SINGLE)
selected_tree_model, selected_tree_iter = selection.get_selected()
if selected_tree_iter:
self.selected_info_shipping_number.set_text(selected_tree_model.get_value(selected_tree_iter, 0) )
self.selected_info_date.set_text(selected_tree_model.get_value(selected_tree_iter, 1) )
self.selected_info_name.set_text(selected_tree_model.get_value(selected_tree_iter, 2) )
self.selected_info_street.set_text(selected_tree_model.get_value(selected_tree_iter, 3) )
self.selected_info_city.set_text(selected_tree_model.get_value(selected_tree_iter, 4) )
self.selected_info_country.set_text(selected_tree_model.get_value(selected_tree_iter, 5) )
#self.selected_info_phone.set_text(selected_tree_model.get_value(selected_tree_iter, 6) )
self.selected_info_reference.set_text(selected_tree_model.get_value(selected_tree_iter, 7) )
def load_from_db(self, widget=None):
logger.debug("run load_from_db")
logger.debug("connect to database")
con = sqlite.connect(DATABASE)
cur = con.cursor()
cur.execute("SELECT * FROM intraship")
logger.info("cur.description = %s", cur.description)
header = [desc[0] for desc in cur.description]
logger.info("header = %s", header)
if not self.liststore:
# create store and treeview
self.liststore = gtk.ListStore(*[type(col) for col in header])
self.modelfilter = self.liststore.filter_new()
self.my_tree_model_sort = gtk.TreeModelSort(self.modelfilter)
self.treeview = gtk.TreeView(self.my_tree_model_sort)
self.treeview.connect("cursor-changed", self.onSelectionChanged)
# fill treeview
logger.debug("fill treeview")
for number, name in enumerate(header):
logger.debug("column %s = %s", number, name)
cell = gtk.CellRendererText()
cell.set_property('editable', True)
column = gtk.TreeViewColumn(name, cell, text=number)
column.add_attribute(cell, "text", number)
column.set_sort_column_id(number)
self.treeview.append_column(column)
model_tree_sortable = self.treeview.get_model()
#sort_function = model_tree_sortable.get_default_sort_func()
model_tree_sortable.set_default_sort_func(lambda *unused: 0)
self.treeview.set_search_entry(self.searchbox)
self.main_sw.add_with_viewport(self.treeview)
logger.debug("clear existing store content")
self.liststore.clear()
# fill store with content
self.treeview.freeze_child_notify()
self.treeview.set_model(None)
self.searchable_row_content = []
logger.debug("add content to store")
n = 0
for n, line in enumerate(cur):
line = [l.encode("utf8") for l in line]
self.liststore.append(line)
self.searchable_row_content.append((line[2], line[3]))
self.selected_info_entry.set_text(%s entries", n)
self.treeview.set_model(self.my_tree_model_sort)
self.treeview.thaw_child_notify()
self.window.show_all()
def __init__(self):
self.liststore = None
# main window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title("Intraship")
self.window.set_position(gtk.WIN_POS_CENTER)
self.window.set_size_request(1000, 600)
# main box
self.mainbox = gtk.VBox()
self.window.add(self.mainbox)
# search box
self.searchbox = gtk.Entry()
self.searchbox.connect("changed", self.on_entry_refilter)
self.mainbox.pack_start(self.searchbox, expand=False)
# buttons
self.buttonbox = gtk.HBox()
self.mainbox.pack_start(self.buttonbox, expand=False)
self.loadbutton = gtk.Button("Load")
self.loadbutton.connect("clicked", self.load_from_db)
self.buttonbox.pack_start(self.loadbutton, expand=False)
self.downloadbutton = gtk.Button("Download")
self.downloadbutton.connect("clicked", self.download)
self.buttonbox.pack_start(self.downloadbutton, expand=False)
# scrolled window box
self.main_sw = gtk.ScrolledWindow()
self.mainbox.pack_start(self.main_sw, expand=True)
# Info Label
self.selected_info_entry = gtk.Label("Info")
self.selected_info_entry.set_selectable(1)
self.selected_info_entry.set_text(str(0)+" entries" )
self.buttonbox.pack_start(self.selected_info_entry, expand=False)
## Selected Info Box
self.selected_info_box = gtk.HBox()
self.mainbox.pack_start(self.selected_info_box, expand=False)
# left info box
self.selected_info_left = gtk.VBox()
self.selected_info_box.pack_start(self.selected_info_left)
self.selected_info_shipping_number = gtk.Label("Number")
self.selected_info_shipping_number.set_selectable(1)
self.selected_info_left.pack_start(self.selected_info_shipping_number)
self.selected_info_date = gtk.Label("Date")
self.selected_info_date.set_selectable(1)
self.selected_info_left.pack_start(self.selected_info_date)
self.selected_info_reference = gtk.Label("Reference")
self.selected_info_reference.set_selectable(1)
self.selected_info_left.pack_start(self.selected_info_reference)
# middle info box
self.selected_info_mid = gtk.VBox()
self.selected_info_box.pack_start(self.selected_info_mid)
self.selected_info_name = gtk.Label("Name")
self.selected_info_name.set_selectable(1)
self.selected_info_mid.pack_start(self.selected_info_name)
self.selected_info_street = gtk.Label("Street")
self.selected_info_street.set_selectable(1)
self.selected_info_mid.pack_start(self.selected_info_street)
self.selected_info_city = gtk.Label("City")
self.selected_info_city.set_selectable(1)
self.selected_info_mid.pack_start(self.selected_info_city)
self.selected_info_country = gtk.Label("Country")
self.selected_info_country.set_selectable(1)
self.selected_info_mid.pack_start(self.selected_info_country)
# right info box
self.selected_info_right = gtk.VBox()
self.selected_info_box.pack_start(self.selected_info_right)
# exit button
self.exitbutton = gtk.Button(stock=gtk.STOCK_QUIT)
self.exitbutton.connect("clicked", self.destroy)
self.mainbox.pack_start(self.exitbutton, expand=False)
# show main window
self.window.show_all()
self.window.connect("destroy", self.destroy)
def main(self):
gtk.main()
if __name__ == "__main__":
base = ShipmentsGTK()
base.load_from_db()
base.main()
aus dem Thema "Trennung von Gui und Code" (viewtopic.php?t=21411)
Stichworte: "Model-View-Controller"-Konzept,
Tipps: Eine Klassen für GUI, eine für Funktionen.
In wie fern ist hier gtkmvc zu empfehlen, auch in Hinblick auf einen Wechsel auf Python 3.0 in den nächsten 1-2 Jahren ?
Bisher habe ich separaten XML Dateien vermieden, dies scheint aber wohl doch das Konzept der Zukunft zu sein?