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).
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.
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()
As #furas pointed out in the comments, constantly drawing a black rectangle on the DrawingArea works very well. I use the following code inside a widget that derives from Gtk.DrawingArea:
def draw(self, c, *args):
rect = self.get_allocation()
win = self.get_window().get_position()
c.set_source_rgb(0, 0, 0)
c.rectangle(rect.x - win.x, rect.y - win.y, rect.width, rect.height)
c.fill()
self.connect("draw", draw)
Edit: See #furas answer for an even simpler approach.
Related
When trying to get the example python libvlc binding to to run, I get the following error:
ModuleNotFoundError: No module named 'evaluator'
Here is what I did:
sudo apt-get install vlc
sudo apt-get install python3-pip
pip3 install python-vlc
Download example for gtkvlc.py as gtkvlc.py and run
python3 gtkvlc.py /path/to/video.mp4
The offending lines are
from evaluator import Evaluator
e = Evaluator(globals(), locals())
e.popup()
How can I get this evaluator?
EDIT: removing the offending lines still leave the application working. What are these lines for?
I think you are running an old code of gtkvlc.py, try this code it is tested and work very well for Python3 and GTK3
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.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 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()
So I want to have my small Python Gtk window have 2 switches. When one switch is ON, the other is turned OFF, and vice versa. I am not too sure how to control both switches. If anyone can lead me in the right direction, it'd be much appreciated.
#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class SwitcherWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Alt Switch Demo")
self.set_border_width(10)
hbox = Gtk.Box(spacing=10)
self.add(hbox)
switch1 = Gtk.Switch()
switch1.connect("notify::active", self.on_switch_activated)
switch1.set_active(True)
hbox.pack_start(switch1, True, True, 0)
switch2 = Gtk.Switch()
switch2.connect("notify::active", self.on_switch_activated)
switch2.set_active(False)
hbox.pack_start(switch2, True, True, 0)
if switch1.get_active():
switch2.set_active(False)
else:
switch2.set_active(True)
def on_switch_activated(self, switch, gparam):
builder = Gtk.Builder()
sw1 = builder.get_object("switch1")
sw2 = builder.get_object("switch2")
if switch.get_active():
state = "on"
sw2.set_active(False)
else:
state = "off"
print("Switch was turned", state)
win = SwitcherWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
I would bind the properties of both switches, inverted and sync'ed on creation:
#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
class SwitcherWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Alt Switch Demo")
self.set_border_width(10)
hbox = Gtk.Box(spacing=10)
self.add(hbox)
switch1 = Gtk.Switch()
switch1.set_active(True)
hbox.pack_start(switch1, True, True, 0)
switch2 = Gtk.Switch()
switch2.set_active(False)
hbox.pack_start(switch2, True, True, 0)
switch1.bind_property("active", switch2, "active", GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN)
win = SwitcherWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
The solution resides on this line of code:
switch1.bind_property("active", switch2, "active", GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.INVERT_BOOLEAN)
Here you bind the "active" property of switch1 and switch2 with the binding flags: bidirectional, sync on create and invert boolean
You can implement a similar logic to what I wrote:
#!/usr/bin/env python
class Switch:
_State = False
def __init__(self, StartingPosition=False):
self._State = StartingPosition
def SwitchON(self):
self._State = True
def SwitchOFF(self):
self._State = False
def Switch(self):
self._State = not self._State
def GetInfo(self):
print(self._State)
class Switcher:
def __init__(self, switchDependencyList=[]):
self.SwitchDependencyList = switchDependencyList
if len(self.SwitchDependencyList) == 0:
return None
if not len(self.SwitchDependencyList) % 2:
return None
def SwitchByIndex(self, Index):
for i, switch in enumerate(self.SwitchDependencyList):
if i == Index:
switch.SwitchON()
else:
switch.SwitchOFF()
def GetInfo(self):
for switch in self.SwitchDependencyList:
switch.GetInfo()
sw1 = Switch()
sw2 = Switch()
SwitcherModule = Switcher([sw1, sw2])
SwitcherModule.SwitchByIndex(1)
SwitcherModule.GetInfo()
No need for anything as complex as the prelisted answers. gtk already has a radiobutton widget that does it all for you. Only thing is that when it is initialised you have no buttons set, so you have to pick one to set.
I'd like to get the current background color of my textview to change it and restore it later.
here what I tried:
context = textview.get_style_context()
state = Gtk.StateFlags.NORMAL
color = context.get_background_color(state)
I tried all possible states, but none returns the correct background color (white in my case)
Any idea how to get it?
I'm not exactly sure what you specific problem is without seeing more code, but here is a quick example that overrides the background and then restores it on a button click:
from gi.repository import Gtk, Gdk
import sys
class MyWindow(Gtk.ApplicationWindow):
def __init__(self, app):
Gtk.Window.__init__(self, title="Textview example", application=app)
self.set_default_size(250, 100)
self.set_border_width(10)
self.view = Gtk.TextView()
self.style_context = self.view.get_style_context()
self.default_bg_color = self.style_context.get_background_color(Gtk.StateFlags.NORMAL)
self.view.override_background_color(Gtk.StateFlags.NORMAL,
Gdk.RGBA(0, 0, 0, 1))
self.btn = Gtk.Button(label="Click Here")
self.btn.connect("clicked", self.on_btn_clicked)
box = Gtk.VBox()
box.pack_start(self.view, True, True, 0)
box.pack_start(self.btn, False, False, 0)
self.add(box)
def on_btn_clicked(self, widget):
current_bg = self.style_context.get_background_color(Gtk.StateFlags.NORMAL)
if current_bg == self.default_bg_color:
self.view.override_background_color(Gtk.StateFlags.NORMAL,
Gdk.RGBA(0, 0, 0, 1))
else:
self.view.override_background_color(Gtk.StateFlags.NORMAL,
self.default_bg_color)
class MyApplication(Gtk.Application):
def __init__(self):
Gtk.Application.__init__(self)
def do_activate(self):
win = MyWindow(self)
win.show_all()
def do_startup(self):
Gtk.Application.do_startup(self)
app = MyApplication()
exit_status = app.run(sys.argv)
sys.exit(exit_status)
I've got a gtk.Expander object, containing in its label a gtk.HBox, which packed a gtk.Image and a gtk.Label.
I want to launch a Webbrowser when the HBox is right-clicked.
Here is my code:
def launchBrowser(widget, host, event):
print event
print host
if event.type == gtk.gdk.BUTTON_PRESS:
if event.button == 3:
webbrowser.open(host, 1)
print "right click"
def addServer(self, loginfo):
main_expand = gtk.Expander()
main_led = gtk.Image()
if int(loginfo["main"]) == 0:
main_led.set_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_BUTTON)
else:
main_led.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_BUTTON)
main_srvname = gtk.Label(loginfo["srvname"])
expand_title = gtk.HBox(False, 2)
expand_title.pack_start(main_led, False, True, 0)
expand_title.pack_start(main_srvname, True, True, 0)
main_srvname.add_events(gtk.gdk.BUTTON_PRESS_MASK)
main_srvname.connect_object('event', self.launchBrowser, loginfo["host"])
main_srvname.emit('event', gtk.gdk.Event(gtk.gdk.BUTTON_PRESS_MASK))
main_expand.set_property("label-widget", expand_title)
Problem is that when I pass my cursor on this HBox, I correctly received the event. But when I clicked nothing happen. I think it's because the click event is intercept by the Expander.
Anyhelp is welcome =)
Thanks in advance!
EDIT:
I also tried that:
main_srvname = gtk.Label(loginfo["srvname"])
eventbox = gtk.EventBox()
eventbox.add(main_srvname)
eventbox.connect_object('button-press-event', self.launchBrowser, loginfo["host"])
# Titre de l'expand box
expand_title = gtk.HBox(False, 2)
expand_title.pack_start(main_led, False, True, 0)
expand_title.pack_start(eventbox, True, True, 0)
Not working either...
EDIT2:
As requested by Jeremy, here a self-contained code, just copy-paste it you lazyboy!
import pygtk
pygtk.require('2.0')
import gtk
class MainWindow(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.set_default_size(300, 300)
self.addServer()
def launchBrowser(widget, host, event):
print event
if event.type == gtk.gdk.BUTTON_PRESS:
if event.button == 3:
print "click"
def addServer(self):
main_expand = gtk.Expander()
main_led = gtk.Image()
main_led.set_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_BUTTON)
main_srvname = gtk.Label("srvname")
main_srvname.add_events(gtk.gdk.BUTTON_PRESS_MASK)
main_srvname.connect_object('button-press-event', self.launchBrowser, "host")
expand_title = gtk.HBox(False, 2)
expand_title.pack_start(main_led, False, True, 0)
expand_title.pack_start(main_srvname, True, True, 0)
main_expand.set_property("label-widget", expand_title)
self.add(main_expand)
self.show_all()
def main():
MainWindow()
gtk.main()
if __name__ == '__main__':
main()
Small change in your code.
Add "button-press-event" on Expander widget instead of Label widget
import pygtk
pygtk.require('2.0')
import gtk
class MainWindow(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.set_default_size(300, 300)
self.addServer()
def launchBrowser(self, widget, event, host, *args):
if event.type == gtk.gdk.BUTTON_PRESS:
if event.button == 3:
print "click"
# Normal behaviour of Expander on single click
expand = widget.get_expanded()
if not expand: widget.set_expanded(True)
else: widget.set_expanded(False)
def addServer(self):
main_expand = gtk.Expander()
main_led = gtk.Image()
main_led.set_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_BUTTON)
main_srvname = gtk.Label("srvname")
main_expand.add_events(gtk.gdk.BUTTON_PRESS_MASK)
main_expand.connect('button-press-event', self.launchBrowser, 'host')
expand_title = gtk.HBox(False, 2)
expand_title.pack_start(main_led, False, True, 0)
expand_title.pack_start(main_srvname, True, True, 0)
main_expand.set_property("label-widget", expand_title)
self.add(main_expand)
self.show_all()
def main():
MainWindow()
gtk.main()
if __name__ == '__main__':
main()
I have a program that opens numerous other programs.
How can I combine the code from the other programs into this code so that instead of 10 sets of code i will only have one?
Code for app that I want to put all the codes in:
import pygtk
pygtk.require('2.0')
import gtk
import subprocess
class Example:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(600, 600)
window.set_title("GTK Menu")
window.connect("delete_event",
lambda w,e: gtk.main_quit())
# Add Vbox so that we can have numerous widgets
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
#Adding a status bar
self.statusbar = gtk.Statusbar()
vbox.pack_start(self.statusbar, False, False, 0)
#Adding 5 buttons one for each of the activities
button = gtk.Button("Write")
button.connect("clicked", self.clicked_Write)
vbox.pack_end(button, True, True, 2)
button.show()
button2 = gtk.Button("Draw")
button2.connect("clicked", self.clicked_Scrible)
vbox.pack_end(button2, True, True, 2)
button2.show()
button3 = gtk.Button("Final Test")
button3.connect("clicked", self.clicked_Final)
vbox.pack_end(button3, True, True, 2)
button3.show()
button4 = gtk.Button("Helloworld")
button4.connect("clicked", self.clicked_Hello)
vbox.pack_end(button4, True, True, 2)
button4.show()
button5 = gtk.Button("Facebook")
button5.connect("clicked", self.clicked_Facebook)
vbox.pack_end(button5, True, True, 2)
button5.show()
button6 = gtk.Button("SpinButtons")
button6.connect("clicked", self.clicked_Spin)
vbox.pack_end(button6, True, True, 2)
button6.show()
button7 = gtk.Button("Calendar")
button7.connect("clicked", self.clicked_Cal)
vbox.pack_end(button7, True, True, 2)
button7.show()
button8 = gtk.Button("Colour Wheel(click popup)")
button8.connect("clicked", self.clicked_Wheel)
vbox.pack_end(button8, True, True, 2)
button8.show()
button9 = gtk.Button("Choose File")
button9.connect("clicked", self.clicked_File)
vbox.pack_end(button9, True, True, 2)
button9.show()
button10 = gtk.Button("Word Completer")
button10.connect("clicked", self.clicked_Word)
vbox.pack_end(button10, True, True, 2)
button10.show()
window.show_all()
def clicked_Write(self, widget):
# push a new message to the statusbar, using context_id 0
self.statusbar.push(0, "You have oppened Write")
subprocess.Popen(["python", "Helloworld.py"])
def clicked_Scrible(self, widget):
self.statusbar.push(0, "You have opened the Drawind Pad")
subprocess.Popen(["python", "scrible.py"])
def clicked_Final(self, widget):
self.statusbar.push(0, "You have opened the Final Exam")
subprocess.Popen(["python", "Final.py"])
def clicked_Hello(self, widget):
self.statusbar.push(0, "You have opened Helloworld")
subprocess.Popen(["python", "Helloword.py"])
def clicked_Facebook(self, widget):
self.statusbar.push(0, "You have opened Facebook")
subprocess.Popen(["python", "facebookfinal.py"])
def clicked_Spin(self, widget):
self.statusbar.push(0, "You have opened the Spin Buttons App")
subprocess.Popen(["python", "SpinButtons.py"])
def clicked_Cal(self, widget):
self.statusbar.push(0, "You have opened the Calender")
subprocess.Popen(["python", "Calender.py"])
def clicked_Wheel(self, widget):
self.statusbar.push(0, "You have opened the Colour Wheel")
subprocess.Popen(["python", "colour.py"])
def clicked_File(self, widget):
self.statusbar.push(0, "You have opened File Chooser")
subprocess.Popen(["python", "filechooser.py"])
def clicked_Word(self, widget):
self.statusbar.push(0, "You have opened the Word Completer")
subprocess.Popen(["python", "finisher.py"])
def main(self):
gtk.main()
return 0
Example().main()
Here is the code for one of the programmes I open
Colour.py
import pygtk
pygtk.require('2.0')
import gtk
class ColorSelectionExample:
# Color changed handler
def color_changed_cb(self, widget):
# Get drawingarea colormap
colormap = self.drawingarea.get_colormap()
# Get current color
color = self.colorseldlg.colorsel.get_current_color()
# Set window background color
self.drawingarea.modify_bg(gtk.STATE_NORMAL, color)
# Drawingarea event handler
def area_event(self, widget, event):
handled = False
# Check if we've received a button pressed event
if event.type == gtk.gdk.BUTTON_PRESS:
handled = True
# Create color selection dialog
if self.colorseldlg == None:
self.colorseldlg = gtk.ColorSelectionDialog(
"Select background color")
# Get the ColorSelection widget
colorsel = self.colorseldlg.colorsel
colorsel.set_previous_color(self.color)
colorsel.set_current_color(self.color)
colorsel.set_has_palette(True)
# Connect to the "color_changed" signal
colorsel.connect("color_changed", self.color_changed_cb)
# Show the dialog
response = self.colorseldlg.run()
if response -- gtk.RESPONSE_OK:
self.color = colorsel.get_current_color()
else:
self.drawingarea.modify_bg(gtk.STATE_NORMAL, self.color)
self.colorseldlg.hide()
return handled
# Close down and exit handler
def destroy_window(self, widget, event):
gtk.main_quit()
return True
def __init__(self):
self.colorseldlg = None
# Create toplevel window, set title and policies
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Color selection test")
window.set_resizable(True)
# Attach to the "delete" and "destroy" events so we can exit
window.connect("delete_event", self.destroy_window)
# Create drawingarea, set size and catch button events
self.drawingarea = gtk.DrawingArea()
self.color = self.drawingarea.get_colormap().alloc_color(0, 65535, 0)
self.drawingarea.set_size_request(200, 200)
self.drawingarea.set_events(gtk.gdk.BUTTON_PRESS_MASK)
self.drawingarea.connect("event", self.area_event)
# Add drawingarea to window, then show them both
window.add(self.drawingarea)
self.drawingarea.show()
window.show()
def main():
gtk.main()
return 0
if __name__ == "__main__":
ColorSelectionExample()
main()
Put the files in the same directory, then use something like:
from Colour import ColorSelectionExample
then to run it, construct a ColorSelectionExample:
ColorSelectionExample()