Python Tkinter cambiando StringVar valore da usare come un indicatore di sfondo su una UI

sto costruendo una UI in cui gli utenti devono selezionare alcune date. ho aggiunto una riga chiamata Date Indicator che mostra una casella con un colore. il colore di partenza (fino a quando l’utente seleziona entrambe le date) è grey. questo colore deve cambiare a seconda delle date che l’utente seleziona.

  • se sceglie due date in cui i giorni tra di loro sono più di due settimane, la scatola deve diventare verde.
  • se sceglie due date in cui i giorni tra di loro sono meno di due settimane, la scatola deve diventare giallo.
    se sceglie due date in cui i giorni tra di loro sono meno di una settimana, la scatola deve diventare rosso.

questo è un risultato auspicabile per la soluzione desiderata:

il codice sembra essere lungo, ma devi solo controllare fino alla classe tkCalendar. da lì in basso è solo il codice del calendario non è necessario modificare. (e sì, ci sono alcuni imports non è necessario utilizzare per questo codice, li mantengo perché devo usarli per altre cose, ma è possibile rimuoverli)

# -*- coding: utf-8 -*-
import os
from Tkinter import *
import Image
import ImageTk
import tkFileDialog
import xlrd
import csv
from tkMessageBox import *
from win32com.client import Dispatch
import datetime
import time
import calendar

year = time.localtime()[0]
month = time.localtime()[1]
day =time.localtime()[2]
strdate = (str(year) +  "/" + str(month) + "/" + str(day))

fnta = ("Helvetica", 10)
fnt = ("Helvetica", 10)
fntc = ("Helvetica", 10, 'bold')


strtitle = "Calendario"
strdays= "Do  Lu  Ma  Mi  Ju  Vi  Sa"
dictmonths = {'1':'Ene','2':'Feb','3':'Mar','4':'Abr','5':'May',
    '6':'Jun','7':'Jul','8':'Ago','9':'Sep','10':'Oct','11':'Nov',
    '12':'Dic'}


class Planificador(Frame):
    def __init__(self,master):
        Frame.__init__(self, master)
        self.master = master
        self.initUI()

    def initUI(self):
        self.master.title("Planner")
        self.frameOne = Frame(self.master)
        self.frameOne.grid(row=0,column=0)
        self.frameTwo = Frame(self.master)
        self.frameTwo.grid(row=0, column=1)
        self.frameThree = Frame(self.master)
        self.frameThree.grid(row=0, column=2)

        self.frameFour = Frame(self.master)
        self.frameFour.grid(row=1,column=0, sticky=N)
        self.frameFive = Frame(self.master)
        self.frameFive.grid(row=1, column=1)
        self.frameSix = Frame(self.master)
        self.frameSix.grid(row=1, column=2, sticky=N)

        self.frameSeven = Frame(self.master)
        self.frameSeven.grid(row=2,column=0)
        self.frameEight = Frame(self.master)
        self.frameEight.grid(row=2, column=1, sticky=S)
        self.frameNine = Frame(self.master)
        self.frameNine.grid(row=2, column=2)

        self.start_date_menu()

    def start_date_menu(self):
        self.initial_num_elements = 4
        self.TEXT_MENU_ROW = 0  # initial date menu grid row
        self.COL_WIDTH = 10  # width of each subcolumn of dates

        for frame in (self.frameFour, self.frameSix):
            self.dayintext = Label(frame, text="Day in",
                                        width=self.COL_WIDTH, justify="center")
            self.dayintext.grid(row=self.TEXT_MENU_ROW, column=0)
            self.dayouttext = Label(frame, text="Day out", width=self.COL_WIDTH,
                                   justify="center")
            self.dayouttext.grid(row=self.TEXT_MENU_ROW, column=1)
            self.status = Label(frame, text="Date indicator", width=self.COL_WIDTH,
                                   justify="center")
            self.status.grid(row=self.TEXT_MENU_ROW, column=2)

        self.dates = [self.create_all_entrys(aux_index)
                        for aux_index in xrange(self.initial_num_elements)]

        self.anadirpiezas = Button(self.frameEight, text="add more",
                                   command=self.addone, width=self.COL_WIDTH)
        self.anadirpiezas.grid(row=0, column=3)


    def addone(self):
        self.dates.append(self.create_all_entrys(len(self.dates)))
        self.printdates()

    def printdates(self):
        print "IN:"
        for i in xrange(self.initial_num_elements):
            print self.dates[i][0].get() # col 0
        print "OUT:"
        for i in xrange(self.initial_num_elements):
            print self.dates[i][2].get() # col 2

    def create_all_entrys(self, aux_index):
        menu_col = aux_index % 2  # left/right column of the date frame
        menu_row = self.TEXT_MENU_ROW + aux_index/2 + 1
        frame = self.frameSix if aux_index % 2 else self.frameFour

        in_var = StringVar(value="--------")
        in_btn = Button(frame, textvariable=in_var, width=self.COL_WIDTH,
                        command=lambda v=in_var: self.fnCalendar(v))
        in_btn.grid(row=menu_row, column=0)

        out_var = StringVar(value="--------")
        out_btn = Button(frame, textvariable=out_var, width=self.COL_WIDTH,
                         command=lambda v=out_var: self.fnCalendar(v))
        out_btn.grid(row=menu_row, column=1)

        self.colorvar = StringVar()
        self.colorvar.set('grey')
        self.status_color = Label(frame, width=2, bg=self.colorvar.get())
        self.status_color.grid(row=menu_row,column=2)

        return in_var, in_btn, out_var, out_btn

    def fnCalendar(self, datebar):
        tkCalendar(self.master, year, month, day, datebar)

