PyGObject and Glade, dynamically changing icon of a button - python

how could i dynamically change the icon of a button created with glade?
______________________ Last Edit _________________________________________
I'm trying this:
self.button_waiting=self.builder.get_object('button_waiting')
image=Gtk.Image()
image.set_from_stock(Gtk.STOCK_DIALOG_ERROR, Gtk.IconSize.BUTTON)
image.show()
self.button_waiting.remove(image)
self.button_waiting.add(image)
I get this error:
Gtk-CRITICAL **: gtk_container_remove: assertion `gtk_widget_get_parent (widget)
== GTK_WIDGET (container) || GTK_IS_ASSISTANT (container)' failed
(fresh_install:16299): Gtk-WARNING **: Attempting to add a widget with type
GtkImage to a GtkButton, but as a GtkBin subclass a GtkButton can only contain
one widget at a time; it already contains a widget of type GtkLabel
it seems like the error of the answer that I'm copying, but doing what he did is not working for me.
I read that it is possible to put images on labels, how can i get the name of the label of the button made in glade?
following this answer:
replace image using gtk.image.set_from_file
___________________ Original Question _________________________________
I'm trying this:
self.button_waiting=self.builder.get_object('button_waiting')
self.button_waiting.set_label("Cancel")
image=Gtk.Image.set_from_stock(Gtk.STOCK_DIALOG_ERROR, Gtk.ICON_SIZE_BUTTON)
image.show()
self.button_waiting.image.clear()
self.button_waiting.add(image)
I get the following error:
AttributeError: 'gi.repository.Gtk' object has no attribute 'ICON_SIZE_BUTTON'
But i found GTK_ICON_SIZE_BUTTON on the reference manual >.<

I'm going to assume that you are using PyGObject (GTK+ 3.x) based on the fact that you're Gtk instead of gtk. If that's the case, then you should use Gtk.IconSize.BUTTON rather than Gtk.ICON_SIZE_BUTTON.
This is because the GObject Introspection will put the constants into a namespace rather than the long constants we see in the C source code. It's generally pretty easy to figure it out based on the context.

Related

Pillow (PIL Fork): Error when using ImageFont/ImageDraw methods with custom font

After reading through much of the Pillow documentation, stack overflow, and the web, I have been unable to decipher this error message that is throwing off my application. My current setup:
Python 3.7.6
Pillow 7.0.0 [Docs]
Below is a verifiable example of what I have been working on. Essentially, my error happens when I use title_font in place of where I use default_font. Emphasized by the 2 comments stating: # TODO Aborts with error unless using default_font TODO.
from PIL import ImageFont, ImageDraw, Image
def app():
# Default Font with static size and font type
default_font = ImageFont.load_default()
# TODO Title Font that is the desired use
title_font = ImageFont.truetype(font="~/Library/Fonts/Verdana.ttf", size=36)
# Background Image to draw text on
bg_img = Image.new(mode = "RGBA",size = (3480,2160), color="Green")
# Creates an object that can be used to draw in the given image.
d = ImageDraw.Draw(bg_img)
txt = "Hello World"
# TODO: Aborts with error unless using default_font TODO
# Returns (width, height) of text in pixels with designated font
txt_width, txt_height = default_font.getsize(txt)
print(f"Text Width:{txt_width} Text Height: {txt_height}")
# TODO: Aborts with error unless using default_font TODO
# Draws "Hello World" onto background image
d.text((10,60), text=txt, font=default_font, fill=(255,255,255,255))
# Pop Up window
bg_img.show()
Below is the error message that I get back from both ImageDraw/ImageFont methods:
>>> app()
dyld: lazy symbol binding failed: Symbol not found: _hb_language_get_default
Referenced from: /usr/local/lib/libraqm.dylib
Expected in: flat namespace
dyld: Symbol not found: _hb_language_get_default
Referenced from: /usr/local/lib/libraqm.dylib
Expected in: flat namespace
I have already tried:
To change the path used for the custom font and to change to another font loading method (i.e. ImageFont.load(filename), ImageFont.load_path(filename).
To settle with ImageFont.load_default() but as you might be able to tell by running it, the default font is very small and there is no way of changing its size or style.
One last thing that I was not sure about was this line in the installation guide that recommended after brew install of the packages Pillow depends on:
Then see depends/install_raqm_cmake.sh to install libraqm.
Can be found here halfway through the Building on macOS section. I have a nagging feeling this could be the cause but I simply do not understand what action it wants me to take.
Long time lurker, first time poster. Thank you for any help now and all the help afforded to me over the years!
UPDATE: Used my example on another MacBook and it works fine. I am going to reset the one it wasn't working on and build from scratch. Thanks for all your assistance!
I assume you used (like me) a Mac with OS Catalina or similar, and might have installed the mentioned library with "$ brew install libraqm" too.
I resolved it by changing the layout_engine, and due to this, not using 'libraqm' for PIL layout work in the background.
font = ImageFont.truetype(
"/System/Library/Fonts/Keyboard.ttf", layout_engine=ImageFont.LAYOUT_BASIC, encoding=self.encoding, self.font_size,)
If you do this you might not be able to use Chinese or similar Fonts. I am not sure where, in 'brew', 'pyenv' or 'libraqm' is the issue but I try to find it out.

Reopen window throws Gtk-CRITICAL **: gtk_widget_get_window: assertion 'GTK_IS_WIDGET (widget)' failed

I have simple python3 + gtk3 code, which connects to dbus and listen for all events. When user click on icon in tray, he must see window with all showed earlier events. Code(I don't know where is problem and code size > 100 lines): https://github.com/rakshazi/notify-feed/blob/master/main.py
How to reproduce:
Run python main.py L117
Click on app icon in tray - will be opened window, it can be empty or with some items if any notifications was shown after run. L83
Close window. L93
Retry step #2, you will see empty window (without any element in all cases, yes, it is bug, but doesn't matter for this question)
Click on window body and app will be crashed:
(gui.py:4882): Gtk-CRITICAL **: gtk_widget_get_window: assertion 'GTK_IS_WIDGET (widget)' failed
[1] 4882 segmentation fault (core dumped) python gui.py
On first windowOpen event and on second windowOpen event self.window object is <__main__.Window object at 0x7f98b1dcd7e0 (__main__+Window at 0x1502260)>
gdb result:
(main.py:17310): Gtk-CRITICAL **: gtk_widget_get_window: assertion 'GTK_IS_WIDGET (widget)' failed
Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007fffea5cd0b8 in gtk_widget_translate_coordinates () from /usr/lib/libgtk-3.so.0
Please, explain to me how to debug and fix this problem.
PS: I'm new to Python, that's why this problem may be stupid.
Lesson 1: Never assume bugs are unrelated
Lesson 2: GTK events are confusing.
The reason you get this error is because the window is actually deleted in you close it in step 3, therefor all the widgets in the window become orphans (they have no parent) and are therefor cleaned. The second time you open the window in step 4 the window only contains references to deleted widgets causing your segmentation fault.
The solution is surprisingly simple just add return True to closeWindow this will let GTK know the event has been handle and that it should not perform the default action of closing the window (that you already hide).
Another elegant solution might be to use hide_on_delete function. For example in Rust (easily rewritten to Python):
my_window.connect_delete_event(move |_win,_| {
_win.hide_on_delete()
});

Accessing QT combo and textbox values

I'm using Python 3 and QT4 with pyqt. I've been unable to access data from qcomboboxes and qplaintextedits.
I've read the documentation here:
http://doc.qt.io/qt-4.8/qcombobox.html
http://doc.qt.io/qt-4.8/qplaintextedit.html
The only thing on these pages that appears to describe how to pull the selected value are 'plainText' for the plain text box and 'currentText'for the combo box. These aren't explicitly described as the solution, but they're the only thing I found that makes sense.
currentText returns the following error: "AttributeError: 'QPlainTextEdit' object has no attribute 'plainText' "
currentText does not return an error, but returns the starting value of the combo box, regardless of what's selected.
Example code I'm using:
x = window.ui.tb_x.plainText()
y = window.ui.cb_y.currentText()
Any ideas?
Its toPlainText() method in qplaintextedit.
And try itemData( combo.currentIndex ) for combo.

How to show a png image in Gtk3 with Python?

First of all, it is important to mention that I'm learning Python and Gtk+ 3, so I'm not an advanced programmer in these languages.
I'm trying to make a graphical interface in Gtk3 for a Python script that creates a png image, and I'd like to display it, but the PyGobject documentation is so scarce that I haven't found a way to do that. So far, my interface looks like this:
The buttons and text entries are arranged in a grid, and I'd like to keep empty the big space (represented by the big button) to the right until the script finishes building the image, and then show it in that area. The code is here.
Is there a way to do that using Python in Gtk3?
Thanks in advance,
Germán.
EDIT
Taking a look at the demos pointed out by #gpoo I discovered the Frame widget, and I implemented it in my GUI. This is how it looks like:
Inside the window class, I add the Frame to the grid:
self.frame_rgb = Gtk.Frame(label='RGB image')
self.frame_rgb.set_label_align(0.5, 0.5)
self.frame_rgb.set_shadow_type(Gtk.ShadowType.IN)
self.grid.attach_next_to(self.frame_rgb, self.label_img_name,
Gtk.PositionType.RIGHT, 3, 8)
I also connect the Run button to a callback function, so that when I click on it, my script creates and then displays the png image:
self.button_run = Gtk.Button(stock=Gtk.STOCK_EXECUTE)
self.button_run.connect('clicked', self.on_button_run_clicked)
self.grid.attach_next_to(self.button_run, self.entry_b_img,
Gtk.PositionType.BOTTOM, 1, 1)
Finally, my callback function is (no calculations yet, only render the image to the Frame for testing purposes):
def on_button_run_clicked(self, widget):
self.img = Gtk.Image.new_from_file('astro-tux.png')
self.frame_rgb.add(self.img)
but I got the following error when I click the Run button:
(makeRGB.py:2613): Gtk-WARNING **: Attempting to add a widget with
type GtkImage to a GtkFrame, but as a GtkBin subclass a GtkFrame can
only contain one widget at a time; it already contains a widget of
type GtkImage
Any help is appreciated!
You can use Gtk.Image. If you generate a file, you could use:
img = Gtk.Image.new_from_file('/path/to/my_file.png')
and add img to the container (GtkGrid in your case). Or, if you already have the Gtk.Image there, you can use:
img.set_from_file('/path/to/my_file.png')
Instead of ...from_file you can use from_pixbuf, and you can create a Gdk.Pixbuf from a stream.
In general, you can use the documentation for C and change the idiom to Python. Also, you can check the demos available in PyGObject, in particular, the demo for handling images.

PyGTK set icon of window with stock image

I feel like this should be pretty simple, but I guess I am missing something.
So I want to set the icon of a window with one of the stock images. I have tried:
windowIcon = gtk.image_new_form_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_MENU)
window.set_icon(windowIcon.get_pixbuf())
Python then complains that:
File "./sample.py", line 44, in init
window.set_icon(windowIcon.get_pixbuf())
ValueError: image should be a GdkPixbuf or empty
I try to convert the gtkImage to a GdkPixbuf because when I didn't python complained that
TypeError: icon should be a GdkPixbuf or None
In the pygtk documentation it says:
If the storage type of the image is not either gtk.IMAGE_EMPTY or gtk.IMAGE_PIXBUF the ValueError exception will be raised.
So I guessing that storage type of the stock image is wrong. The question is how to I get around this?
You can use the .render_icon() method on any GtkWidget to provide a stock item as the icon.
windowicon = window.render_icon(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_MENU)
window.set_icon(windowicon)
The render_icon() method works as given above. Your code was having problems, because the get_pixbuf() method was returning None. This is because the image was not created from a pixbuf, and for some reason, it won't convert it. Another way of getting a pixbuf from an image is to use the gtk.gdk.pixbuf_new_from_image() function.

Categories