I have an application that show an image.
I want to be able to print the picture, but I can't figure how to send the image to the printer.
I ran into gtk.PrintOperation, but I seen nothing to tell what image file I want to print (so I have a blank page).
Does anyone knows how to set the data to print with pygtk and maybe gtk.PrintOperation?
In gtk.PrintOperation for painting in pages you must connect "draw-page" to a function that get PrintOperation object, a context as a parameter that you can draw page by cairo and pango libraries and page_number as third parameter, and draw pages by this function, similar below:
def print_page(print_dialog, context, n):
ctx = context.get_cairo_context()
img = cairo.ImageSurface.create_from_png("an-image.png")
cr.set_source_surface(img, 20, 20)
cr.paint()
print_dialog = gtk.PrintOperation()
print_dialog.set_default_page_setup(self.print_page_setup)
print_dialog.set_unit(gtk.Unit.POINTS)
print_dialog.set_n_pages(1)
print_dialog.set_export_filename("/path/to/export/file.pdf")
print_dialog.connect("draw-page", print_page)
win = gtk.Window()
win.connect('clicked', lambda widget: print_dialog.run())
win.set_size_request(200, 200)
win.show_all()
gtk.main()
Read more...
Thanks a lot for the hint!
I don't have only PNG images, so I had to adapt the code like this:
def print_page(self,print_dialog, context, n):
ctx = context.get_cairo_context()
gdkcr = gtk.gdk.CairoContext(ctx)
gdkcr.set_source_pixbuf(self.getPixbuf(), 0,0)
gdkcr.paint ()
def print_image(self):
print_dialog = gtk.PrintOperation()
print_dialog.set_n_pages(1)
print_dialog.connect("draw-page", self.print_page)
Thanks again .
Related
I am messing around with the print preview of a QGraphicsView instance in Pyside6. I tried many things, but can't get it right.
def onPreview(self):
printer = QtPrintSupport.QPrinter(QtPrintSupport.QPrinter.HighResolution)
layout = QtGui.QPageLayout()
layout.setOrientation(QtGui.QPageLayout.Landscape)
layout.setPageSize(QtGui.QPageSize.A3)
printer.setPageLayout(layout)
preview = QtPrintSupport.QPrintPreviewDialog(printer, self.parent)
preview.paintRequested.connect(self.handlePaintRequest)
preview.exec_()
# handle paint request
def handlePaintRequest(self, printer):
# render QGraphicsView
self.parent.view.render(QtGui.QPainter(printer))
The snippet works without throwing an error, but the page orientation in the preview is always portrait. Also the page size doesn't work when printing. For sure I handle this in the wrong manner.
I wish to take screenshot of python tkinter window (NOT the entire computer scrren). I applied following codes:
import pyautogui
import tkinter as tk
root= tk.Tk()
# Define tkinter window
canvas1 = tk.Canvas(root, width = 300, height = 300)
canvas1.pack()
# Define fuction to take screenshot
def takeScreenshot ():
myScreenshot = pyautogui.screenshot()
myScreenshot.save('screenshot.png')
# Define fuction to take screenshot
myButton = tk.Button(text='Take Screenshot', command=takeScreenshot, bg='green',fg='white',font= 10)
canvas1.create_window(150, 150, window=myButton)
root.mainloop()
I wish to grab screenshot of only the window defined by "tk.Canvas(root, width = 300, height = 300)"
But, I am capturing the entire screren.
Can somebody please let me know how do we go about this in python ?
You can get the region of the canvas and pass them to screenshot():
def takeScreenshot():
# get the region of the canvas
x, y = canvas1.winfo_rootx(), canvas1.winfo_rooty()
w, h = canvas1.winfo_width(), canvas1.winfo_height()
pyautogui.screenshot('screenshot.png', region=(x, y, w, h))
Since you are on windows you should be able to employ the win32 API,
Contrary to this you could use more simple solutions such as PyScreenshot
Take the following code for example:
from pyscreenshot import grab
im = grab(bbox=(100, 200, 300, 400))
im.show()
“
As you can see you can use bbox to take screenshot that is at co-ordinates (100, 200) and has a width of 300 and a height of 400.
This would require you knowing the position of the windows before hand- which you can do in Tkinter I believe.”
I found this information from previous SO questions. Here is another snippet that may help you.
Here's how you can do it using PIL on win32. Given a window handle (hwnd), you should only need the last 4 lines of code. The preceding simply search for a window with "firefox" in the title. Since PIL's source is available, you should be able to poke around the ImageGrab.grab(bbox) method and figure out the win32 code you need to make this happen.
from PIL import ImageGrab
import win32gui
toplist, winlist = [], []
def enum_cb(hwnd, results):
winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
win32gui.EnumWindows(enum_cb, toplist)
firefox = [(hwnd, title) for hwnd, title in winlist if 'firefox' in title.lower()]
# just grab the hwnd for first window matching firefox
firefox = firefox[0]
hwnd = firefox[0]
win32gui.SetForegroundWindow(hwnd)
bbox = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox)
img.show()
Suggestions I found include:
How to do a screenshot of a tkinter application?
How to Get a Window or Fullscreen Screenshot in Python 3k? (without PIL)
I hope this helps, sometimes all it takes is a good google search. If this help you please select this as the correct answer
Edit
Depending upon the contents of the window you could use this- if it is a drawing.
“ You can either generate a postscript document (to feed into some other tool: ImageMagick, Ghostscript, etc)”
from Tkinter import *
root = Tk()
cv = Canvas(root)
cv.create_rectangle(10,10,50,50)
cv.pack()
root.mainloop()
cv.update()
cv.postscript(file="file_name.ps", colormode='color')
root.mainloop()
Look at this if you are trying to save a drawing https://www.daniweb.com/programming/software-development/code/216929/saving-a-tkinter-canvas-drawing-python
You would need to define the rectangle for the screenshot
instead of myScreenshot = pyautogui.screenshot()
use the following in place of it:
myScreenshot = pyautogui.screenshot(region=(0,0, 300, 400))
The 4 points describe where you want the screenshot
https://pyautogui.readthedocs.io/en/latest/screenshot.html
I'm writing a Gtk program that does stuff with images. I got app window with menu and connected one of the buttons to Gtk.FileChooser that gets a filename (i can open it with Gtk.Image() but cant do much with such object afaik). The problem is I don't know how to pass the filename to my init function so I can open image from that filename using opencv (need to be able to draw with mouse on that image thats why opencv3). Here's the code structure Im using:
class main_win(Gtk.Window):
def __init__(self):
'''menu stuff and box with widgets, few labels'''
def FileChooser(self):
dialog = Gtk.FileChooserDialog("Open a File Image", self, Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
response = dialog.run()
if response == Gtk.ResponseType.OK:
path = dialog.get_filename()
elif response == Gtk.ResponseType.CANCEL:
pass
dialog.destroy()
Ideally I would prefere to put this inside init:
img = cv2.imread(path,0)
cv2.imshow('image',img)
Then afaik i could do stuff with the image in opencv window like for example getting pixel (from a drawn area with mouse or just a single pixel by mouse click) statistics into gtk.label or drawing plots.
Im fairly new to python, so maybe I'm asking sth super easy or super stupid;p
Thanks in advance ;).
Well, maybe you have a legitimate reason for using OpenCV to simply display an image (because for example you use that library elsewhere in your code) but you can use GTK+ 3 facilities for that.
import os, re
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class main_win(Gtk.Window):
def __init__(self):
'''menu stuff and box with widgets, few labels'''
super().__init__(title="Image show")
main_column = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL)
self.add(main_column)
button1 = Gtk.Button(label="Get Image")
button1.connect("clicked", self.FileChooser)
main_column.pack_start(button1, True, True, 0)
self.embedded_image = Gtk.Image()
main_column.pack_start(self.embedded_image, True, True, 0)
def FileChooser(self, widget):
dialog = Gtk.FileChooserDialog("Open a File Image", self, Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
response = dialog.run()
if response == Gtk.ResponseType.OK:
path = dialog.get_filename()
self.embedded_image.set_from_file(path)
self.show_all()
dialog.destroy()
main_windows = main_win()
main_windows.connect("delete-event", Gtk.main_quit)
main_windows.show_all()
Gtk.main()
You can use a Gtk.Image() to put an image anywhere in your interface. You can update it using .set_from_file().
Moved to pyqt4, not only opencv but also matplotlib works there smoothly ;)
I need a little help here.
I have this QTextBrowser where I redirect all stdout to it.
self.console_window = QtGui.QTextBrowser()
self.console_window.setReadOnly(True)
What I need now is to auto scroll to the bottom so I can see what is happening without the need of manually scroll to the bottom.
I tried this
scrollBar = self.console_window.verticalScrollBar()
scrollBar.setValue(scrollBar.maximum())
but is not working.
Any thoughts?
FIXED!!!
def handleOutput(self, text, stdout):
self.console_window.moveCursor(QtGui.QTextCursor.End)
self.console_window.ensureCursorVisible()
self.console_window.insertPlainText(text)
def Console_Window(self):
self.console_window = QtGui.QTextEdit()
self.console_window.setReadOnly(True)
just a quick update in Pyqt5.
i did it bit differently, as i've seen that a delay is needed:
self.scrollbar = self.log_output.verticalScrollBar() #the self.scrollbar is the same as your self.console_window
try:
time.sleep(0.1) #needed for the refresh
self.scrollbar.setValue(10000) #try input different high value
except:
pass #when it is not available
I have a little problem with the following code. It creates a GtkWindow, make it paintable so I can draw on it with cairo on draw events. Then I add a GtkHeaderBar and a simple button widget.
from gi.repository import Gtk
import cairo
def draw_callback(widget,cr):
if widget.transparency:
cr.set_source_rgba(0,0,0,0.5)
else:
cr.set_source_rgb(0,0,0)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
win= Gtk.Window()
win.connect('delete-event', Gtk.main_quit)
win.set_app_paintable(True)
screen = win.get_screen()
visual = screen.get_rgba_visual()
win.transparency = False
if visual and screen.is_composited():
win.set_visual(visual)
win.transparency = True
else:
print('System doesn\'t support transparency')
win.set_visual(screen.get_system_visual)
win.connect('draw', draw_callback)
win.add(Gtk.Button(label='test'))
bar = Gtk.HeaderBar(title='title')
bar.set_has_subtitle(False)
bar.set_show_close_button(True)
win.set_titlebar(bar)
win.show_all()
Gtk.main()
The draw_callback paint the window background but this background looks like this :
It is like the cairo context doesn't have the same size of the window. The part that is draw and that is outside the window doesn't seems to answer to mouse event ( I cannot grab the window from this part for example)
If I don't use an HeaderBar, I don't have this problem.
This works with ruby 2.2 and the Gtk3 bindings.
My python Version is python 3 and the up to date Gtk modules
Edit:
Problem still exist with :
def size_allocation_cb(widget, rectangle):
widget.x = rectangle.x
widget.y = rectangle.y
widget.width = rectangle.width
widget.height = rectangle.height
win.connect('size-allocate', size_allocation_cb)
def draw_callback(widget,cr):
if widget.transparency:
cr.set_source_rgba(0,0,0,0.5)
else:
cr.set_source_rgb(0,0,0)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.rectangle(widget.x, widget.y, widget.width, widget.height)
cr.fill()
cr.set_operator(cairo.OPERATOR_OVER)
When you have a header bar, your window is drawn entirely on the client side, including shadows (for some reason). You will need to call cairo_rectangle() or some other function, preferably with the size allocation (not size request!) of the child of the GtkWindow, to clip cairo_paint() to the correct size.