Tkinter und Calendar

Fragen zu Tkinter.
Antworten
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

hallo freunde,
ich habe ein problem mit den ausgabefenstern.

Code: Alles auswählen

"""
Simple calendar using ttk Treeview together with calendar and datetime
classes.
"""

# -*- coding: cp1252 -*-

import datetime
from time import *
from Tkinter import *
import sys
import calendar
import Tkinter
import tkFont
import ttk

def kontoWahlausgabe():
        ufenster = Tkinter.Tk()
        ufenster.title('Testdatum')
        ufenster.geometry('600x700+485+100')

        def get_calendar(locale, fwday):
            # instantiate proper calendar class
            if locale is None:
                return calendar.TextCalendar(fwday)
            else:
                return calendar.LocaleTextCalendar(fwday, locale)

        class Calendar(ttk.Frame):
            # XXX ToDo: cget and configure

            datetime = calendar.datetime.datetime
            timedelta = calendar.datetime.timedelta

            def __init__(self, master=None, **kw):
                """
                WIDGET-SPECIFIC OPTIONS

                    locale, firstweekday, year, month, selectbackground,
                    selectforeground
                """
                # remove custom options from kw before initializating ttk.Frame
                fwday = kw.pop('firstweekday', calendar.MONDAY)
                year = kw.pop('year', self.datetime.now().year)
                month = kw.pop('month', self.datetime.now().month)
                locale = kw.pop('locale', None)
                sel_bg = kw.pop('selectbackground', '#ecffc4')
                sel_fg = kw.pop('selectforeground', '#05640e')

                self._date = self.datetime(year, month, 1)
                self._selection = None # no date selected

                ttk.Frame.__init__(self, master, **kw)

                self._cal = get_calendar(locale, fwday)

                self.__setup_styles()       # creates custom styles
                self.__place_widgets()      # pack/grid used widgets
                self.__config_calendar()    # adjust calendar columns and setup tags
                # configure a canvas, and proper bindings, for selecting dates
                self.__setup_selection(sel_bg, sel_fg)

                # store items ids, used for insertion later
                self._items = [self._calendar.insert('', 'end', values='')
                                    for _ in range(6)]
                # insert dates in the currently empty calendar
                self._build_calendar()

                # set the minimal size for the widget
                self._calendar.bind('<Map>', self.__minsize)

            def __setitem__(self, item, value):
                if item in ('year', 'month'):
                    raise AttributeError("attribute '%s' is not writeable" % item)
                elif item == 'selectbackground':
                    self._canvas['background'] = value
                elif item == 'selectforeground':
                    self._canvas.itemconfigure(self._canvas.text, item=value)
                else:
                    ttk.Frame.__setitem__(self, item, value)

            def __getitem__(self, item):
                if item in ('year', 'month'):
                    return getattr(self._date, item)
                elif item == 'selectbackground':
                    return self._canvas['background']
                elif item == 'selectforeground':
                    return self._canvas.itemcget(self._canvas.text, 'fill')
                else:
                    r = ttk.tclobjs_to_py({item: ttk.Frame.__getitem__(self, item)})
                    return r[item]

            def __setup_styles(self):
                # custom ttk styles
                style = ttk.Style(self.master)
                arrow_layout = lambda dir: (
                    [('Button.focus', {'children': [('Button.%sarrow' % dir, None)]})]
                )
                style.layout('L.TButton', arrow_layout('left'))
                style.layout('R.TButton', arrow_layout('right'))

            def __place_widgets(self):
                # header frame and its widgets
                hframe = ttk.Frame(self)
                lbtn = ttk.Button(hframe, style='L.TButton', command=self._prev_month)
                rbtn = ttk.Button(hframe, style='R.TButton', command=self._next_month)
                self._header = ttk.Label(hframe, width=15, anchor='center')
                # the calendar
                self._calendar = ttk.Treeview(show='', selectmode='none', height=7)

                # pack the widgets
                hframe.pack(in_=self, side='top', pady=4, anchor='center')
                lbtn.grid(in_=hframe)
                self._header.grid(in_=hframe, column=1, row=0, padx=12)
                rbtn.grid(in_=hframe, column=2, row=0)
                self._calendar.pack(in_=self, expand=1, fill='both', side='bottom')

            def __config_calendar(self):
                cols = self._cal.formatweekheader(3).split()
                self._calendar['columns'] = cols
                self._calendar.tag_configure('header', background='grey90')
                self._calendar.insert('', 'end', values=cols, tag='header')
                # adjust its columns width
                font = tkFont.Font()
                maxwidth = max(font.measure(col) for col in cols)
                for col in cols:
                    self._calendar.column(col, width=maxwidth, minwidth=maxwidth,
                        anchor='e')

            def __setup_selection(self, sel_bg, sel_fg):
                self._font = tkFont.Font()
                self._canvas = canvas = Tkinter.Canvas(self._calendar,
                    background=sel_bg, borderwidth=0, highlightthickness=0)
                canvas.text = canvas.create_text(0, 0, fill=sel_fg, anchor='w')

                canvas.bind('<ButtonPress-1>', lambda evt: canvas.place_forget())
                self._calendar.bind('<Configure>', lambda evt: canvas.place_forget())
                self._calendar.bind('<ButtonPress-1>', self._pressed)

            def __minsize(self, evt):
                width, height = self._calendar.master.geometry().split('x')
                height = height[:height.index('+')]
                self._calendar.master.minsize(width, height)

            def _build_calendar(self):
                year, month = self._date.year, self._date.month

                # update header text (Month, YEAR)
                header = self._cal.formatmonthname(year, month, 0)
                self._header['text'] = header.title()

                # update calendar shown dates
                cal = self._cal.monthdayscalendar(year, month)
                for indx, item in enumerate(self._items):
                    week = cal[indx] if indx < len(cal) else []
                    fmt_week = [('%02d' % day) if day else '' for day in week]
                    self._calendar.item(item, values=fmt_week)

            def _show_selection(self, text, bbox):
                """Configure canvas for a new selection."""
                x, y, width, height = bbox

                textw = self._font.measure(text)

                canvas = self._canvas
                canvas.configure(width=width, height=height)
                canvas.coords(canvas.text, width - textw, height / 2 - 1)
                canvas.itemconfigure(canvas.text, text=text)
                canvas.place(in_=self._calendar, x=x, y=y)

            # Callbacks
            def _pressed(self, evt):
                """Clicked somewhere in the calendar."""
                x, y, widget = evt.x, evt.y, evt.widget
                item = widget.identify_row(y)
                column = widget.identify_column(x)

                if not column or not item in self._items:
                    # clicked in the weekdays row or just outside the columns
                    return

                item_values = widget.item(item)['values']
                if not len(item_values): # row is empty for this month
                    return

                text = item_values[int(column[1]) - 1]
                if not text: # date is empty
                    return

                bbox = widget.bbox(item, column)
                if not bbox: # calendar not visible yet
                    return

                # update and then show selection
                text = '%02d' % text
                self._selection = (text, item, column)
                self._show_selection(text, bbox)

            def _prev_month(self):
                """Updated calendar to show the previous month."""
                self._canvas.place_forget()

                self._date = self._date - self.timedelta(days=1)
                self._date = self.datetime(self._date.year, self._date.month, 1)
                self._build_calendar() # reconstuct calendar

            def _next_month(self):
                """Update calendar to show the next month."""
                self._canvas.place_forget()

                year, month = self._date.year, self._date.month
                self._date = self._date + self.timedelta(
                    days=calendar.monthrange(year, month)[1] + 1)
                self._date = self.datetime(self._date.year, self._date.month, 1)
                self._build_calendar() # reconstruct calendar

            # Properties
            @property
            def selection(self):
                """Return a datetime representing the current selected date."""
                if not self._selection:
                    return None
                year, month = self._date.year, self._date.month
                return self.datetime(year, month, int(self._selection[0]))

        def test():
            import sys
            root = Tkinter.Tk()
            root.title('Ttk Calendar')
            ttkcal = Calendar(firstweekday=calendar.SUNDAY)
            ttkcal.pack(expand=1, fill='both')

            if 'win' not in sys.platform:
                style = ttk.Style()
                style.theme_use('clam')

        b_test = Button(ufenster, text = 'Datum', command=test)
        b_test.place(relx=.78, rely=.65, anchor="c")

        def datumZurueck():
            ufenster.destroy()

        b_beenden = Button(ufenster, text = 'Beenden', command=datumZurueck)
        b_beenden.place(relx=.78, rely=.75, anchor="c")

        ufenster.mainloop()


