Search code examples
pythonpython-3.xgtk3pygtkpython-vlc

GtkDrawingArea gets messed up when resized


I'm working on a GTK+ frontend for libvlc in python using python-vlc. So far I followed this guide, which is working fine, except that when I resize the window, the DrawingArea gets messed up as you can see in the picture (there's probably a word for that phenomenon I don't know).


Messed up GtkDrawingArea


I'm getting these warnings in the console, but am not sure if this is related:

[00007fce1c014eb0] main filter error: Failed to create video converter
[00007fce2807ff70] vdpau_avcodec generic error: Xlib is required for VDPAU

I already tried setting the background color of the window using the css styling for GTK+ but it had no effect.

I think this should not happen, am I missing something? I'm on wayland by the way.


Solution

  • Using Google and checking different examples I created code which fills background in DrawingArea with black color.

    Assign drawing function to DrawingArea

    self.draw_area = Gtk.DrawingArea()
    self.draw_area.connect("draw", self.da_draw_event)
    

    Function which fills area

    def da_draw_event(self, widget, cairo_ctx):
        cairo_ctx.set_source_rgb(0, 0, 0)
        cairo_ctx.paint()
    

    Full code

    import sys
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk
    gi.require_version('GdkX11', '3.0')
    from gi.repository import GdkX11
    
    import vlc
    
    MRL = ""
    
    class ApplicationWindow(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self, title="Python-Vlc Media Player")
            self.player_paused=False
            self.is_player_active = False
            self.connect("destroy", Gtk.main_quit)
    
        def show(self):
            self.show_all()
    
        def setup_objects_and_events(self):
            self.playback_button = Gtk.Button()
            self.stop_button = Gtk.Button()
    
            self.play_image = Gtk.Image.new_from_icon_name(
                    "gtk-media-play",
                    Gtk.IconSize.MENU
                )
            self.pause_image = Gtk.Image.new_from_icon_name(
                    "gtk-media-pause",
                    Gtk.IconSize.MENU
                )
            self.stop_image = Gtk.Image.new_from_icon_name(
                    "gtk-media-stop",
                    Gtk.IconSize.MENU
                )
    
            self.playback_button.set_image(self.play_image)
            self.stop_button.set_image(self.stop_image)
    
            self.playback_button.connect("clicked", self.toggle_player_playback)
            self.stop_button.connect("clicked", self.stop_player)
    
            self.draw_area = Gtk.DrawingArea()
            self.draw_area.set_size_request(300, 300)
            self.draw_area.connect("realize",self._realized)
            self.draw_area.connect("draw", self.da_draw_event)
    
            self.hbox = Gtk.Box(spacing=6)
            self.hbox.pack_start(self.playback_button, True, True, 0)
            self.hbox.pack_start(self.stop_button, True, True, 0)
    
            self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
            self.add(self.vbox)
            self.vbox.pack_start(self.draw_area, True, True, 0)
            self.vbox.pack_start(self.hbox, False, False, 0)
    
        def da_draw_event(self, widget, cairo_ctx):
            #print('da_draw_event')
            #print('widget:', widget)
            #print('cairo_ctx:', cairo_ctx)
    
            cairo_ctx.set_source_rgb(0, 0, 0)
            cairo_ctx.paint()
    
        def stop_player(self, widget, data=None):
            self.player.stop()
            self.is_player_active = False
            self.playback_button.set_image(self.play_image)
    
        def toggle_player_playback(self, widget, data=None):
    
            """
            Handler for Player's Playback Button (Play/Pause).
            """
    
            if self.is_player_active == False and self.player_paused == False:
                self.player.play()
                self.playback_button.set_image(self.pause_image)
                self.is_player_active = True
    
            elif self.is_player_active == True and self.player_paused == True:
                self.player.play()
                self.playback_button.set_image(self.pause_image)
                self.player_paused = False
    
            elif self.is_player_active == True and self.player_paused == False:
                self.player.pause()
                self.playback_button.set_image(self.play_image)
                self.player_paused = True
            else:
                pass
    
        def _realized(self, widget, data=None):
            self.vlcInstance = vlc.Instance("--no-xlib")
            self.player = self.vlcInstance.media_player_new()
            win_id = widget.get_window().get_xid()
            self.player.set_xwindow(win_id)
            self.player.set_mrl(MRL)
            self.player.play()
            self.playback_button.set_image(self.pause_image)
            self.is_player_active = True
    
    if __name__ == '__main__':
        if not sys.argv[1:]:
           print("Exiting \nMust provide the MRL.")
           sys.exit(1)
        if len(sys.argv[1:]) == 1:
            MRL = sys.argv[1]
            window = ApplicationWindow()
            window.setup_objects_and_events()
            window.show()
            Gtk.main()
            window.player.stop()
            window.vlcInstance.release()