2014-11-16 14 views
5

ändern Ich bin mit ttkcalendar.py die in this link.ttk.Treeview - Kann nicht Zeilenhöhe

gefunden werden kann ich es für den Einsatz in Python 3.3

Grundsätzlich angepasst habe, was ich versuche zu tun, geben Sie Dieses Kalender-Widget in meiner Tkinter-Anwendung, das funktioniert gut und es gibt keine Probleme dort.

Die Probleme, die ich wünschte, zu überwinden sind:

  1. Wie ändere ich die Schriftgröße des Kalenders (Monat, Tag & Termine) - abgeschlossen
  2. Wie kann ich das ausgewählte Datum ändern, so es geht bold. -
  3. Wie kann ich die Höhe der Zeilen in der treeview wie in prevoius versuchen Schriftgröße kann erhöht werden, aber die Zeilenhöhe erhöht sich nicht mit der Schriftgröße. - NOCH ERWARTENDE HILFE

Vielen Dank im Voraus.

EDIT 1:

für das gesamte Programm unter dem Code finden:

import calendar 
import tkinter as Tkinter 
import tkinter.font as tkFont 
from tkinter import ttk        #Imports ttk Module 

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): 
    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', '#EEEEEE') 
     sel_fg = kw.pop('selectforeground', '#B6333B') 

     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 & Setup Tags 
     #Configure a Canvas & Proper Bindings for Selecting Dates 
     self.__setup_selection(sel_bg, sel_fg) 

     #Store Item ids - Used for Insertion Later On 
     self._items = [self._calendar.insert('', 'end', values='') 
          for _ in range(6)] 
     #Insert Dates in the Currently Empty Calendar 
     self._build_calendar() 

     #Set Minimal Size for 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 & 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', font='Arial 20') 
     #Main Calendar 
     self._calendar = ttk.Treeview(show='', selectmode='none', height='6') 
     #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', font='Arial 20') 
     self._calendar.insert('', 'end', values=cols, tag=('header', 'dayFont')) 
     #Change Font of dayFont TAG 
     self._calendar.tag_configure('dayFont', font='Arial 20') 
     #Adjust Column Widths 
     font = tkFont.Font(size=20) 
     maxwidth = max(font.measure(col) for col in cols) 
     for col in cols: 
      self._calendar.column(col, width=maxwidth, minwidth=maxwidth, anchor='c') 

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

     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 Showing 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, tag='bodyFont') 
      self._calendar.tag_configure('bodyFont', font='Arial 10')   


    def _show_selection(self, text, bbox): #SELECTION FONT 
     """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, font='Arial 15 bold') 
     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 is not Visible Yet 
      return 

     #Update & 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) 
     #Reconstruct Calendar 
     self._build_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() 

    #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])) 

#---------------------------------- 

EDIT 2:

Wie kann ich die relief der Treeview ändern?

Antwort

9

Vielleicht wie Sie, erwartete ich Linien zu erweitern, wie nötig. Aber ich habe das Problem mit dem folgenden Code bestätigt, wobei die Lösung (die beiden Stilzeilen) weggelassen wurde. Als ich die Lösung here und die dazugehörige Style-Seite nicht finden konnte, googelte ich und fand this. Scrollen Sie nach unten zu Emilianos Antwort und einigen der folgenden Punkte (es gibt auch eine Einrückungsoption).

import tkinter as tk 
from tkinter import ttk 

root = tk.Tk() 
root.geometry('500x200') 
style = ttk.Style(root) 
style.configure('Treeview', rowheight=40) #SOLUTION 
tree = ttk.Treeview(root) 
tree.insert('', 0, text='Line 1 of many XXX', tags='T') 
tree.insert('', 1, text='Line 2 of many XXX', tags='T') 
tree.insert('', 2, text='Line 3 of many XXX', tags='T') 
tree.column('#0', stretch=True) 
tree.tag_configure('T', font='Arial 20') 
tree.pack(fill='x') 

Das obige, mit der Antwort weggelassen, ist ein Beispiel für minimalen Code, der das Problem aufweist. Dies ist die Art von Dingen zu posten!

EDIT 1:

Um den Kalender-Widget richtig importierbar und verwendbar in einer anderen Anwendung zu machen, soll es einen benutzerdefinierten Stil verwenden, so dass ihr Stil in der App hat keine Auswirkungen auf andere treeviews.

style.configure('Calendar.Treeview', rowheight=40) 
tree = ttk.Treeview(root, style='Calendar.Treeview') 

EDIT 2:

Ich lerne gerade über ttk Arten selbst. Um Ihre Hilfsfrage zu beantworten, ging ich zu dieser style doc und versuchte das folgende in Idle's Shell nach dem Ausführen der oben genannten, mit den zwei Änderungen in Edit 1.

>>> style.layout('Calendar.Treeview') 
[('Treeview.field', {'sticky': 'nswe', 'children': [('Treeview.padding', 
{'sticky': 'nswe', 'children': [('Treeview.treearea', {'sticky': 'nswe'})]})], 'border': '1'})] 
>>> style.element_options('Calendar.Treeview.border') 
('-relief',) 
>>> style.lookup('Calendar.Treeview.border', 'relief') 
'' 
>>> style.configure('Calendar.Treeview.border', relief='raised') 
{} 

Ich sehe keine Grenze noch keinen Effekt der Einstellung. Vielleicht gilt Erleichterung für die Grenzen zwischen den Spalten. Ich weiß es nicht. (Beachten Sie, dass die Änderung der Rowheight sofort verfügbar ist, so dass die Konfiguration 'live' ist.)

+0

Danke Terry! Haben Stunden damit verbracht, es herauszufinden, ohne Erfolg. Ich habe eine kleine Frage hinzuzufügen: Wie kann ich die Erleichterung der Treeview ändern? Ist es möglich? – MistUnleashed

+0

Siehe Bearbeiten 2 oben. –

+0

Große Antworten, tolle Leute. –

0

Wie kann ich die Höhe der Zeilen in der Baumansicht ändern, da in vorherigen Versuchen Schriftgröße erhöht werden kann, aber die Zeilenhöhe nicht Zunahme mit Schriftgröße. - STILL HELP AWAITING

Falls Sie noch Hilfe auf dieser erwartet werden, gibt ist eine way die Zeilenhöhe zu ändern, obwohl das Google Groups Thread sagt, dass es nicht offiziell von Tk unterstützt:

3

Ich habe festgestellt, dass das Tkinter Font-Objekt eine metrics() -Methode hat, die ihre Höhe als "linespace" angibt. Das erlaubt die Zeilenhöhe dynamisch skaliert werden:

try: 
    from tkinter.font import Font 
    from tkinter.ttk import Style, Treeview 
    from tkinter import *   
except: 
    from tkFont import Font 
    font ttk import Style, Treeview 
    from Tkinter import * 

font=Font(family='Arial', size=20) 
font.metrics() 
#output: {'ascent': 31, 'descent': 7, 'linespace': 38, 'fixed': 0} 

Damit Sie die Schrifthöhe mit bekommen:

font.metrics()['linespace'] 
#output: 38 

Dann ist es verwenden, um die rowHeight in Ihrem Treeview-Widget zu setzen:

fontheight=font.metrics()['linespace'] 

style=Style() 
style.configure('Calendar.Treeview', font=font, rowheight=fontheight) 

tree=Treeview(style='Calendar.Treeview') 

Durch das Ändern der Schriftobjektparameter wird das Treeview-Widget bequem aktualisiert, aber die Zeilenhöhe wird nicht aktualisiert und muss erneut erstellt werden. So zum Beispiel, mit einer Tastenkombination folgendermaßen aussehen kann die Schriftgröße Skalierung:

das Verhalten
def scaleup(): 
    font['size']+=1 
    style.configure('Calendar.Treeview', rowheight=font.metrics()['linespace']) 

def scaledown(): 
    font['size']-=1 
    style.configure('Calendar.Treeview', rowheight=font.metrics()['linespace']) 

tree.bind('<Control-equal>', scaleup) 
tree.bind('<Control-minus>', scaledown) 

Ich wollte eigentlich das gleiche mit Strg-Mausrad tun, aber nicht herausfinden, noch (Würde mich freuen zu höre, wie das funktioniert).

Hoffe, das ist praktisch.

+0

Wunderbar !! Genau das, was ich brauchte. – Riyaz