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 ;)
Related
I drew a GUI in Qt Creator, with a button, a slider and some labels.
What I am trying: when the button is pressed, print on terminal and in a label the modified value of the slider and display an image. As many webpages suggested, I am trying to display an image into a label by using the pixmap method. This is my whole code (the structure of the GUI is in the imported mainwindow.ui file)
import sys
from PyQt4 import QtCore, QtGui, uic
qtCreatorFile = "mainwindow.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class myownGUI(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
#button
self.Do_button.clicked.connect(self.action)
#slider
self.SLIDER.valueChanged[int].connect(self.SLIDER_update)
#"global" variable init. by callback
self.SLIDER_update()
#The button callback
def action(self):
print "DOING ACTION!"
print self.Slider
#trying to display the image in the Image_label
image = QtGui.QImage(QtGui.QImageReader(":/images/test.png").read())
self.Image_label.setPixmap(QtGui.QPixmap(image))
#self.Image_label.show() #unuseful command?
#Slider update callback
def SLIDER_update(self):
self.Slider= self.SLIDER.value()
if (self.Slider % 2 == 0): #even
self.Slider = self.Slider + 1
self.Slider_label.setText(str(self.Slider))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = myownGUI()
window.show()
sys.exit(app.exec_())
The code runs, it shows no error but the image is not displayed.
I tried both JPG and PNG images. I tried also the simple image name, when the image is in the same folder.
What is wrong in my code?
There is another way to display images in QT inside the GUI (with python) ?
Thank you in advance
Working with: Ubuntu 14.04 / Qt version 4.8.6
I try to read all similar questions in stack overflow. It seems that my question is duplicated, but none of the answers seems to resolve my problem.
EDIT: Using PRMoureu's syntax it works also when the image is the same folder, like
image = QtGui.QImage(QtGui.QImageReader("./test.png").read())
Now the image is displayed and have only to be rescaled.
You should call the image with another path syntax :
image = QtGui.QImage(QtGui.QImageReader("./images/test.png").read())
or
image = QtGui.QImage(QtGui.QImageReader("images/test.png").read())
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 .
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.
I have successfully created a python GTK application using Gobject Introspection, and opened a source file in a GTKSourceView Widget.
I am attempting to scroll to place a specific line (line 150) into the center of the screen when the user clicks a button.
I have read how to (programmatically) scroll to a specific line in gtktextview/gtksourceview
and also the documentation surrounding GtkSourceViews, GTKTextView, and the buffer objects for both of these (it is my understanding that the sourceview inherits from the textview)
I have attempted to use the following methods:
-getting an iterator at line 150, and then using the scroll_to_iter() method
- getting an iterator at line 150, making a mark at the iterator, and then using the scroll_to_mark() method
I know the iterators and marks are correct, because i can successfully use the place_cursor(iter) method and it successfully places the marker at the end of line 150, however either scrolling to the mark or the iterator using the given methods does nothing.
The scroll to mark method does not return a value, but the iterator method is returning false.
Can anyone please suggest a way to achieve this?
My testing code is as follows:
from gi.repository import Gtk
from gi.repository import GObject
from gi.repository import GtkSource
class MyApplication (Gtk.Window):
def __init__(self, *args, **kwargs):
Gtk.Window.__init__(self, *args, **kwargs)
self.set_title("SourceView Test")
self.set_size_request(400, 400)
self.connect("destroy", Gtk.main_quit)
self.create_widgets()
self.show_all()
def create_widgets(self):
self.sourceview=GtkSource.View.new()
self.lm = GtkSource.LanguageManager.new()
self.scrolledwindow = Gtk.ScrolledWindow()
vbox = Gtk.VBox()
self.add(vbox)
vbox.pack_start(self.scrolledwindow,True,True,0)
self.scrolledwindow.add_with_viewport(self.sourceview)
self.scrolledwindow.show_all()
button = Gtk.Button("Jump To Line")
button.connect("clicked", self.scroll_to_line_and_mark)
self.open_file_in_srcview("/home/tel0s/source_android/system/core/adb/adb.c")
vbox.pack_start(button, False, False, 5)
def open_file_in_srcview(self,filename,*args,**kwargs):
self.buffer = self.sourceview.get_buffer()
self.filename = filename
self.language = self.lm.guess_language(self.filename,None)
self.sourceview.set_show_line_numbers(True)
if self.language:
self.buffer.set_highlight_syntax(True)
self.buffer.set_language(self.language)
else:
print 'No language found for file "%s"' % self.filename
self.buffer.set_highlight_syntax(False)
txt = open(self.filename).read()
self.buffer.set_text(txt)
self.buffer.place_cursor(self.buffer.get_start_iter())
def scroll_to_line_and_mark(self,*args,**kwargs):
print "setting iterator"
iterator = self.sourceview.get_buffer().get_iter_at_line(150)
print iterator
print "scrolling to iter"
if self.sourceview.scroll_to_iter(iterator,0, False, 0.5, 0.5):
print "done!"
else:
print "scrolling failed!!"
if __name__ == "__main__":
MyApplication()
Gtk.main()
So the issue is the line:
self.scrolledwindow.add_with_viewport(self.sourceview)
According to the Gtk docs for scrolledwindow objects, you should only use add_with_viewport for objects that don't support scrolling. For those that do natively like GtkTextView (and so by inheritance GtkSourceView), you should use GtkContainer.add()...
Hope that helps
I've got a small PyGTK program, that has a statusicon. Upon left click on the statusicon a window with a TextView should appear and a predefined text should be shown in the TextView widget. My problem is that I don't know how to pass the text to shown as a parameter to the method that creates the window. I can create the window with a TextView without problems, but I cannot insert text into it.
Here's my code:
import gtk
import keybinder
class PyPPrinter(object):
def __init__(self):
self.staticon = gtk.StatusIcon()
self.staticon.set_from_stock(gtk.STOCK_INDEX)
self.staticon.set_visible(True)
self.staticon.connect('activate', self.browser(output_text = 'text'))
gtk.main()
def browser(self, window, output_text):
browser = gtk.Window()
browser.set_usize(600, 500)
textbox = gtk.TextView()
text = gtk.TextBuffer()
text.set_text(output_text)
textbox.set_buffer(text)
browser.add(textbox)
browser.show_all()
if __name__ == '__main__':
PyPPrinter()
This code gives me an exception: TypeError: browser() takes exactly 3 arguments (2 given). Perhaps I should also pass a value for the window parameter, but what should it be?
Two variants:
Change connect part:
self.staticon.connect('activate', self.browser(output_text = 'text'))
to:
self.staticon.connect('activate', self.browser, 'text')
or change Handler-Signature:
def browser(self, window, output_text):
to:
def browser(self, window):