Календарь (gtk.Calendar)

Виджет Calendar это эффективный способ для отображения или получения дат. Он очень прост в создании и работе.

Создание виджета gtk.Calendar также просто как:

  calendar = gtk.Calendar()

По умолчанию календарь будет отображать текущий месяц и год.

Случается, что вам нужно изменить большое количество информации в этом виджете, и следующие методы позволяют делать множественные изменения в виджете Calendar, без мерцания обновлений на экране.

  calendar.freeze()

  calendar.thaw()

Они работают также как методы freeze/thaw на любом другом виджете.

Виджет Calendar имеет несколько настроек, которые позволяют изменить внешний вид виджета, управляются они с помощью метода:

  calendar.display_options(flags)

Аргумент flags может быть создан смешиванием следующих пяти опций с помощью операции логического сложения OR (|):

CALENDAR_SHOW_HEADING Эта опция указывает что месяц и год должны быть отображены на календаре.
CALENDAR_SHOW_DAY_NAMES Эта опция указывает что необходимо отображать трёхбуквенные названия дней недели (Пнд, Втр, Ср и т.д.)
CALENDAR_NO_MONTH_CHANGE Эта опция задаёт что пользователь не должен и не может изменять отображаемый месяц. Это может быть полезно когда вам нужно отобразить определённый месяц, так, если нужно отобразить 12 календарей на каждый месяц определённого года.
CALENDAR_SHOW_WEEK_NUMBERS Эта опция указывает что номер каждой недели должен быть показан слева от календаря. (так 1 Янв = 1 неделя, 31 Дек =  52 неделя).
CALENDAR_WEEK_START_MONDAY Эта опция задаёт начало календарной недели с понедельника, а не с воскресенья как выбрано по умолчанию. Это влияет только на порядок в котором дни отображаются слева направо. Заметим, что в PyGTK 2.4 и выше эта опция считается устаревшей.

Следующие методы используются для установки отображаемой даты:

  result = calendar.select_month(month, year)

  calendar.select_day(day)

Логическое значение возвращаемое после метода select_month() показывает успешность выбора.

С методом select_day() указывается номер дня в текущем месяце, если это возможно. День 0 снимает любой текущий выбор.

В дополнение к выбору, любое число дней в месяце могут быть “отмечены”. Отмеченный день выделяется подсветкой. Следующие методы предоставлены для управления отмеченными днями:

  result = calendar.mark_day(day)

  result = calendar.unmark_day(day)

  calendar.clear_marks()

mark_day() и unmark_day() возвращают логическое значение, показывающее успешность выполнения. Заметим что метки сохраняются при изменении месяца или года.

Последний метод виджета Calendar используется для получения текущей выбранной даты, месяца и/или года.

  year, month, day = calendar.get_date()

Виджет Calendar может генерировать несколько сигналов означающих выбор даты и её изменение. Названия говорят сами за себя, вот они:

  month_changed

  day_selected

  day_selected_double_click

  prev_month

  next_month

  prev_year

  next_year

Остаётся нам только поместить все это в наш пример calendar.pyРисунок 9.12, “Пример календаря” показывает интерфейс программы:

Рисунок 9.12. Пример календаря

Calendar Example

Исходный код calendar.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# example calendar.py
#
# Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Gronlund
# Copyright (C) 2000 Tony Gale
# Copyright (C) 2001-2004 John Finlay
# Copyright (C) 2011 Sergey Zavgorodniy, Grigoriy Kramarenko
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import pygtk
pygtk.require('2.0')
import gtk, pango
import time

