Forum >> Programmazione Python >> GUI >> Aggiornare il contenuto di un wxPanel

Pagina: 1

Buona sera a Tutti.

E' parecchio tempo che non frequento più il forum (causa mancanza di tempo per la programmazione) e di questo chiedo venia,

da poco ho ricominciato a smanettare (dire programmare e una bestemmia) con Python e con le Wx,

stò cercando di creare un pannello (wx.Panel) in qui all'interno vengono inseriti n pulsanti "anonimi" tramite un ciclo for,


( per anonimi intendo che non vengono settati a delle variabili) n (quantità di pulsanti) viene stabilita da quanti giorni ci sono in un mese (es. Ottobre ha 31 giorni i pulsanti saranno 31, Febbraio ha 28 giorni i pulsanti saranno 28 ecc.), il mese viene visualizzato uno static text.

Ai lati dello static Text ci sono due pulsati non anonimi che servono ad avanzare o indietreggiare sui mesi.

Il tutto viene organizzato con dei Sizer.

Ora veniamo al problema:

nel momento in qui cerco di cambiare il mese,( dovrebbero aggiornarsi anche i pulsanti, aumentare o diminuire di quantità ) mi ritrovo con una scelta da fare,

1) eliminare i pulsanti già presenti nel pannello e aggiungere quelli nuovi (il Sizer in fin dei conti funziona come una lista a dirla grossa :quiet:)


ma in questo caso prima che il panel venga aggiornato devo perlomeno intervenire manualmente ingrandendo la finestra.


Sicuramente la cosa è dovuta a erronea programmazione

2) modificare in qualche modo quelli già esistenti. Credo che il qualche modo sia utilizzare il "metodo" MVC-O (Model View Control Observer) e qui avrei necessità di

avere qualche suggerimento anche pratico per implementare l' MVC-O in quanto "so de coccio e non capisco na mazza" :D :D :sarcastic: :sarcastic: :sick: :sick:.




Nell'affrontare una delle due scelte, non so se sia fondamentale, il pannello creato verrà poi inserito in un altro panello ecc. ecc. Ma questa è un altra storia.




Quale scelta effettuare?

Se la prima come faccio ad aggiornare " in tempo reale " il panel non appena viene cliccato sul pulsante?

Se la seconda chi gentilmente mi aiuta dandomi delle dritte ed esempi pratici sul come creare l'MVC-O ?

Da tenere presente che il mio inglese è pressochè sotto zero oltre che l'italiano :foot-in-mouth: :O :( :embarrassed: :confused:

questo quello che ho fatto fin Ora:

import wx
import wx.lib.scrolledpanel as scrolled
from datetime import date
import calendar
import locale
import monthdelta

