在Tkinter中打开打印机选择窗口

问题描述 投票:-1回答:2

我可能由于缺乏知识而遇到问题。我想打开Windows对话框来选择打印机,然后使用Tkinter发送到打印机(发送到打印机)。

当前,我使用代码将Tkinter与Wxpython相关联,并使其异步创建单独的进程。

这是上面提到的代码:

from tkinter import *
from threading import Thread
import wx

def f_imprimir(ventana, entry):
    class TextDocPrintout(wx.Printout):
        def __init__(self):
            wx.Printout.__init__(self)

        def OnPrintPage(self, page):
            dc = self.GetDC()

            ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()     
            ppiScreenX, ppiScreenY = self.GetPPIScreen()     
            logScale = float(ppiPrinterX)/float(ppiScreenX)

            pw, ph = self.GetPageSizePixels()
            dw, dh = dc.GetSize()     
            scale = logScale * float(dw)/float(pw)
            dc.SetUserScale(scale, scale)

            logUnitsMM = float(ppiPrinterX)/(logScale*25.4)

            ### Print code ###

            return True

    class PrintFrameworkSample(wx.Frame):        
        def OnPrint(self):
            pdata = wx.PrintData()
            pdata.SetPaperId(wx.PAPER_A4)
            pdata.SetOrientation(wx.LANDSCAPE)

            data = wx.PrintDialogData(pdata)
            printer = wx.Printer(data)

            printout = TextDocPrintout()

            useSetupDialog = True

            if not printer.Print(self, printout, useSetupDialog) and printer.GetLastError() == 
wx.PRINTER_ERROR:

                wx.MessageBox(

                    "There was a problem printing.\n"

                    "Perhaps your current printer is not set correctly?",

                    "Printing Error", wx.OK)

            else:
                data = printer.GetPrintDialogData() 
                pdata = wx.PrintData(data.GetPrintData()) # force a copy

            printout.Destroy()
            self.Destroy()

    app=wx.App(False)
    PrintFrameworkSample().OnPrint()
    entry.config(state="normal")


def process(ventana, entry):
    entry.config(state="disable")
    t = Thread(target=f_imprimir, args=(ventana,entry))
    t.start()

v = Tk()
entry = Entry(v)
entry.pack()
v.bind("a", lambda a:process(v,entry))

当wx.app完成时(可能会在打印机选择器关闭时发生),我计划将条目的状态更改为“正常”。但是将条目的状态更改为“正常”时会引发错误,我认为这是因为我发送的窗口和顺序位于单独的进程中。错误将是:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Python38-32\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\DANTE\Google Drive\JNAAB\DESARROLLO\pruebas\pedasito.py", line 65, in f_imprimir
    entry.config(state="normal")
  File "C:\Python38-32\lib\tkinter\__init__.py", line 1637, in configure
    return self._configure('configure', cnf, kw)
  File "C:\Python38-32\lib\tkinter\__init__.py", line 1627, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
RuntimeError: main thread is not in main loop

任何人都有解决此问题的方法或创建打印窗口而不阻止TCL窗口并能够阻止输入的替代方法吗?如果有办法做到这一点,或者使用Tkinter发送打印,避免这种混乱,那就更好了。谢谢。

python tkinter printing wxpython
2个回答
0
投票

我不使用wxPython,但是您的错误是由于与tkinter有关的线程问题。 Tkinter喜欢在主线程中,尝试将小部件传递到单独的线程可能会导致问题。但是,您的输入字段已经在全局名称空间中,因此您无需传递它。

一旦需要就从您的线程进行简单更新。

我会在您的if/else条件下执行此操作,因此它只会在正确的时间发生。

这样的方法会起作用:请注意,您实际上需要对传递的值做一些事情。现在,除了空白页,您的代码实际上都没有打印任何内容。

import tkinter as tk
from threading import Thread
import wx


