Как извлечь значение из класса Tkinter и использовать его в другом? - PullRequest
0 голосов
/ 15 октября 2019

У меня возникла проблема с Tkinter, и я не могу разобраться с часами поиска в Google. Я нашел большой кусок кода, который создает календарь в Tkinter и возвращает дату в определенном формате. Когда я использую другой класс для доступа к этим данным, он возвращает либо ошибки, место хранения текста, либо просто не то, что мне нужно вообще.

Вот базовый код, который создает приложение календаря tkinter (кредит Rambarun Komaljeet)

import calendar
import tkinter as tk
import time
from tkinter import ttk
import sys

class MyDatePicker(tk.Toplevel):
    """
    Description:
        A tkinter GUI date picker.
    """

    def __init__(self, widget=None, format_str=None):
        """
        :param widget: widget of parent instance.

        :param format_str: print format in which to display date.
        :type format_str: string

        Example::
            a = MyDatePicker(self, widget=self.parent widget,
                             format_str='%02d-%s-%s')
        """

        super().__init__()
        self.widget = widget
        self.str_format = format_str

        self.title("Date Picker")
        self.resizable(0, 0)
        self.geometry("+630+390")

        self.init_frames()
        self.init_needed_vars()
        self.init_month_year_labels()
        self.init_buttons()
        self.space_between_widgets()
        self.fill_days()
        self.make_calendar()

    def init_frames(self):
        self.frame1 = tk.Frame(self)
        self.frame1.pack()

        self.frame_days = tk.Frame(self)
        self.frame_days.pack()

    def init_needed_vars(self):
        self.month_names = tuple(calendar.month_name)
        self.day_names = tuple(calendar.day_abbr)
        self.year = time.strftime("%Y")
        self.month = time.strftime("%B")

    def init_month_year_labels(self):
        self.year_str_var = tk.StringVar()
        self.month_str_var = tk.StringVar()

        self.year_str_var.set(self.year)
        self.year_lbl = tk.Label(self.frame1, textvariable=self.year_str_var,
                                 width=3)
        self.year_lbl.grid(row=0, column=5)

        self.month_str_var.set(self.month)
        self.month_lbl = tk.Label(self.frame1, textvariable=self.month_str_var,
                                  width=8)
        self.month_lbl.grid(row=0, column=1)

    def init_buttons(self):
        self.left_yr = ttk.Button(self.frame1, text="←", width=5,
                                  command=self.prev_year)
        self.left_yr.grid(row=0, column=4)

        self.right_yr = ttk.Button(self.frame1, text="→", width=5,
                                   command=self.next_year)
        self.right_yr.grid(row=0, column=6)

        self.left_mon = ttk.Button(self.frame1, text="←", width=5,
                                   command=self.prev_month)
        self.left_mon.grid(row=0, column=0)

        self.right_mon = ttk.Button(self.frame1, text="→", width=5,
                                    command=self.next_month)
        self.right_mon.grid(row=0, column=2)

    def space_between_widgets(self):
        self.frame1.grid_columnconfigure(3, minsize=40)

    def prev_year(self):
        self.prev_yr = int(self.year_str_var.get()) - 1
        self.year_str_var.set(self.prev_yr)

        self.make_calendar()

    def next_year(self):
        self.next_yr = int(self.year_str_var.get()) + 1
        self.year_str_var.set(self.next_yr)

        self.make_calendar()

    def prev_month(self):
        index_current_month = self.month_names.index(self.month_str_var.get())
        index_prev_month = index_current_month - 1

        #  index 0 is empty string, use index 12 instead,
        # which is index of December.
        if index_prev_month == 0:
            self.month_str_var.set(self.month_names[12])
        else:
            self.month_str_var.set(self.month_names[index_current_month - 1])

        self.make_calendar()

    def next_month(self):
        index_current_month = self.month_names.index(self.month_str_var.get())

        try:
            self.month_str_var.set(self.month_names[index_current_month + 1])
        except IndexError:
            #  index 13 does not exist, use index 1 instead, which is January.
            self.month_str_var.set(self.month_names[1])

        self.make_calendar()

    def fill_days(self):
        col = 0
        #  Creates days label
        for day in self.day_names:
            self.lbl_day = tk.Label(self.frame_days, text=day)
            self.lbl_day.grid(row=0, column=col)
            col += 1

    def make_calendar(self):
        #  Delete date buttons if already present.
        #  Each button must have its own instance attribute for this to work.
        try:
            for dates in self.m_cal:
                for date in dates:
                    if date == 0:
                        continue

                    self.delete_buttons(date)

        except AttributeError:
            pass

        year = int(self.year_str_var.get())
        month = self.month_names.index(self.month_str_var.get())
        self.m_cal = calendar.monthcalendar(year, month)

        #  build dates buttons.
        for dates in self.m_cal:
            row = self.m_cal.index(dates) + 1
            for date in dates:
                col = dates.index(date)

                if date == 0:
                    continue

                self.make_button(str(date), str(row), str(col))

    def make_button(self, date, row, column):
        """
        Description:
            Build a date button.

        :param date: date.
        :type date: string

        :param row: row number.
        :type row: string

        :param column: column number.
        :type column: string
        """
        exec(
            "self.btn_" + date + " = ttk.Button(self.frame_days, text=" + date
            + ", width=5)\n"
            "self.btn_" + date + ".grid(row=" + row + " , column=" + column
            + ")\n"
            "self.btn_" + date + ".bind(\"<Button-1>\", self.get_date)"
        )

    def delete_buttons(self, date):
        """
        Description:
            Delete a date button.

        :param date: date.
        :type: string
        """
        exec(
            "self.btn_" + str(date) + ".destroy()"
        )

    def get_date(self, clicked=None):
        """
        Description:
            Get the date from the calendar on button click.

        :param clicked: button clicked event.
        :type clicked: tkinter event
        """

        clicked_button = clicked.widget
        year = self.year_str_var.get()
        month = self.month_str_var.get()
        date = clicked_button['text']

        self.full_date = self.str_format % (date, month, year)
        print(self.full_date)
        sys.stderr.write(self.full_date)
        #  Replace with parent 'widget' of your choice.
        try:
            self.widget.delete(0, tk.END)
            self.widget.insert(0, self.full_date)
        except AttributeError:
            pass


