【问题标题】:How to keep open Tkcalendar after running code运行代码后如何保持打开的 Tkcalendar
【发布时间】:2020-08-10 03:57:52
【问题描述】:

我正在尝试在 Windows 10 的 Python 3.8.5 中使用 Tkcalendar 和 PyQt5 从网站打印 PDF

我可以在第一次尝试时打印 PDF 文件。但我无法再次打印,因为 Tkcalendar 关闭了,我想保持打开状态。我做错了什么?

谢谢。

import datetime
import requests
import re
import sys
from bs4 import BeautifulSoup
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5 import QtWebEngineWidgets
from tkinter import *
from tkinter import messagebox
from tkcalendar import *

def generar_pdf():
    
    fecha = datetime.datetime.strptime(cal.get_date(), "%d-%m-%Y").strftime("%Y-%m-%d")
    day = datetime.datetime.strptime(cal.get_date(), "%d-%m-%Y").strftime("%d")
    month = datetime.datetime.strptime(cal.get_date(), "%d-%m-%Y").strftime("%m")
    year = datetime.datetime.strptime(cal.get_date(), "%d-%m-%Y").strftime("%Y")
    strURL = "https://www.dof.gob.mx/index_111.php?year=" + year + "&month=" + month + "&day=" + day + "&edicion=MAT"

    req = requests.get(strURL)
    soup = BeautifulSoup(req.text, "lxml")

    for sub_heading in soup.find_all("a", href=True):

        if re.sub("[^\w .]", "", sub_heading.text) == "Tipo de cambio para solventar obligaciones denominadas en moneda extranjera pagaderas en la República Mexicana.":

            DOF_URL = "https://www.dof.gob.mx" + sub_heading.get("href")

        else:
            pass
    
    app = QtWidgets.QApplication(sys.argv)
    loader = QtWebEngineWidgets.QWebEngineView()
    loader.page().pdfPrintingFinished.connect(loader.close)
    loader.load(QtCore.QUrl(DOF_URL))

    def emit_pdf(finished):
        loader.page().printToPdf(fecha + ".pdf")
        messagebox.showinfo("PDF Generado", "Se generó el PDF con éxito.")

    loader.loadFinished.connect(emit_pdf)
    app.exec()

root = Tk()
root.geometry("400x400")

fecha_hoy = datetime.datetime.now()
dia_hoy = int(fecha_hoy.strftime("%d"))
mes_hoy = int(fecha_hoy.strftime("%m"))
año_hoy = int(fecha_hoy.strftime("%Y"))

cal = Calendar(root, selectmode="day", year=año_hoy, month=mes_hoy, day=dia_hoy, date_pattern="dd-mm-yyyy")
cal.pack(pady=20, fill="both", expand=True)

my_button = Button(cal, text="Generar PDF", command=generar_pdf)
my_button.pack(pady=20)

root.mainloop()

【问题讨论】:

    标签: python tkinter pyqt5 tkcalendar


    【解决方案1】:

    问题是您正在使用具有 2 个事件循环的 2 个库,一个可能的解决方案是在不同的进程中分别运行事件循环,但这会不必要地使应用程序复杂化。更好的解决方案是使用单个库编写所有逻辑,在这个库中因为在 tkinter 中没有等效的 Qt WebEngine 我将选择使用 pyqt5:

    from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
    
    
    SCRIPT_FIND_URL = """
    var url = ""
    var phrase = "Tipo de cambio para solventar obligaciones denominadas en moneda extranjera pagaderas en la República Mexicana."
    var elements = document.getElementsByTagName("a");
    for(const e of elements){
        if(e.text.includes(phrase))
            url = e.href
    }
    url
    """
    
    
    class PageOffline(QtWebEngineWidgets.QWebEnginePage):
        finished = QtCore.pyqtSignal(bool)
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self.date_url = QtCore.QUrl()
            self.loadFinished.connect(self.handle_loaded)
            self.pdfPrintingFinished.connect(self.handle_pdf)
    
        def search(self, date):
            self.date = date
            self.date_url = QtCore.QUrl("https://www.dof.gob.mx/index_111.php")
            query = QtCore.QUrlQuery()
            query.addQueryItem("year", self.date.toString("yyyy"))
            query.addQueryItem("month", self.date.toString("MM"))
            query.addQueryItem("day", self.date.toString("dd"))
            query.addQueryItem("edicion", "MAT")
            self.date_url.setQuery(query)
            self.load(self.date_url)
    
        def handle_loaded(self, ok):
            if ok:
                if self.url() == self.date_url:
                    self.runJavaScript(SCRIPT_FIND_URL, self.handle_url)
                else:
                    filename = "{}.pdf".format(self.date.toString("yyyy-MM-dd"))
                    self.printToPdf(filename)
            else:
                self.finished.emit(False)
    
        def handle_url(self, url):
            if url:
                pdf_url = QtCore.QUrl.fromUserInput(url)
                self.load(pdf_url)
            else:
                self.finished.emit(False)
    
        def handle_pdf(self, path, ok):
            self.finished.emit(ok)
    
    
    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.page = PageOffline()
    
            self.button = QtWidgets.QPushButton("Generate pdf")
            self.calendar = QtWidgets.QCalendarWidget()
    
            lay = QtWidgets.QVBoxLayout(self)
            lay.addWidget(self.calendar)
            lay.addWidget(self.button, alignment=QtCore.Qt.AlignCenter)
    
            self.button.clicked.connect(self.handle_clicked)
            self.page.finished.connect(self.handle_print_finished)
    
        def handle_clicked(self):
            date = self.calendar.selectedDate()
            self.page.search(date)
            self.button.setEnabled(False)
    
        def handle_print_finished(self, status):
            QtWidgets.QMessageBox.information(
                self,
                "Generación de PDF",
                "El PDF fue generado con éxito" if status else "La generación de PDF fallo",
            )
            self.button.setEnabled(True)
    
    
    def main():
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        QtCore.QLocale.setDefault(QtCore.QLocale(QtCore.QLocale.Spanish))
        w = Widget()
        w.resize(400, 400)
        w.show()
        sys.exit(app.exec_())
    
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-21
      • 1970-01-01
      • 2013-01-29
      • 2023-03-02
      • 2023-02-05
      • 2013-02-07
      • 2013-05-20
      相关资源
      最近更新 更多