Python Forum
How to create a menu button?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to create a menu button?
#11
I am already doing it.
This is an attemp, i am not done yet, just to give you an idea where i am going. Dont scold me yet. I am doing copy paste with old code.

from tkinter import *
import calendar

def affCal(self, mois, annee):
    
    if choix.get() == 'Janvier':         //i am still unsure how i will pass the choice of months in the calendar method.

     return resultat.insert(tk.INSERT, calendar.month(annee, mois))   //print(calendar.month(2022, 3))
        

    else:
        


def changement(event):
        if choix.get() == 'Janvier':
        txt1.configure(text='Janvier')
        
def afficher():
    monCal = Calendrier()
    monCal.annee = str(entD1.get())


fen = Tk()
fen.title('Calendrier')

txt1 = Label(fen1, text='Température en Fahrenheit')
txt1.grid(row=0, column=0, sticky=E)

txtD1 = tk.Label(fen, text = 'Année:')
txtD1.grid(row = 0, column = 0, sticky = tk.E)

entD1 = tk.Entry(fen)
entD1.grid(row = 0, column = 1)

resultat = tk.Text(fen)
resultat.config(width=40, height=50)
resultat.grid(row=1, column=0, columnspan=2)

bouton = tk.Button(fen, text = "Afficher", command = afficher)
bouton.grid(row = 1, column = 0, columnspan = 1)

bouton2 = tk.Button(fen, text="Quitter", command=fen.destroy)
bouton2.grid(row=1, column=1)

choix = StringVar(fen1)
choix.set('Celcius à Fahrenheit')
liste = OptionMenu(fen1, choix, 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Octobre', 'Novembre', 'Décembre', command=changement)

liste.grid(row=2, column=1)

fen1.mainloop()
Reply
#12
The calendar module has a localized month name generator.
import calendar
for month in calendar.month_name):
    print(month)
You should use that instead of hardcoding. If you run the code you will notice the first month name is blank so January is 1.

How would you convert "October" to 10? I don't mean in Python, but if you were filling out a form that needed the date in the form YYYY/MM/DD how do you convert the current month to a number? I know that I don't remember the month as a number, I remember that this month is March. Take a moment and write the procedure you used down on paper. Do you have a memorized mapping? September=9, June=5? Or do you count up? I have to count up because my mind rebels at DECember being the 12th month instead of the 10th.

Either method can be implemented in Python. A lookup uses a dictionary or the list.index() method. A count-up involves a for loop or a while loop. I think you skip the planning stage of programming and jump right into coding. This is always a bad practice, but particularly bad when you are learning coding.

I also think it is a bad idea to copy/paste. Copy/Paste is a productivity tool. You should be starting each program from scratch. Not only because the code you have to sample is not all that great (this is true for all beginning programmers), but because it hinders learning the process of writing code. First write a docstring that describes what the program does. Next import the modules you plan to use. Stub in the functions and write a docstring for each of those. Write the main. This is a slower way to program, but repeating these steps over and over will make them familiar.

It also provides you with time for reflection. I used to write tkinter code like this:
root = tk.Tk()
label = tk.Label(root, text="Some text")
label.pack()
root.mainloop()
After typing that a few times I began to rebel. Why do I use tk.Tk() to make the top window, but use subclassing to make subsequent windows? Why do I make a variable for that label when I the label is only there for decoration? One day I decided to subclass the root window and I have never gone back.
Reply
#13
I am stuck with what the book assigment ask. They want an option menu so calendar.month_name wont help.
When assigments are small you dont need much planification. In this case it needs more thinking.

Thank you for your input ill figure it out soon or later, i always do.
Reply
#14
Why doesn't calendar.month_name help? It is an iterator of all the month names. Don't you need month names? Are you going to hard-code the month manes? If I can get a list of month names for free and they are guaranteed to not contain any typing errors, I am going to take them. As a very big side benefit my program will automatically use localized month names.