class CalendarExample:
    DEF_PAD = 10
    DEF_PAD_SMALL = 5
    TM_YEAR_BASE = 1900

    calendar_show_header = 0
    calendar_show_days = 1
    calendar_month_change = 2 
    calendar_show_week = 3

    def calendar_date_to_string(self):
        year, month, day = self.window.get_date()
        mytime = time.mktime((year, month+1, day, 0, 0, 0, 0, 0, -1))
        return time.strftime("%x", time.localtime(mytime))

    def calendar_set_signal_strings(self, sig_str):
        prev_sig = self.prev_sig.get()
        self.prev2_sig.set_text(prev_sig)

        prev_sig = self.last_sig.get()
        self.prev_sig.set_text(prev_sig)
        self.last_sig.set_text(sig_str)

    def calendar_month_changed(self, widget):
        buffer = "month_changed: %s" % self.calendar_date_to_string()
        self.calendar_set_signal_strings(buffer)

    def calendar_day_selected(self, widget):
        buffer = "day_selected: %s" % self.calendar_date_to_string()
        self.calendar_set_signal_strings(buffer)

    def calendar_day_selected_double_click(self, widget):
        buffer = "day_selected_double_click: %s"
        buffer = buffer % self.calendar_date_to_string()
        self.calendar_set_signal_strings(buffer)

        year, month, day = self.window.get_date()

        if self.marked_date[day-1] == 0:
            self.window.mark_day(day)
            self.marked_date[day-1] = 1
        else:
            self.window.unmark_day(day)
            self.marked_date[day-1] = 0

    def calendar_prev_month(self, widget):
        buffer = "prev_month: %s" % self.calendar_date_to_string()
        self.calendar_set_signal_strings(buffer)

    def calendar_next_month(self, widget):
        buffer = "next_month: %s" % self.calendar_date_to_string()
        self.calendar_set_signal_strings(buffer)

    def calendar_prev_year(self, widget):
        buffer = "prev_year: %s" % self.calendar_date_to_string()
        self.calendar_set_signal_strings(buffer)

    def calendar_next_year(self, widget):
        buffer = "next_year: %s" % self.calendar_date_to_string()
        self.calendar_set_signal_strings(buffer)

    def calendar_set_flags(self):
        options = 0
        for i in range(5):
            if self.settings[i]:
                options = options + (1<<i)
        if self.window:
            self.window.display_options(options)

    def calendar_toggle_flag(self, toggle):
        j = 0
        for i in range(5):
            if self.flag_checkboxes[i] == toggle:
                j = i

        self.settings[j] = not self.settings[j]
        self.calendar_set_flags()

    def calendar_font_selection_ok(self, button):
        self.font = self.font_dialog.get_font_name()
        if self.window:
            font_desc = pango.FontDescription(self.font)
            if font_desc: 
                self.window.modify_font(font_desc)

    def calendar_select_font(self, button):
        if not self.font_dialog:
            window = gtk.FontSelectionDialog("Диалог выбора шрифта")
            self.font_dialog = window
    
            window.set_position(gtk.WIN_POS_MOUSE)
    
            window.connect("destroy", self.font_dialog_destroyed)
    
            window.ok_button.connect("clicked",
                                     self.calendar_font_selection_ok)
            window.cancel_button.connect_object("clicked",
                                                lambda wid: wid.destroy(),
                                                self.font_dialog)
        window = self.font_dialog
        if not (window.flags() & gtk.VISIBLE):
            window.show()
        else:
            window.destroy()
            self.font_dialog = None

    def font_dialog_destroyed(self, data=None):
        self.font_dialog = None

    def __init__(self):
        flags = [
            "Показать заголовок",
            "Показать название дня",
            "Не изменять месяц",
            "Показать номера недель",
            ]
        self.window = None
        self.font = None
        self.font_dialog = None
        self.flag_checkboxes = 5*[None]
        self.settings = 5*[0]
        self.marked_date = 31*[0]

        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_title("Пример календаря")
        window.set_border_width(5)
        window.connect("destroy", lambda x: gtk.main_quit())

        window.set_resizable(False)

        vbox = gtk.VBox(False, self.DEF_PAD)
        window.add(vbox)

        # Верхняя часть окна, календарь, флаги и выбор шрифта.
        hbox = gtk.HBox(False, self.DEF_PAD)
        vbox.pack_start(hbox, True, True, self.DEF_PAD)
        hbbox = gtk.HButtonBox()
        hbox.pack_start(hbbox, False, False, self.DEF_PAD)
        hbbox.set_layout(gtk.BUTTONBOX_SPREAD)
        hbbox.set_spacing(5)

        # Календарь
        frame = gtk.Frame("Календарь")
        hbbox.pack_start(frame, False, True, self.DEF_PAD)
        calendar = gtk.Calendar()
        self.window = calendar
        self.calendar_set_flags()
        calendar.mark_day(19)
        self.marked_date[19-1] = 1
        frame.add(calendar)
        calendar.connect("month_changed", self.calendar_month_changed)
        calendar.connect("day_selected", self.calendar_day_selected)
        calendar.connect("day_selected_double_click",
                         self.calendar_day_selected_double_click)
        calendar.connect("prev_month", self.calendar_prev_month)
        calendar.connect("next_month", self.calendar_next_month)
        calendar.connect("prev_year", self.calendar_prev_year)
        calendar.connect("next_year", self.calendar_next_year)

        separator = gtk.VSeparator()
        hbox.pack_start(separator, False, True, 0)

        vbox2 = gtk.VBox(False, self.DEF_PAD)
        hbox.pack_start(vbox2, False, False, self.DEF_PAD)
  
        # Создаём рамку справа, с флагами внутри
        frame = gtk.Frame("Флаги")
        vbox2.pack_start(frame, True, True, self.DEF_PAD)
        vbox3 = gtk.VBox(True, self.DEF_PAD_SMALL)
        frame.add(vbox3)

        for i in range(len(flags)):
            toggle = gtk.CheckButton(flags[i])
            toggle.connect("toggled", self.calendar_toggle_flag)
            vbox3.pack_start(toggle, True, True, 0)
            self.flag_checkboxes[i] = toggle

        # Создаём кнопку выбора шрифта
        button = gtk.Button("Шрифт...")
        button.connect("clicked", self.calendar_select_font)
        vbox2.pack_start(button, False, False, 0)

        # Создаём часть сигнал-событие.
        frame = gtk.Frame("События сигналов")
        vbox.pack_start(frame, True, True, self.DEF_PAD)

        vbox2 = gtk.VBox(True, self.DEF_PAD_SMALL)
        frame.add(vbox2)
  
        hbox = gtk.HBox (False, 3)
        vbox2.pack_start(hbox, False, True, 0)
        label = gtk.Label("Сигнал:")
        hbox.pack_start(label, False, True, 0)
        self.last_sig = gtk.Label("")
        hbox.pack_start(self.last_sig, False, True, 0)

        hbox = gtk.HBox (False, 3)
        vbox2.pack_start(hbox, False, True, 0)
        label = gtk.Label("Предыдущий сигнал:")
        hbox.pack_start(label, False, True, 0)
        self.prev_sig = gtk.Label("")
        hbox.pack_start(self.prev_sig, False, True, 0)

        hbox = gtk.HBox (False, 3)
        vbox2.pack_start(hbox, False, True, 0)
        label = gtk.Label("Второй предыдущий сигнал:")
        hbox.pack_start(label, False, True, 0)
        self.prev2_sig = gtk.Label("")
        hbox.pack_start(self.prev2_sig, False, True, 0)

        bbox = gtk.HButtonBox ()
        vbox.pack_start(bbox, False, False, 0)
        bbox.set_layout(gtk.BUTTONBOX_END)

        button = gtk.Button(gtk.STOCK_CLOSE, gtk.STOCK_CLOSE)
        button.connect("clicked", lambda w: gtk.main_quit())
        bbox.add(button)
        button.set_flags(gtk.CAN_DEFAULT)
        button.grab_default()

        window.show_all()

def main():
    gtk.main()
    return 0

if __name__ == "__main__":
    CalendarExample()
    main()

Предыдущая страница На уровень выше Следующая страница
9.11. Комбинированный список (gtk.Combo) К оглавлению  9.13. Выбор цвета (gtk.ColorSelection)

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>