if __name__ == '__main__':
    kontoWahlausgabe()
und zwar werden immer zwei fenster geöffnet.
ich möchte aber gern in dem kleinen fenster den kalender (datepicker)
angezeigt bekommen, ohne dass das große fenster verändert wird.
nur wie?
BlackJack

@DMD: In dem Code werden zwei Fenster erzeugt. Wenn Du keine zwei Fenster willst dann schreibe keinen Code der zwei Fenster erzeugt. Wobei das nicht geschrieben sondern wild geraten und von anderen Quellen zusammenkopiert aussieht. So funktioniert Programmieren nicht. Lerne die Grundlagen, inklusive objektorientierter Programmierung (OOP), damit Du *verstehst* was Code macht den Du von woanders kopierst, sonst wird das nichts.

Die beiden Fenster sind zudem auch noch *Hauptfenster*, was nicht sein darf, weil ab dem Zeitpunkt wo mehr als ein `Tk`-Exemplar gleichzeitig existiert, das Programmverhalten undefiniert ist. Da können komische Sachen passieren, bis hin zu harten Programmabstürzen.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

...und generell: *-Importe nicht machen!

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

das programm is der stink normale datepicker code,
der als standardisierter ttkcalendar benannt wurde.
ich habe nur ein weiteres Tk-fenster gesetzt, um mein problem zu zeigen.
klar sollen es zwei fenster sein, das eine groß das andere klein.
das kleine soll nach klick den datepicker zeigen, das große soll völlig unverändert
bleiben.
wie sag ich denn

Code: Alles auswählen

ttkcal = Calendar(firstweekday=calendar.SUNDAY)
ttkcal.pack(expand=1, fill='both')
dass es nicht zu

Code: Alles auswählen

root = Tkinter.Tk()
sondern ein eigenständiges toplevel is???
BlackJack

@DMD: In dem Du ein `Toplevel`-Exemplar erstellst und das als `master`-Argument an `Calendar` übergibst. Da sollte man eigentlich immer explizit etwas übergeben.
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

Code: Alles auswählen

eingDatum = Tkinter.Toplevel(master=None)
eingDatum.title('Ttk Calendar')
eingDatum.geometry('200x200+200+200')

eingDatum = Calendar(firstweekday=calendar.MONDAY)
eingDatum.pack(expand=1, fill='both')
???
kannst du mir ein minimales beispiel zeigen?
ich versteh das leider net
Antworten