I'm making a Gtk.Window using PyGi Gtk3 and It adds an annoying border around widgets and the main window:
The border is this grey border between the two images and in the outside of the window. Anyone knows how to completely remove it? So the two images could be seamless joint together.
This is my code:
#!/usr/bin/python3
#encoding:utf-8
from gi.repository import Gtk, Gdk
class TestMainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Test Window")
self.set_resizable(False)
self.box = Gtk.Box(orientation='vertical')
self.add(self.box)
self.album_cover = Gtk.Image()
self.album_cover.set_from_file('../reference/album-cover.jpg')
self.box.pack_start(self.album_cover, True, True, 0)
self.album_cover2 = Gtk.Image()
self.album_cover2.set_from_file('../reference/album-cover.jpg')
self.box.pack_end(self.album_cover2, True, True, 0)
def main():
win = TestMainWindow()
win.connect('delete-event', Gtk.main_quit)
win.show_all()
Gtk.main()
if __name__ == '__main__':
main()
Give a try at setting the "margins" property inherited from GtkWidget to FALSE. In C this is done using g_object_set.
Related
When I have, for instance the following widget hierarchy:
Window
Box
Drawing Area 1
Drawing Area 2
and I call queue_draw on Drawing Area 1 then also Drawing Area 2 is updated (draw). Is this behavior intended and can I prevent this and only update Drawing Area 1, because of performance reasons.
Edit: Added a minimal example:
#!/usr/bin/env python3
import pgi
pgi.require_version('Gtk', '3.0')
from pgi.repository import Gtk, Gdk, GdkPixbuf
import cairo
class DrawingArea(Gtk.DrawingArea):
def __init__(self, id):
super().__init__()
self.id = id
self.vexpand = True
self.hexpand = True
self.connect("draw", self.on_draw)
def on_draw(self, area, context):
print ("on_draw ", self.id)
context.set_source_rgb (1, 0, 0)
context.rectangle (0,0,20,20)
context.fill ()
return False
class Window(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_title("Test Draw Radial Gradient")
self.set_default_size(400, 200)
self.connect("destroy", Gtk.main_quit)
self.drawingArea1 = DrawingArea (1)
self.drawingArea2 = DrawingArea (2)
box = Gtk.Box ()
box .pack_start (self.drawingArea1, True, True, 0)
box .pack_start (self.drawingArea2, True, True, 0)
button = Gtk.Button.new_with_label("Click Me")
box .pack_start (button, True, True, 0)
button.connect("clicked", self.on_click_me_clicked)
self.add(box)
def on_click_me_clicked(self, button):
print ("Button clicked")
self.drawingArea1.queue_draw()
window = Window()
window.show_all()
Gtk.main()
Unless I misunderstand Gtk source, it's some kind of intended behaviour. queue_draw leads to invalidation of part of window and it recursively updates widgets. Most likely (it's just guesses!) it tells box to be redrawn and box redraws all of it's children.
Anyway, your widgets should be always ready to be redrawn. If user resizes window -- it's many redraws. If he minimizes and brings window back -- it's another redraw.
First of all, make sure your redraw is a real bottleneck. Second, I'd suggest implementing some kind of caching or proxy: a cairo surface of the same size as widget, when your data changes you draw it there and on redraw you just paint that surface on widget's surface. Another approach would be preparing drawables in another thread (which is questionable if you use python), but again: start with some measurements and find out if redraw is really slow.
How can I add a new widget from a callback function within a class? For example, I have a Gtk.Box and Gtk.Button and I want to add Gtk.Label to the Gtk.Box from callback function connected to button click. (this code doesn't work)
import gi
import os
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk, GObject, Gio
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Delete Screenshots")
self.main_grid = Gtk.Grid()
self.main_grid.set_row_homogeneous(True)
self.add(self.main_grid)
self.screen_label = Gtk.Label()
self.screen_label.set_text("Test Label")
self.screen_label2 = Gtk.Label()
self.screen_label2.set_text("Test Label2")
self.label_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.label_box.homogeneous = True
self.button_search = Gtk.Button(label="Search")
self.button_search.connect("clicked", self.on_button_search_clicked)
self.button_delete = Gtk.Button(label="Delete")
self.button_delete.connect("clicked", self.on_button_delete_clicked)
self.main_grid.add(self.button_search);
self.main_grid.attach(self.button_delete, 1, 0, 1, 1);
self.main_grid.attach(self.label_box, 0, 1, 1, 1)
def on_button_search_clicked(self, widget):
self.label_box.pack_start(self.screen_label, True, True, 0)
def on_button_delete_clicked(self, widget):
print("Delete")
win = MainWindow()
win.set_default_size(50, 30)
win.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
How to add something to label_box from on_button_search_clicked?
Your code is basically correct. However all widgets need to be shown by either calling show() on them or show_all() on a parent widget. In your code, show_all() is called on the MainWindow instance. At that time, the widget you are adding in your callback is not attached to the window or any of its children. It will thus not be included in the show_all() call.
To fix this, simply call show() on your label in the callback:
...
def on_button_search_clicked(self, widget):
self.label_box.pack_start(self.screen_label, True, True, 0)
self.screen_label.show()
...
I'm writing a simple paint like application:
#!/usr/bin/env python3
from gi.repository import Gtk
class Application(Gtk.Window):
def __init__(self):
super().__init__(Gtk.WindowType.TOPLEVEL, title='paint')
self.connect('destroy', self.__on_destroy)
vbox = Gtk.VBox()
drawing_area = Gtk.DrawingArea()
drawing_area.conenct('draw', self.__on_draw)
vbox.pack_start(drawing_area, True, True, 2)
self.add(vbox)
self.show_all()
def __on_draw(self, widget, g):
g.set_source_rgb(200, 0, 0)
g.move_to(16, 0)
g.line_to(16, 32)
g.stroke()
def save_to_file(self, filename):
# How to get pixels from drawing_area?
pass
def __on_destroy(self, e):
Gtk.main_quit()
app = Application()
Gtk.main()
Now I want to save user drawing. How can I access pixels inside Gtk.DrawingArea widget?
Quote from this following SO link
Gtk.DrawingArea derives from Gtk.Window.Hence you can use
Gdk.pixbuf_get_from_window() to get the contents of the drawing area
into a GdkPixbuf.Pixbuf and then use the GdkPixbuf.Pixbuf.savev()
function to write the pixbuf as an image on disk.
You can follow the link for complete code.Also this link can also help you.
I'm working on a transparent window which includes a DrawingArea widget, which gets on top with a solid background color, but I want to keep it transparent. I've tried everything, unfortunately the docs are a bit dated (with PyGTK on the top results). Other things I've done is connecting its draw event as I'm doing it with the window, but with no success.
Of course I need the square to be shown, so I just need the background color to transparent. I've also tried with modify_bg, but I only manage to set it to solid colors.
Here's what I have so far.
#!/usr/bin/env python
from gi.repository import Gtk, Gdk
import cairo
class GWin (Gtk.Window):
def __init__(self):
super(GWin, self).__init__()
self.set_position(Gtk.WindowPosition.CENTER)
self.screen = self.get_screen()
self.visual = self.screen.get_rgba_visual()
if self.visual != None and self.screen.is_composited():
self.set_visual(self.visual)
self.connect("draw", self.on_win_draw)
self.set_app_paintable(True)
self.show_all()
self.draw_area = Gtk.DrawingArea()
self.draw_area.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
self.draw_area.connect('draw', self.begin_draw)
self.draw_area.show()
self.add(self.draw_area)
def begin_draw(self, draw_area, cairo_context):
cairo_context.rectangle(20, 20, 120, 120)
cairo_context.stroke()
def on_win_draw(self, widget, cr):
cr.set_source_rgba(1, 1, 1, 0.1)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
win = GWin()
win.connect('delete-event', Gtk.main_quit)
Gtk.main()
You need to set the cairo.Context source rgba before creating the rectangle. Here is the code, the edited line marked with ### ADDED THIS LINE:
#!/usr/bin/env python
from gi.repository import Gtk, Gdk
import cairo
class GWin (Gtk.Window):
def __init__(self):
super(GWin, self).__init__()
self.set_position(Gtk.WindowPosition.CENTER)
self.screen = self.get_screen()
self.visual = self.screen.get_rgba_visual()
if self.visual != None and self.screen.is_composited():
self.set_visual(self.visual)
self.connect("draw", self.on_win_draw)
self.set_app_paintable(True)
self.show_all()
self.draw_area = Gtk.DrawingArea()
self.draw_area.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
self.draw_area.connect('draw', self.begin_draw)
self.draw_area.show()
self.add(self.draw_area)
def begin_draw(self, draw_area, cairo_context):
cairo_context.set_source_rgba(1, 1, 1, 1) ### ADDED THIS LINE
cairo_context.rectangle(20, 20, 120, 120)
cairo_context.stroke()
def on_win_draw(self, widget, cr):
cr.set_source_rgba(1, 1, 1, 0.1)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
win = GWin()
win.connect('delete-event', Gtk.main_quit)
Gtk.main()
I can Add boxs and Tables
Also the Quit button does not work can someone edit that part of the code please
import gtk
class helloworld:
def close(self,widget):
print "I'm outta here"
gtk.main_quit()
def printit(self,widget,lab1):
print lab1.get_text()
def filllab(self,widget,lab1):
lab1.set_text(widget.get_text())
def __init__(self):
window = gtk.Window()
window.set_size_request(300,400)
vbox = gtk.VBox()
window.add(vbox)
lab1 = gtk.Label("shazbut")
# entry widget
ent1 = gtk.Entry()
ent1.connect("activate",self.filllab,lab1)
# quit
quitb = gtk.Button("quit",gtk.STOCK_QUIT)
quitb.set_size_request(50,100)
quitb.connect("destroy", gtk.main_quit)
printb = gtk.Button("print")
printb.connect("clicked",self.printit,lab1)
# Pack widgets in the vbox
vbox.add(ent1)
vbox.add(lab1)
vbox.add(quitb)
vbox.add(printb)
window.show_all()
helloworld()
gtk.main()
The "quit" button doesn't work because you connected the "destroy" signal to the button instead of the clicked signal
quitb.connect("clicked", gtk.main_quit)
Also, you forgot to connect the window destroy event (so the program will never exit when you click the window close button). Add
window.connect("destroy", gtk.main_quit)
To change the label properties use the pango attributes
def _add_attributes_to_label(self,label):
attr = pango.AttrList()
fg_color = pango.AttrForeground(65535, 0, 0,0,-1)
strike = pango.AttrStrikethrough(True,0,-1)
size = pango.AttrSize(30000, 0, -1)
attr.insert(fg_color)
attr.insert(size)
attr.insert(strike)
label.set_attributes(attr)
In your init function call the previous function like this:
self._add_attributes_to_label(lab1)
Follow this tutorial to know more about pango attributes.