If no more planning is required, what is your plan? How will the user enter the year? How will the user enter the month? When do you update the calendar display? If the common tkinter controls for selecting an item from a list returns a string and the calendar.month() method takes and integer month, how are you going to do the conversion? When the program starts what month do you display? If you display the current date on startup how are you going to get the month and year?
Reply
#15
Back to square one.
Its compiling without any errors but cant see the calendar in the window.
I am failling to understand whats doing what.

import tkinter as tk
import calendar


class Calendrier:
    '''Calendrier'''

    def affCal(self, annee, mois):

        resultat.insert(tk.INSERT, calendar.month(annee, mois))


def afficher():
    monCal = Calendrier()
    monCal.annee = str(entD1.get())
    monCal.mois = str(entD2.get())


fen = tk.Tk()
fen.title('Calendrier')

txtD1 = tk.Label(fen, text='Année:')
txtD1.grid(row=0, column=0, sticky=tk.E)

entD1 = tk.Entry(fen)
entD1.grid(row=0, column=1)

txtD2 = tk.Label(fen, text='Mois:')
txtD2.grid(row=0, column=1, sticky=tk.E)

entD2 = tk.Entry(fen)
entD2.grid(row=0, column=2)

resultat = tk.Text(fen)
resultat.config(width=40, height=50)
resultat.grid(row=1, column=0, columnspan=2)

bouton = tk.Button(fen, text="Afficher", command=afficher)
bouton.grid(row=1, column=0, columnspan=1)

bouton2 = tk.Button(fen, text="Quitter", command=fen.destroy)
bouton2.grid(row=1, column=1)


fen.mainloop()
Reply
#16
You really don't get classes. You are having the same problems here as you had it the temperature conversion.

In this program Calendar should be a class for the window.
import tkinter as tk
import calendar
from datetime import datetime

class Calendrier(tk.Tk):  # This says "Calendrier is a kind of Tk.  Tk is the class for the main window in tkinter
    '''Calendrier'''
    def __init__(self, *args, **kwargs):    # This allows passing additional arguments on to Tk.
        super().__init__(*args, **kwargs)  # args will have the positional arguments.  kwargs will have the named arguments
        self.title('Calendrier')  # Because Calendrier is a subclass of Tk, it can do all the things Tk can do, like setting the window title

        # Calendar label needs a monospace font for day column to line up.  Must
        # also be left justified.
        self.calendrier = tk.StringVar()  # It is easier to use tkinter variables than it is to work directly with widgets
        tk.Label(self, textvariable=self.calendrier, font=("Courier", 16), width=22, height=9, justify=tk.LEFT) \
            .grid(row=0, column=0, columnspan=5)
 
        # Enter the year
        self.annee = tk.IntVar(value=datetime.now().year)  # A tkinter variable to get or set the year entry
        tk.Label(self, text='Année:').grid(row=1, column=0, sticky=tk.E)
        tk.Entry(self, textvariable=self.annee, width=5).grid(row=1, column=1)
 
        # Enter the month.  I think a OptionMenu or combo box is a better choice
        self.mois = tk.IntVar(value=datetime.now().month)  # A tkinter variable to get or set the month entry
        tk.Label(self, text='Mois:').grid(row=1, column=2, sticky=tk.E)
        tk.Entry(self, textvariable=self.mois, width=3).grid(row=1, column=3)

        # This is not needed.  You can bind events to the month or year
        # changing and have that update the calendar
        tk.Button(self, text="Afficher", command=self.affcal) \
            .grid(row=1, column=4)

        # Show the first calendar
        self.affcal()
 
    def affcal(self):
        """Update the calendar label"""
        try:
            text = calendar.month(self.annee.get(), self.mois.get())
        except (tk.TclError, calendar.IllegalMonthError):
            text = "-NA-"
        self.calendrier.set(text)