def f_imprimir(value):
    # here you can see the value of entry was passed as a string so we can avoid any issues with the widget
    print(value)
    class TextDocPrintout(wx.Printout):
        def __init__(self):
            wx.Printout.__init__(self)

        def OnPrintPage(self, page):
            dc = self.GetDC()
            ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()     
            ppiScreenX, ppiScreenY = self.GetPPIScreen()     
            logScale = float(ppiPrinterX)/float(ppiScreenX)

            pw, ph = self.GetPageSizePixels()
            dw, dh = dc.GetSize()     
            scale = logScale * float(dw)/float(pw)
            dc.SetUserScale(scale, scale)
            logUnitsMM = float(ppiPrinterX)/(logScale*25.4)
            return True

    class PrintFrameworkSample(wx.Frame):        
        def OnPrint(self):
            pdata = wx.PrintData()
            pdata.SetPaperId(wx.PAPER_A4)
            pdata.SetOrientation(wx.LANDSCAPE)
            data = wx.PrintDialogData(pdata)
            printer = wx.Printer(data)
            printout = TextDocPrintout()
            useSetupDialog = True

            if not printer.Print(self, printout, useSetupDialog) and printer.GetLastError() == wx.PRINTER_ERROR:

                wx.MessageBox("There was a problem printing.\n\n"
                              "Perhaps your current printer is not set correctly?\n\n"
                              "Printing Error", wx.OK)
                entry.config(state="normal")
            else:
                data = printer.GetPrintDialogData() 
                pdata = wx.PrintData(data.GetPrintData())  # force a copy
                entry.config(state="normal")

            printout.Destroy()
            self.Destroy()

    app = wx.App(False)
    PrintFrameworkSample().OnPrint()



def process(_=None):
    entry.config(state="disable")
    t = Thread(target=f_imprimir, args=(entry.get(),))
    t.start()


v = tk.Tk()
entry = tk.Entry(v)
entry.pack()
v.bind("<Return>", process)
v.mainloop()

0
投票

这是一种有关绑定的解决方案,现在我正在了解其他形式的事件如何工作。

from tkinter import *
import wx

def f_imprimir():
    class TextDocPrintout(wx.Printout):
        def __init__(self):
            wx.Printout.__init__(self)

        def OnPrintPage(self, page):
            dc = self.GetDC()

            ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()     
            ppiScreenX, ppiScreenY = self.GetPPIScreen()     
            logScale = float(ppiPrinterX)/float(ppiScreenX)

            pw, ph = self.GetPageSizePixels()
            dw, dh = dc.GetSize()     
            scale = logScale * float(dw)/float(pw)
            dc.SetUserScale(scale, scale)

            logUnitsMM = float(ppiPrinterX)/(logScale*25.4)

            ### Print code ###

            return True

    class PrintFrameworkSample(wx.Frame):        
        def OnPrint(self):
            pdata = wx.PrintData()
            pdata.SetPaperId(wx.PAPER_A4)
            pdata.SetOrientation(wx.LANDSCAPE)

            data = wx.PrintDialogData(pdata)
            printer = wx.Printer(data)

            printout = TextDocPrintout()

            useSetupDialog = True

            if not printer.Print(self, printout, useSetupDialog) and         printer.GetLastError() == wx.PRINTER_ERROR:

                wx.MessageBox(

                    "There was a problem printing.\n"

                    "Perhaps your current printer is not set correctly?",

                    "Printing Error", wx.OK)

            else:
                data = printer.GetPrintDialogData() 
                pdata = wx.PrintData(data.GetPrintData()) # force a copy

            printout.Destroy()
            self.Destroy()

    app=wx.App(False)
    PrintFrameworkSample().OnPrint()

v = Tk()
entry = Entry(v)
entry.pack()
v.bind("a", lambda a:(entry.config(state="disable"),f_imprimir(),entry.config(state="normal")))
© www.soinside.com 2019 - 2024. All rights reserved.