class MioPannello(scrolled.ScrolledPanel):
	def __init__(self, *a, **k):
		scrolled.ScrolledPanel.__init__(self, *a, **k)
		
		locale.setlocale(locale.LC_ALL, '')   # use user's preferred locale
		self.dataAttuale = date.today()
		dataInFormato = self.dataAttuale.strftime("%A %d %B %Y")
		meseInFormato = self.dataAttuale.strftime("%B %Y")
		idStaticText = wx.NewId()
		idButtonDx = wx.NewId()
		idButtonSx = wx.NewId()
		self.pulsanteDestro = wx.Button(self, id= idButtonDx, label= '-->' )
		self.pulsanteSinistro = wx.Button(self, id= idButtonSx, label='<--')
		self.ST dataAttuale = wx.StaticText(self, idStaticText,
		                                    style = wx.ALIGN_CENTER,
		                                    label= 'Siamo nel mese di:\n' + meseInFormato)
		
		boxBase = wx.BoxSizer(wx.VERTICAL)
		boxPulsantiEtesto = wx.BoxSizer(wx.HORIZONTAL)
		self.boxPulsantiMultipi = wx.BoxSizer(wx.VERTICAL)
		
		boxPulsantiEtesto.Add(self.pulsanteSinistro)
		boxPulsantiEtesto.Add(self.ST dataAttuale)
		boxPulsantiEtesto.Add(self.pulsanteDestro)
		boxBase.Add(boxPulsantiEtesto)
		boxBase.Add(wx.StaticLine(self),0,wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
		
		self.aggiornaPulsanti()
		
		boxBase.Add(self.boxPulsantiMultipi)
		
		self.SetSizer(boxBase)
		self.SetupScrolling()
		
		self.pulsanteDestro.Bind(wx.EVT_BUTTON, self.avanti)
	#----------------------------------------------------------------------
	def aggiornaPulsanti(self):
		""""""
		
		calendario = calendar.Calendar()
		anno = self.dataAttuale.year
		mese = self.dataAttuale.month
		# nGiornimese = calendar.monthrange(dataAttuale.year, dataAttuale.month)
		nGiornimese = calendario.itermonthdates(anno, mese)
		print(nGiornimese)
		print(type(nGiornimese))
		# nGiornimese = range(1, self.giorni)

		for giorni in nGiornimese:
			formatoGiorni = giorni.strftime("%A %d")
			# print(formatoGiorni)
			if giorni.month != self.dataAttuale.month:
				next
			else:
				self.boxPulsantiMultipi.Add(wx.Button(self, name= 'pulsante', label=str(giorni)))
	#----------------------------------------------------------------------
	def avanti(self, event):
		""""""
		meseAttuale = self.dataAttuale
		meseAggiunto = meseAttuale + monthdelta.monthdelta(+1)
		print ('mese aggiunto =', meseAggiunto)
		meseInFormato = meseAggiunto.strftime("%B %Y")
		self.ST dataAttuale.SetLabel('Siamo nel mese di:\n' + meseInFormato)
		self.dataAttuale = meseAggiunto
		# self.Update()
		# self.boxPulsantiMultipi.Clear()
		# self.Refresh()
		# self.boxPulsantiMultipi.Replace()
		
		# ---
		# in questo caso sto aggiungendo dei pulsanti a quelli gia esistenti ???????
		# self.aggiornaPulsanti() # ?????????
		# ----
		# in questo caso modifico l'aspetto dei pulsanti gia presenti ????????ù
		a = self.boxPulsantiMultipi.GetItemCount()
		print(a)
		#---
		"""
		for figlio in  self.GetChildren():
			if figlio.Name == 'pulsante':
				figlio.SetBackgroundColour('Pink')
		"""
		#---
		# self.Refresh()


class Finestra(wx.Frame):
	def __init__(self, *a, **k):
		wx.Frame.__init__(self, *a, **k)
		#panel = wx.Panel(self)
		MioPannello(self)


app = wx.App(False)
Finestra(None).Show()
app.MainLoop()
Ringrazio fin da subito chi avrà il coraggio e la pazienza nell'aiutarmi.










Mah guarda, in generale il problema che poni è interessante, solo che nel tuo caso particolare diventa tutto molto banale.


In generale il problema è: come generare dinamicamente una parte della gui, e quali strategie usare per aggiornarla altrettanto dinamicamente. E qui in effetti si pone tutto il problema di MVC, bla bla bla. E, a seconda dei casi, può essere più conveniente una cosa, l'altra, l'altra ancora. Bla bla bla.


Ma nel tuo caso specifico, che senso ha quello che stai cercando di fare? Per cominciare, wxPython ha *già* dei widget che visualizzano un calendario, e che fanno già tutto il lavoro per te. Se ben ricordo, ne aveva addirittura due. Usa quelli e vivi felice.


In secondo luogo, se proprio vuoi farti un calendario a mano (magari per esercizio, non so), allora nel tuo caso ha poco senso complicarsi la vita. Semplicemente disegna 31 pulsanti e poi, a ogni cambio di mese, nascondi quelli che non ti servono. Così non hai bisogno di rifare il disegno, e tutto resta semplice. Come bonus di scaltrezza, puoi chiedere direttamente a python quanti giorni ha il mese che ti serve: così risolvi anche il problema degli anni bisestili, ed eviti di mettere sempre 28 giorni a Febbraio.


Ecco una bozza di idea buttata giù in cinque minuti:


import datetime
import wx

class CalendarPanel(wx.Panel):
    def __init__(self, parent, initial_date=None):
        wx.Panel.__init__(self, parent)
        if initial_date is None:
            initial_date = datetime.date.today()
        self.current_year = initial_date.year
        self.current_month = initial_date.month
        move_back = wx.Button(self, -1, '<')
        move_back.Bind(wx.EVT_BUTTON, self.on_move_back)
        move_forw = wx.Button(self, -1, '>')
        move_forw.Bind(wx.EVT_BUTTON, self.on_move_forw)
        self.display_date = wx.TextCtrl(self, style=wx.TE_READONLY)
        self.day_buttons = []
        for day in range(31):
            b = wx.Button(self, -1, str(day+1), size=(40, 40))
            b.Bind(wx.EVT_BUTTON, self.on_day_clic)
            self.day_buttons.append(b)
        self._refresh_display()
        self._refresh_day_buttons()
        siz1 = wx.BoxSizer(wx.HORIZONTAL)
        for widget in (move_back, self.display_date, move_forw):
            siz1.Add(widget, 0, wx.ALL, 5)
        siz2 = wx.GridSizer(7, 0, 0)
        for button in self.day_buttons:
            siz2.Add(button)
        s = wx.BoxSizer(wx.VERTICAL)
        s.Add(siz1)
        s.Add(siz2, 0, wx.ALL, 5)
        self.SetSizer(s)

    def _refresh_display(self):
        'Setta mese e anno attuali nella casella di testo.'
        display = '%i / %i' % (self.current_month, self.current_year)
        self.display_date.SetValue(display)

    def _refresh_day_buttons(self):
        "Reimposta i pulsanti per il mese corrente, nasconde i giorni in piu'."
        for button in self.day_buttons:
            button_day = int(button.GetLabel())
            try:
                datetime.date(self.current_year, self.current_month, button_day)
                button.Show()
            except ValueError:
                # metodo brutale: se datetime.date non puo' essere formata, vuol dire
                # che il mese attuale non ha quel giorno (es. 30 febbraio): 
                # quindi semplicemente nascondo il pulsante.
                # Nota che questo ha pure il vantaggio di tener conto dei bisestili!
                button.Hide()

    def on_move_back(self, evt):
        self.current_month -= 1
        if self.current_month < 1:
            self.current_year -= 1
            self.current_month = 12
        self._refresh_display()
        self._refresh_day_buttons()

    def on_move_forw(self, evt):
        self.current_month += 1
        if self.current_month > 12:
            self.current_year += 1
            self.current_month = 1
        self._refresh_display()
        self._refresh_day_buttons()

    def on_day_clic(self, evt):
        button = evt.GetEventObject()
        button_day = int(button.GetLabel())
        date = datetime.date(self.current_year, self.current_month, button_day)
        print('hai cliccato', date)


class MainFrame(wx.Frame):
    def __init__(self, *a, **k):
        wx.Frame.__init__(self, *a, **k)
        p = CalendarPanel(self)

app = wx.App()
MainFrame(None).Show()
app.MainLoop()
Naturalmente un vero calendario dovrebbe tenere i giorni incolonnati, e per questo c'è bisogno di un po' di lavoro in più. Dovresti farti una griglia di cinque settimane e poi, a ogni refresh del mese, non solo nascondi i giorni superflui, ma cambi proprio le label dei pulsanti. O meglio ancora, cambi le label dei pulsanti e non nascondi i pulsanti dei giorni superflui, ma li mostri come i giorni adiacenti del mese precedente e successivo. Come fanno i veri calendari, insomma.


Ma allora, come dicevo... perché non usare un vero calendario, visto che wxPython ce l'ha?











Pagina: 1



Esegui il login per scrivere una risposta.