Calendrier().mainloop()
Having the user type in a number for the month because you couldn't figure out how to convert month names to month numbers it lazy. You could have figured it out if you stopped thinking about tkinter and classes for a few minutes and thought about how you get the index of an item in a list.
months = (None, 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Octobre', 'Novembre', 'Décembre')
#TBD: get index of 'Mars' in months
Unless instructions for the assignment specify a button, there is no place for a button in this program. You have a control for selecting the year and another for selecting the month. Since they are controls there will be ways you can bind them to a function call. The user should not have to press a button to see an updated calendar.
Reply
#17
You are right i dont get it at all. I have 3 weeks before the last exam to learn that concept. I am wasting to much time on this, it should take 5 minutes to fix this.
But its a pretty calendar you have shown me, ill give you that.

Edit: They put an image in the book showing a button that roll down where you choose the month you need. Its kind of stupid, it makes a long button of 12 choices.

I am not thinking much of Tkinter. Tkinter is not the problem i pretty get most of the lines of codes. Its the concept of self init and how to indent the functions that bugs me.
When do i use self and why. In some examples its there sometimes its not.
There is 10 exercices in chap 10. I have been able to make the other 7, there are 3 i lag. I think i got the other 7 by luck.

How can i make it work, that part:

class Calendrier:
    '''Calendrier'''

    def affCal(self, annee, mois):

        resultat.insert(tk.INSERT, calendar.month(annee, mois))


def afficher():
    monCal = Calendrier()
    monCal.annee = str(entD1.get())
    monCal.mois = str(entD2.get())
Reply
#18
See additional comments in my prior post.

If you don't understand classes you should do a couple of online tutorials. There are many. If you don't understand tkinter there are online tutorials for that too. You should not be working on classes and tkinter together because that is too much all at once.

Can you see that my program and your program are the same? The only difference is that I put the pieces where they belong.

In your program you should not have any classes at all. Make some buttons, bind some functions, use global variables. Quick and dirty. You tried to force in a Calendrier class, but it didn't do anything, and you couldn't figure out how your program should interact with this "thing" that didn't do anything. You would be better off forgetting about making the class and just going with functions.

My example took all the global variables and made them instance variables of a new window class. I took the functions and made them methods of the class. I took the initialization code that made all the widgets and put that in the __init__() method for the class. I did make a couple of small changes, using tkinter variables because they are easier than getting values directly from a tk.Entry widget, and fixing the afficher function since you had no idea what to do there. But other than those minor changes, the code is the same.
Reply
#19
Yes i did thank you
i kind of replied by editing my last comment.

Like that it is working but i got to figure out to make it work with tkinter.

import calendar

class Calendrier:

    def affCal(self, annee, mois):

        return calendar.month(annee, mois)


Calendrier.affCal = classmethod(Calendrier.affCal)

Calendrier.affCal(2022,3)
print(Calendrier.affCal(2022,3))
Reply
#20
Quote:but i got to figure out to make it work with tkinter.

It is working with tkinter. What are you talking about?

And this obviously doesn't do what you think it should.
classmethod(Calendrier.affCal)
What do you think the above code does?
Quote:Edit: They put an image in the book showing a button that roll down where you choose the month you need. Its kind of stupid, it makes a long button of 12 choices.
This is exaclty what I would do. Use a OptionMenu or Combobox that is a button with a list that drops down for the user to make a selection. That is the standard way to present users with a limited set of options to choose from.
Quote:ts the concept of self init and how to indent the functions that bugs me.
When do i use self and why. In some examples its there sometimes its not.
self is the first argument in any instance method. self should never appear anywhere else.
When you do this in your program.
x = Calendrier()
x.affCal()
Python changes it to:
x = Calendrier()
Calendrier.affCal(x)
Inside the Calendrier.affCal method you should see this:
    def affCal(self):
    annee = self.anne.get()
    mois = self.mois.get()
    self.resultat.insert(tk.INSERT, calendar.month(annee, mois))
The "self" parameter is going to receive the "x" arguement that was used to call the method. self with be a Calendrier object and it is how you can call Calendrier methods and access Calendrier attributes.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How can I create menu in Python? khagan07 1 578 Oct-07-2023, 12:44 PM
Last Post: deanhystad
  Create a dynamic Menu from a editable Dictionary. KiNeMs 1 2,354 Jan-28-2020, 04:27 AM
Last Post: Larz60+
  Create menu with selectable items SaladFingers 4 3,025 Sep-28-2019, 11:23 AM
Last Post: SaladFingers

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020