0

好的,所以我正在编写一个使用 pytray 创建系统托盘图标的脚本。该脚本基本上连接到用户谷歌日历,并且(好吧,最终无论如何)允许您选择要使用的日历并向您显示不同的即将发生的事件。

问题 #1 选择我想使用的日历时,我总是在选择日历时获得最后一个日历 ID。我的通讯录日历恰好是我日历列表中列出的最后一个。当我选择任何日历时,我总是会获得地址簿日历的 ID。

我认为与此问题有关的代码:

    def set_cal_id(self, cal_id):
        self.cal_id = cal_id
        print(self.cal_id)
        # return self.cal_id
    
    def get_cal_id(self):
        return self.cal_id

def build_calendar_list(self):
        cal_list = []
        calendarlist = self.service.calendarList().list().execute()

        for k in calendarlist.get('items', tuple()):
            # print(k['id'])
            calendar_id = k['id']
            cal_list.append(
                (item(k["summary"], lambda *args: self.set_cal_id(calendar_id)))
            )
            # pprint.pprint(k)

        # pprint.pprint(cal_list)
        # print(self.cal_id)
        
        return cal_list

问题 #2(已修复)当使用 pystray 在系统托盘中创建我的日历列表时,是否有某种方法可以遍历我正在构建的元组并列出它?我必须手动输入元组中每个项目的索引才能列出菜单。有什么方法可以“动态/以编程方式”做到这一点吗?

更新问题 #2 我只需要 menu() 中的 lambda 函数来正确创建所有项目

与此问题相关的代码:

    def create_tray(self):
        # count = self.cal_list.count()
        menu_items = tuple(self.cal_list)
        icon(
            'TrayCalendar',
            icon=self.tray_icon(),
            # visible=True,
            menu=menu(
                item(
                    'Quit',
                    self.good_bye
                ),
                item(
                    'Calendar List', 
                    menu(
                     lambda: (item for item in menu_items)
                    ),
                ),
            )
        
        ).run()

我认为最好知道一些事情:

  • 我现在正在严格地为 Windows 编写这个。我稍后会扩展,也许嗯,现在不确定这只是一个“嘿,我可以做这个”的项目。

  • build_calendar_list() 为 pystray 的 MenuItem() 创建元组

  • create_tray() 创建托盘图标。

  • 我正在 MyCalendar 类的 init 函数中构建日历列表​​。

  • 我也可能这样做完全错误。

  • 我认为问题在于,当它使用 lambda 函数生成列表时,无论出于何种原因,它都会导致回调的所有参数成为堆栈中的最后一项。如果是这种情况,那么生成此列表的更好方法是什么?

下面是完整的代码。

from __future__ import print_function

import datetime
import os.path
import pprint
import sys

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

from PIL import Image
from pystray import Icon as icon, Menu as menu, MenuItem as item


# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar']

class MyCalendar:
    def __init__(self):
        """Shows basic usage of the Google Calendar API.
            Prints the start and name of the next 10 events on the user's calendar.
        """
        self.creds = None
        # The file token.json stores the user's access and refresh tokens, and is
        # created automatically when the authorization flow completes for the first
        # time.
        if os.path.exists('token.json'):
            self.creds = Credentials.from_authorized_user_file('token.json', SCOPES)
        # If there are no (valid) credentials available, let the user log in.
        if not self.creds or not self.creds.valid:
            if self.creds and self.creds.expired and self.creds.refresh_token:
                self.creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    'credentials.json', SCOPES)
                self.creds = flow.run_local_server(port=0)
            # Save the credentials for the next run
            with open('token.json', 'w') as token:
                token.write(self.creds.to_json())

        try:
            # Call the Calendar API
            self.service = build('calendar', 'v3', credentials=self.creds)
            self.cal_id = None
            self.cal_list = self.build_calendar_list()
            # print(self.cal_list)


        except HttpError as error:
            print('An error occurred: %s' % error)


    # def get_events(self):
    #     now = datetime.datetime.utcnow().isoformat() + 'Z'  # 'Z' indicates UTC time

    #     events_result = self.service.events().list(calendarId=self.get_cal_id(), timeMin=now,
    #                                         maxResults=10, singleEvents=True,
    #                                         orderBy='startTime').execute()
    #     events = events_result.get('items', [])

    #     if not events:
    #         print('No upcoming events found.')
    #         return

    #     # Prints the start and name of the next 10 events
    #     for event in events:
    #         start = event['start'].get('dateTime', event['start'].get('date'))
            
    #         print(start, event['summary'])

    def set_cal_id(self, cal_id):
        self.cal_id = cal_id
        print(self.cal_id)
        # return self.cal_id
    
    def get_cal_id(self):
        return self.cal_id


    def tray_icon(self):
        image = Image.open("icon.ico")
        return image

    def good_bye(self, icon):
        print("Later Tater!")
        icon.visible = False
        icon.stop()

    def create_tray(self):
        # count = self.cal_list.count()
        menu_items = tuple(self.cal_list)
        icon(
            'TrayCalendar',
            icon=self.tray_icon(),
            # visible=True,
            menu=menu(
                item(
                    'Quit',
                    self.good_bye
                ),
                item(
                    'Calendar List', 
                    menu(
                        lambda: (item for item in menu_items)
                    ),
                ),
            )
        
        ).run()

    def build_calendar_list(self):
        cal_list = []
        calendarlist = self.service.calendarList().list().execute()

        for k in calendarlist.get('items', tuple()):
            # print(k['id'])
            calendar_id = k['id']
            cal_list.append(
                (item(k["summary"], lambda *args: self.set_cal_id(calendar_id)))
            )
            # pprint.pprint(k)

        # pprint.pprint(cal_list)
        # print(self.cal_id)
        
        return cal_list


if __name__ == '__main__':
    my_cal = MyCalendar()
    my_cal.create_tray()
4

0 回答 0