Python QtGui 日历控件调用按钮

1 投票
1 回答
1364 浏览
提问于 2025-04-18 18:35

我正在使用一个Python的日历小部件。我需要在点击按钮时调用这个小部件。现在的问题是,我找不到日历类中用来显示这个小部件的方法。

这个日历类是从这里获取的:http://www.eurion.net/python-snippets/snippet/Calendar_Date%20picker.html

以下是我的导入内容:

from tkinter import *
from tkinter import ttk
import tkinter.messagebox
import time
import requests #needs to be installed
import pymysql #needs to be installed
import csv 
import win32com.client #needs to be installed
from calendar import Calendar
import datetime

这是我创建按钮的代码:

# Calendar Buttons
calBut=ttk.Button(f2, width=4, text="Cal",       command=Calendar.what_method?).grid(column=3,row=1, sticky=W)

据我所知,我可以直接把按钮的命令设置为调用日历类中显示小部件的方法。可是,我该怎么找到这个方法呢?每次我点击按钮时,日历小部件都没有显示出来。

我使用的是Python 3.3.5,Spider,WinPython 3.3.5

**编辑**

这个程序有多个标签,f2表示按钮所在的标签。

from tkinter import *
from tkinter import ttk
import tkinter.messagebox
import time
import requests #needs to be installed
import pymysql #needs to be installed
import csv 
import win32com.client #needs to be installed
import datetime
from calendar import Calendar
import calendar


#################################
# Create Button Click Calendar

 def callback():
    root2=Toplevel(f2)
    ttkcal = Calendar(root2,firstweekday=calendar.SUNDAY)
    ttkcal.pack(expand=1, fill='both')
    root2.update()
    root2.minsize(root2.winfo_reqwidth(), root2.winfo_reqheight())



 # Calendar Buttons

 b=ttk.Button(f2, width=4, text="Cal", command=callback).grid(column=3,row=1, sticky=W)

当我按下按钮时,日历窗口会打开,但里面是空的。控制台还给我报错:

TypeError: __init__() got multiple values for argument 'firstweekday

谢谢

1 个回答

1

这可不简单。问题在于你混用了两种图形界面库。因此,你需要两个主要的事件循环(至少):一个用于 Tkinter 代码,另一个用于 PyQt 代码。
实现你想要的一个方法是使用 subprocessthreading 模块,在不同的线程中运行 calendar.py。示例:

from tkinter import *
from tkinter import ttk

import subprocess
import threading

master = Tk()

def callback():
    subprocess.call('python calendar.py')


b=ttk.Button(master, width=4, text="Cal", command=lambda:threading.Thread(target=callback).start()).grid(column=3,row=1, sticky=W)


mainloop()

另一种方法是在回调函数中创建 Qt 的主事件循环(这是一种不太干净的解决方案):

from tkinter import *
from tkinter import ttk
from calendar import Calendar
import sys
from PyQt4 import QtGui

master = Tk()

def callback():
    app = QtGui.QApplication(sys.argv)
    gui = Calendar()
    gui.show()
    app.exec_()


b=ttk.Button(master, width=4, text="Cal", command=callback).grid(column=3,row=1, sticky=W)

mainloop()

编辑:如何调用小部件。
首先,看看 这个回答,并按照 kalgasnik 的建议修改你的 ttkcalendar.py。然后试试这个:

from tkinter import *
from tkinter import ttk
from ttkcalendar import Calendar
import calendar

master = Tk()

def callback():
    root2=Toplevel(master)
    ttkcal = Calendar(root2,firstweekday=calendar.SUNDAY)
    ttkcal.pack(expand=1, fill='both')
    root2.update()
    root2.minsize(root2.winfo_reqwidth(), root2.winfo_reqheight())

b=ttk.Button(master, width=4, text="Cal", command=callback).grid(column=3,row=1, sticky=W)

mainloop()

编辑 2. 解决问题
好的,看来我找到了所有问题。

  1. 实际上,你导入了两次相同的模块——标准的 calendar 模块:

    from calendar import Calendar
    import calendar
    

但你没有从 ttkcalendar 模块中导入 Calendar 类(别忘了按照 这里的描述进行更改)。 所以,导入应该像这样:

import ttkcalendar
import calendar

创建日历(我稍微修改了一下代码以便更清晰):

ttkcal = ttkcalendar.Calendar(root2,firstweekday=calendar.SUNDAY)
  1. 在你的代码中,主窗口被初始化了两次:
    第15行: master = Tk()
    第960行: root = Tk()
    你需要删除第一次的初始化。

  2. 你在同一个主窗口中混用了 pack()grid()。根据 文档,这是个坏主意:

警告:绝不要在同一个主窗口中混合使用 grid 和 pack。Tkinter 会乐于花费你余生的时间来尝试找到一个让两个管理器都满意的解决方案。与其等待,不如杀掉应用程序,重新审视你的代码。一个常见的错误是为某些小部件使用了错误的父级。

所以,代替 nb.pack(fill='both', expand='yes'),你应该写类似于 nb.grid(column=0, row=0, sticky=(W, E)) 的代码。

最后,这里是修复后代码的链接:

ttkcalendar.py(已经修改,准备使用):
https://gist.github.com/anonymous/5e0d973f57e185572df2

你的脚本与描述的修改:
https://gist.github.com/anonymous/65cb808dc64e414c0c12

撰写回答