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.
Related
I have an application (actually a plugin for another application) that presents a GTK notebook. Each tab contains a technical drawing of an operation, with a set of SpinButtons that allow you to alter the dimensions of the operation.
If you need more context, it's here: https://forum.linuxcnc.org/41-guis/26550-lathe-macros?start=150#82743
As can be seen above, this all worked fine in GTK2. The widgets (first iteration in a GTK_Fixed, then moved to a GTK_Table) were pre-positioned and the image (a particular layer of a single SVG) was plonked in behind.
Then we updated to GTK3 (and Python 3) and it stopped working. The SVG image now appears on top of the input widgets, and they can no-longer be seen or operated.
I am perfectly happy to change the top level container[1], if that will help. But the code that used to work (and now doesn't) is:
def on_expose(self,nb,data=None):
tab_num = nb.get_current_page()
tab = nb.get_nth_page(tab_num)
cr = tab.get_property('window').cairo_create()
cr.set_operator(cairo.OPERATOR_OVER)
alloc = tab.get_allocation()
x, y, w, h = (alloc.x, alloc.y, alloc.width, alloc.height)
sw = self.svg.get_dimensions().width
sh = self.svg.get_dimensions().height
cr.translate(0, y)
cr.scale(1.0 *w / sw, 1.0*h/sh)
#TODO: gtk3 drawing works, but svg is drawn over the UI elements
self.svg.render_cairo_sub(cr = cr, id = '#layer%i' % tab_num)
[1] In fact I will probably go back to GTK_Fixed and move the elements about in the handler when the window resizes, scaled according to the original position. The GTK_Table (deprecated) version takes over 2 minutes to open in the Glade editor.
Unless there is a more elegant way to do this too?
I am using the IPython module in a Jupyter Notebook.
I am using the display module to display buttons.
from ipywidgets import widgets
import IPython.display as dsply
def click_reset(b):
print("reset domains button")
restoreDomains()
resetButton = widgets.Button(description="Reset Domains")
resetButton.on_click(click_reset)
dsply.display(resetButton)
This works fine, but I am trying to find a way to programatically hide certain buttons. Based off the execution of my other code, I want certain buttons to be removed from the UI. Is there anything like hide(resetButton) that I can use?
You can hide a widget using
resetButton.layout.visibility = 'hidden'
to let the widget still consume space, or
resetButton.layout.display = 'none'
to let the widget not consume space anymore.
The top-level attribute resetButton.visible = False is not longer supported.
When I use #SergeyGornostaev's answer, I still have a residual cross showing up on the left side of the cell output. I found the following command removes the widget all together:
resetButton.close()
You can hide every widget by setting it's property visible to False
resetButton.visible = False
I came across a function to insert image in a gtk dialog box. but there is some issue with it and not working.
messagedialog = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_OK,\
message_format="Congratulations..!!")
messagedialog.set_image('scoreimg') #line 3
action_area = messagedialog.get_content_area()
lbl2=gtk.Label("Awesome")
action_area.pack_start(lbl2)
messagedialog.show_all()
messagedialog.run()
messagedialog.destroy()
The code is not working due to #line 3. Yes, the image is available to this code.
I guess, set_image is used to set background of a dialog box. I want to add some images in dialog box (not background this time).
Also, I am trying to eliminate the "bulb" from the dialog that appears based on type=gtk.MESSAGE_INFO though I need an "OK" button.
Any idea about how I can proceed with this?
here is Gtk3, which is basically the same.
messagedialog = Gtk.MessageDialog (None, Gtk.DialogFlags.MODAL, Gtk.MessageType.INFO,\
Gtk.ButtonsType.OK, "Congratulations..!!")
""" Assume you have it """
scoreimg = Gtk.Image ()
scoreimg.set_from_file ("yourpathhere") #or whatever its variant
messagedialog.set_image (scoreimg) #without the '', its a char
action_area = messagedialog.get_content_area()
lbl2=Gtk.Label("Awesome")
action_area.add(lbl2)
messagedialog.show_all()
messagedialog.run()
messagedialog.destroy()
A note: "set-image" property override the bulb icon (from gnome-hicolor)
Is there a way to add an icon to a Gtk.ToolButton (Gtk3 using PyGi for Python) to add to the GTK+3 toolbar ?
Below is my code:
self.addfile = Gtk.ToolButton()
self.addfile.set_label("Add File")
self.addfileimg = Gtk.Image()
self.addfileimg.show()
self.addfileimg.set_from_file(self.get_resource("img/file.png"))
self.addfile.set_icon_widget(self.addfileimg)
self.addfile.connect("clicked", self.on_open_file)
Note: The get_resource() method digs into the local working folder for the resource path and this method is assumed working in this context.
I tried the code written above using PyGi. The image file is valid and everything is working but the image doesn't appear.
There is a method of the GtkToolButton class named set_icon_widget, taking a GtkWidget instance as its operand. GtkImage is a container that holds an image. Thus:
myToolButton.set_icon_widget(myImageWidget)
OK, so iv almost completed my program for my project but I cant get a BUTTON_EVT to work which if i am honest should be the easiest thing todo. I have the buttons on my program which represent the hardware and I have created a def function for them to appear on the OGL canvas.
Problem has been solved... The code associated with the problem is found in the answer below
Edited from your last comment. Use this (using your own images):
def OnClickRouter(self, event):
image=wx.Image('cat.jpg', wx.BITMAP_TYPE_JPEG)
self.frame = bucky(None, image)
self.frame.Show()
If you call bucky() this way you must also fix the class signature:
class bucky(wx.Frame):
# Creating the outer window/frame
def __init__(self, parent, image=None):
wx.Frame.__init__(self, parent, -1,'Karls Network Tool', size=(900,700))
my_image = image if image else wx.Image("myself.bmp", wx.BITMAP_TYPE_BMP)
''''''''''''''''''''''''''''''''
# Button images
buttonOneRouter = my_image.ConvertToBitmap()
self.buttonOneRouter = wx.BitmapButton(panel, -1, buttonOneRouter, pos=(20,340))
self.buttonOneRouter.Bind(wx.EVT_BUTTON, self.OnClickRouter)
''''''''''''''''''''''''''''''''
Then you can see that after clicking the buttonOnerouter what actually you are doing is opening a new frame. The left figure is what I get when I run the program, the right one is after I click and enter again my name (I simplified a bit your code. Thats why you only see one button at the bottom instead of 4):
If you want to put my cat in the canvas instead of in the button there is still some work to do. I recommend to you to give a look at the wxPython demo. In the miscellaneous group of examples you have one called OGL that shows how to do that.
Edit: You can download the wxPython docs and demos package from here
I don't know if this is right or not but I suggest you to take this approach and see if it works or not.
Modify your frame class as:
def __init(self,parent,id,img=None)
def onClickRouter(self,event):
image=wx.Image('router.jpg', wx.BITMAP_TYPE_JPEG)
temp = image.ConvertToBitmap()
self.bmp = wx.StaticBitmap(parent=self, bitmap=temp)
self.frame=bucky(self.bmp)
Please let know the outcome.