在 Tkinter 中打开打印机选择 window
Open printer selection window in Tkinter
我遇到问题可能是因为我缺乏知识。我想打开 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 完成时,打印机选择器关闭时可能会发生这种情况,我打算将条目的状态更改为 "normal"。
但是当将条目的状态更改为 "normal" 时它会抛出错误,我想这是因为 window 和我发送的订单在不同的进程中。错误将是:
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
有没有人有这个问题的解决方案或创建打印 window 而不阻止 TCL window 并且能够阻止条目的替代方法?如果有办法做到这一点或使用 Tkinter 发送打印并避免这种混乱,那就更好了。谢谢。
我不使用 wxPython 但是你的错误是由于与 tkinter 相关的线程问题。 Tkinter 喜欢在主线程中,尝试将小部件传递到单独的线程可能会导致问题。但是,您的输入字段已经在全局命名空间中,因此您无需传递它。
只需在需要时从您的线程更新即可。
我会在你的 if/else
条件下这样做,所以它只会在正确的时间发生。
像这样的东西会起作用:
请注意,您实际上需要对传递的值执行某些操作。现在 none 您的代码实际上会打印空白页以外的任何内容。
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()
我遇到问题可能是因为我缺乏知识。我想打开 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 完成时,打印机选择器关闭时可能会发生这种情况,我打算将条目的状态更改为 "normal"。 但是当将条目的状态更改为 "normal" 时它会抛出错误,我想这是因为 window 和我发送的订单在不同的进程中。错误将是:
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
有没有人有这个问题的解决方案或创建打印 window 而不阻止 TCL window 并且能够阻止条目的替代方法?如果有办法做到这一点或使用 Tkinter 发送打印并避免这种混乱,那就更好了。谢谢。
我不使用 wxPython 但是你的错误是由于与 tkinter 相关的线程问题。 Tkinter 喜欢在主线程中,尝试将小部件传递到单独的线程可能会导致问题。但是,您的输入字段已经在全局命名空间中,因此您无需传递它。
只需在需要时从您的线程更新即可。
我会在你的 if/else
条件下这样做,所以它只会在正确的时间发生。
像这样的东西会起作用: 请注意,您实际上需要对传递的值执行某些操作。现在 none 您的代码实际上会打印空白页以外的任何内容。
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()