class tkCalendar :
  def __init__ (self, master, arg_year, arg_month, arg_day,
       arg_parent_updatable_var):
    print arg_parent_updatable_var.get()
    self.update_var = arg_parent_updatable_var
    top = self.top = Toplevel(master)
    top.title("Choose a date")
    try : self.intmonth = int(arg_month)
    except: self.intmonth = int(1)
    self.canvas =Canvas (top, width =200, height =220,
      relief =RIDGE, background ="#ece9d8", borderwidth =0)
    self.canvas.create_rectangle(0,0,303,30, fill="#ece9d8",width=0 )
    self.canvas.create_text(100,17, text="Choose!",  font=fntc, fill="#BA1111")
    stryear = str(arg_year)

    self.year_var=StringVar()
    self.year_var.set(stryear)
    self.lblYear = Label(top, textvariable = self.year_var,
        font = fnta, background="#ece9d8")
    self.lblYear.place(x=85, y = 30)

    self.month_var=StringVar()
    strnummonth = str(self.intmonth)
    strmonth = dictmonths[strnummonth]
    self.month_var.set(strmonth)

    self.lblYear = Label(top, textvariable = self.month_var,
        font = fnta, background="#ece9d8")
    self.lblYear.place(x=85, y = 50)
    #Variable muy usada
    tagBaseButton = "Arrow"
    self.tagBaseNumber = "DayButton"
    #draw year arrows
    x,y = 40, 43
    tagThisButton = "leftyear"
    tagFinalThisButton = tuple((tagBaseButton,tagThisButton))
    self.fnCreateLeftArrow(self.canvas, x,y, tagFinalThisButton)
    x,y = 150, 43
    tagThisButton = "rightyear"
    tagFinalThisButton = tuple((tagBaseButton,tagThisButton))
    self.fnCreateRightArrow(self.canvas, x,y, tagFinalThisButton)
    #draw month arrows
    x,y = 40, 63
    tagThisButton = "leftmonth"
    tagFinalThisButton = tuple((tagBaseButton,tagThisButton))
    self.fnCreateLeftArrow(self.canvas, x,y, tagFinalThisButton)
    x,y = 150, 63
    tagThisButton = "rightmonth"
    tagFinalThisButton = tuple((tagBaseButton,tagThisButton))
    self.fnCreateRightArrow(self.canvas, x,y, tagFinalThisButton)
    #Print days
    self.canvas.create_text(100,90, text=strdays, font=fnta)
    self.canvas.pack (expand =1, fill =BOTH)
    self.canvas.tag_bind ("Arrow", "<ButtonRelease-1>", self.fnClick)
    self.canvas.tag_bind ("Arrow", "<Enter>", self.fnOnMouseOver)
    self.canvas.tag_bind ("Arrow", "<Leave>", self.fnOnMouseOut)
    self.fnFillCalendar()

  def fnCreateRightArrow(self, canv, x, y, strtagname):
    canv.create_polygon(x,y, [[x+0,y-5], [x+10, y-5] , [x+10,y-10] ,
        [x+20,y+0], [x+10,y+10] , [x+10,y+5] , [x+0,y+5]],
        tags = strtagname , fill="black", width=0)

  def fnCreateLeftArrow(self, canv, x, y, strtagname):
    canv.create_polygon(x,y, [[x+10,y-10], [x+10, y-5] , [x+20,y-5] ,
        [x+20,y+5], [x+10,y+5] , [x+10,y+10] ],
        tags = strtagname , fill="black", width=0)


  def fnClick(self,event):
    owntags =self.canvas.gettags(CURRENT)
    if "rightyear" in owntags:
    intyear = int(self.year_var.get())
    intyear +=1
    stryear = str(intyear)
    self.year_var.set(stryear)
    if "leftyear" in owntags:
    intyear = int(self.year_var.get())
    intyear -=1
    stryear = str(intyear)
    self.year_var.set(stryear)
    if "rightmonth" in owntags:
    if self.intmonth < 12 :
        self.intmonth += 1
        strnummonth = str(self.intmonth)
        strmonth = dictmonths[strnummonth]
        self.month_var.set(strmonth)
    else :
        self.intmonth = 1
        strnummonth = str(self.intmonth)
        strmonth = dictmonths[strnummonth]
        self.month_var.set(strmonth)
        intyear = int(self.year_var.get())
        intyear +=1
        stryear = str(intyear)
        self.year_var.set(stryear)
    if "leftmonth" in owntags:
    if self.intmonth > 1 :
        self.intmonth -= 1
        strnummonth = str(self.intmonth)
        strmonth = dictmonths[strnummonth]
        self.month_var.set(strmonth)
    else :
        self.intmonth = 12
        strnummonth = str(self.intmonth)
        strmonth = dictmonths[strnummonth]
        self.month_var.set(strmonth)
        intyear = int(self.year_var.get())
        intyear -=1
        stryear = str(intyear)
        self.year_var.set(stryear)
    self.fnFillCalendar()
  def fnFillCalendar(self):
    init_x_pos = 20
    arr_y_pos = [110,130,150,170,190,210]
    intposarr = 0
    self.canvas.delete("DayButton")
    self.canvas.update()
    intyear = int(self.year_var.get())
    monthcal = calendar.monthcalendar(intyear, self.intmonth)
    for row in monthcal:
    xpos = init_x_pos
    ypos = arr_y_pos[intposarr]
    for item in row:
        stritem = str(item)
        if stritem == "0":
        xpos += 27
        else :
        tagNumber = tuple((self.tagBaseNumber,stritem))
        self.canvas.create_text(xpos, ypos , text=stritem,
            font=fnta,tags=tagNumber)
            xpos += 27
    intposarr += 1
    self.canvas.tag_bind ("DayButton", "<ButtonRelease-1>", self.fnClickNumber)
    self.canvas.tag_bind ("DayButton", "<Enter>", self.fnOnMouseOver)
    self.canvas.tag_bind ("DayButton", "<Leave>", self.fnOnMouseOut)

  def fnClickNumber(self,event):
    owntags =self.canvas.gettags(CURRENT)
    for x in owntags:
    if (x == "current") or (x == "DayButton"): pass
    else :
        strdate = (str(self.year_var.get()) + "/" +
            str(self.intmonth) + "/" +
            str(x))
        self.update_var.set(strdate)
        self.top.withdraw()

  def fnOnMouseOver(self,event):
    self.canvas.move(CURRENT, 1, 1)
    self.canvas.update()

  def fnOnMouseOut(self,event):
    self.canvas.move(CURRENT, -1, -1)
    self.canvas.update()