if __name__ == '__main__':
    def application():
        MyDatePicker(format_str='%02d-%s-%s')

    root = tk.Tk()
    btn = tk.Button(root, text="test", command=application)
    btn.pack()
    root.mainloop()

Я пытался вернуть эти данные в первое окно tkinter. что я открываю, чтобы я мог использовать его для функции поиска. Похоже, что мне нужно именно то, что мне нужно, в разделе get_date(), где он извлекает информацию и печатает дату в консоли как переменную self.full_date.

. Как мне заставить это работать в другомкласс? Это то, что у меня есть до сих пор (MyDatePicker тоже есть, но я не хотел загромождать слишком много места)

class Main_Window(tk.Frame,MyDatePicker):
    def __init__(self, root):
        self.root=root
        #self.MyDatePicker=MyDatePicker()
        tk.Frame.__init__(self, root)
        self.root.geometry('300x300')
        b1 = tk.Button(self.root, text="Add another window", command =lambda: self.newWindow(1))
        b1.grid(column=1, row=1)
        self.total = 0
        self.count=0
        self.total_label_text = tk.IntVar()
        self.total_label_text.set(self.total)
        #self.total_label_text
        self.lbl1=tk.Label(self.root,textvariable=self.total_label_text)
        self.lbl1.grid(column=1,row=2)

        b2 = tk.Button(self.root, text="Add another window", command =lambda: self.newWindow(2))
        b2.grid(column=2, row=1)
        self.total2 = 0
        self.count2=0
        self.total_label_text2 = tk.IntVar()
        self.total_label_text2.set(self.total2)
        #self.total_label_text
        self.lbl2=tk.Label(self.root,textvariable=self.total_label_text2)
        self.lbl2.grid(column=2,row=2)

        b1 = tk.Button(self.root, text="Add another window", command =lambda: self.press_calendar(format_str='%02d-%s-%s',Class=MyDatePicker))
        b1.grid(column=1, row=1)


    def press_calendar(self,format_str,Class):
        self.MyDatePicker1=Class(format_str)
        self.MyDatePicker1.get_date(self)

    def newWindow(self,m):
        if m ==1:
            self.count += 1
        if m ==2:
            self.count2+=1
        self.window = tk.Toplevel(self)

        but1=tk.Button(self.window,text="Add One",command =lambda:self.close(m))
        but1.grid(row=2,column=1)
    def close(self,m):
        if m==1:
            self.total_label_text.set(self.count)
        if m==2:
            self.total_label_text2.set(self.count2)
        self.window.destroy()


if __name__ == "__main__":
    root = tk.Tk()
    Main_Window(root)
    root.mainloop()

Я пытаюсь сделать это в части press_calendarмоего кода, где я вызываю другой класс, запускаю его и возвращаю дату.

Все, что я получаю, - это местоположение переменной, или мне нужно инициализировать все переменные из MyDatePicker вMain_Window class.

Что я могу сделать лучше, чтобы на самом деле получить дату и использовать ее в моем главном окне?

Спасибо за помощь!

1 Ответ

0 голосов
/ 15 октября 2019

Насколько я вижу, класс MyDatePicker() не предназначен для наследования, а используется как сервер. В моем примере я звоню MyDatePicker() и предоставляю виджет мастера, куда я хотел бы отправить строку даты.

class Main_Window(tk.Frame):
    def __init__(self, root):
        self.root = root
        self.root.geometry('300x300')

        tk.Frame.__init__(self, root)
        self.pack()

        b1 = tk.Button(self, text="Pick date", command=self.pick_date)
        b1.grid(column=0, row=0)

        # Widget to recieve date string from MyDatePicker
        self.date_display = tk.Entry(self, text='apa', width=20)
        self.date_display.grid(column=0, row=1)

    def pick_date(self):
        # Call MyDatePicker and provide widget to recieve date string
        picker = MyDatePicker(widget=self.date_display, format_str='%02d-%s-%s')


if __name__ == "__main__":
    root = tk.Tk()
    Main_Window(root)
    root.mainloop()

Вам придется удалить секцию if __name__ == "__main__": из кода MyDatePicker(), чтобы он функционировал, если они должны находиться в одном файле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...