if __name__ == "__main__":
    root = Tk()
    aplicacion = Planificador(root)
    root.mainloop()

sono totalmente perso cercando di fare questo. so che devo cambiare self.colorvar, ma non so come farlo. ho tryed a self.colorvar.set('red') per esempio ma non posso farlo funzionare il senso ho spiegato sopra. le date in e out si trovano sulla funzione printdates. si aiuta è molto apprezzato.

EN From: Python Tkinter changing StringVar value to use it as a background indicator on a UI

More similar articles:

9 Comments

  1. non credo che si può collegare l’opzione bg a un Var String. è possibile farlo solo con l’opzione textvariable. il modo in cui si dovrebbe fare è tramite il metodo Label.config ().

    così si potrebbe scrivere:

    self.status_color.config(bg='red')

    oppure, se vuoi continuare ad usare il colorvar:

    self.colorvar.set('red')
    self.status_color.config(bg=self.colorvar.get())

    che dovrebbe funzionare, e credo che si può capire la cosa di 2 settimane.

    modifica: modifica:

    è anche possibile ‘collegare’ il self.colorvar StringVar ad una funzione che cambia self.status _ color (con il metodo trace); in modo che ogni volta che colorvar è cambiato, la funzione sarà chiamata e cambierà il colore dello stato. questo è il mio suggerimento:

    def myFunc(*args):
        self.status_color.config(bg=self.colorvar.get())
    
    self.colorvar.trace('w',self.myFunc)

    ora ogni volta che chiami self.colorvar.set (), chiamerai anche self.myFunctions.

    modifica: modifica:

    per quanto riguarda la cosa settimana, non ho intenzione di rispondere completamente come sembra facile. basta ottenere un intero per mese e giorno di IN e OUT e fare qualcosa di simile:

    monthdiff = monthout-monthin
    if monthdiff!=0:
        dayout += monthdiff*30 #or 31, depending on the month. Just add an if/else
    
    weeks = ((dayout-dayin)//7)+1 #For python2.7 use only one slash

    e poi il tuo if / else con la funzione di cambio colore. fate attenzione anche a gennaio, aggiungetene uno in più. e credo che si può analizzare le stringhe IN e OUT per ottenere il mese e il giorno da soli.

    1. il self.status_color.config(bg='red') funziona. la cosa è che con questo .config non è possibile modificare il precedente grey stato contrassegnato, che è lo scopo della domanda.

    2. @Borja L’uomo, allora non ho quello che vuoi… Vuoi una funzione che prende il IN e OUT date e poi cambia il colore? perché pensavo di averne già uno, o almeno non era così chiaro nella tua domanda…

    3. @borja: il tuo commento non è chiaro. è possibile modificare il colore di quasi tutto – non c’è nulla di chiamare il metodo config che impedisce di impostare il colore di altri widget pure.

    4. @JGallo Sì, esattamente questo. penso che sia chiaro se si legge l’intera domanda, o se si esegue solo il codice. l’immagine che è collegato al post è solo un’immagine Photoswanted della soluzione desiderata. grazie in anticipo!

    5. @BryanOakley La cosa è che hai già creato i pulsanti grey al momento di creare la prima volta i entrys. con il ‘.config. metodo cambia il colore proprio di quelli nuovi.

    6. @Borja: Non capisco ancora il tuo commento. è possibile modificare il colore di quelli grigi. non capisco perché pensi di non poter. se lo hai creato, puoi cambiarlo.

Leave a Reply

Your email address will not be published. Required fields are marked *