Python3 show image in a sequence - python

Hello I'm need to show a sequnce of images whe the user make click in a button, I wrote the next code but only show me the las image... any idea what is wrong?
#!/usr/bin/python3
import os
import time
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
class GridWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="NEOTECH")
self.grid = Gtk.Grid()
self.add(self.grid)
self.btnStartTest=Gtk.Button("Iniciar Prueba")
self.btnStartTest.connect("clicked",self.StartTest)
self.image = Gtk.Image()
self.image.set_from_file("logo-NeoTech.png")
self.grid.add(self.btnStartTest)
self.grid.attach(self.image,0,1,1,1)
def StartTest(self,widget):
self.image.set_from_file("gato3.jpg")
time.sleep(2)
self.image.set_from_file("gato4.jpg")
print("fin")
win = GridWindow()
win.set_position(Gtk.WindowPosition.CENTER)
win.set_default_size(1000,480)
win.set_type_hint(Gdk.WindowTypeHint.MENU)
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

Don't use time.sleep() in a GUI program; it blocks the GUI mainloop and makes it unresponsive.
Use GLib.timeout_add instead:
from gi.repository import Gtk, Gdk, GLib
class GridWindow(Gtk.Window):
def StartTest(self,widget):
self.image.set_from_file("gato3.jpg")
GLib.timeout_add(2000, self.show_last_image)
def show_last_image(self):
self.image.set_from_file("gato4.jpg")
print("fin")

Related

GTK4 Window Created From XML Immediately Closes

I create a GTK4 Window from an XML file via Python.
When I run the code, the window actually pops up very briefly (and all controls are there as expected), but then closes immediately. I assume there is something missing in my code, but I can't figure out what it is from the documentation.
import sys
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw
class MyApp(Adw.Application):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.connect('activate', self.on_activate)
def on_activate(self, app):
builder = Gtk.Builder()
builder.add_from_file("main.glade")
self.win = builder.get_object("window")
self.win.present()
app = MyApp(application_id="com.example.GtkApplication")
app.run(sys.argv)
Fixed it :-)
The solution is a simple one-liner:
self.win.set_application(app)

How to poll MPD from GTK with mpd.idle() without blocking

I want to use MPD's idle feature to wait for any changes and then display them in the GTK GUI using Python. The problem is that the GUI seems to block and become unresponsive when I use MPD's idle feature (when changing songs the GTK window becomes unresponsive). When I remove self.mpd.idle() it works, but then the function keeps getting run all the time which I find unnecessary.
What is the best way to solve this?
Not working
My initial approach:
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from mpd import MPDClient
class GUI:
def __init__(self):
self.mpd = MPDClient()
self.mpd.timeout = 10
self.mpd.connect("localhost", 6600)
self.window = Gtk.Window()
self.window.connect("delete-event", Gtk.main_quit)
self.window.show_all()
GLib.idle_add(self.get_current_song)
Gtk.main()
def get_current_song(self):
self.mpd.idle()
print(self.mpd.currentsong())
return True
app = GUI()
Not working
My second approach using this. Still getting the same results.
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from mpd import MPDClient
import threading
class GUI:
def __init__(self):
self.mpd = MPDClient()
self.mpd.timeout = 1
self.mpd.connect("localhost", 6600)
self.window = Gtk.Window()
self.window.connect("delete-event", Gtk.main_quit)
self.window.show_all()
self.thread = threading.Thread(target=self.idle_loop)
self.thread.daemon = True
self.thread.start()
Gtk.main()
def get_songs(self):
print(self.mpd.currentsong())
self.mpd.idle()
return True
def idle_loop(self):
GLib.idle_add(self.get_songs)
app = GUI()
WORKING
Leaving out the GLib.idle_add() function seems to be a solution. But I don't know if this is the "proper" way. It feels wrong not knowing why GLib.idle_add() was messing it up and not using it since it's mentioned in the documentation.
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from mpd import MPDClient
import threading
class GUI:
def __init__(self):
self.mpd = MPDClient()
self.mpd.timeout = 1
self.mpd.connect("localhost", 6600)
self.window = Gtk.Window()
self.window.connect("delete-event", Gtk.main_quit)
self.window.show_all()
self.thread = threading.Thread(target=self.get_songs)
self.thread.daemon = True
self.thread.start()
Gtk.main()
def get_songs(self):
self.mpd.idle()
print(self.mpd.currentsong())
app = GUI()
Let us use the threading module here.
As described in this article : https://pygobject.readthedocs.io/en/latest/guide/threading.html, we can make the following code:
import gi
from threading import Thread
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
from mpd import MPDClient
class GUI:
def __init__(self):
self.mpd = MPDClient()
self.mpd.timeout = 10
self.mpd.connect("localhost", 6600)
self.window = Gtk.Window()
self.window.connect("delete-event", Gtk.main_quit)
self.window.show_all()
thread = Thread(target=self.get_current_song, args=())
thread.start()
Gtk.main()
def get_current_song(self):
self.mpd.idle()
print(self.mpd.currentsong())
return True
app = GUI()

Python: WebKit.WebView: how to reload on error?

I recently asked this question, which was answered. I'm trying exactly the same, but with WebKit.WebView with GTK and I'm stuck at the same part.
Goal: Load another URL if the first isn't reachable.
import gi, time
gi.require_version('Gtk', '3.0')
gi.require_version('WebKit', '3.0')
from gi.repository import Gtk, WebKit
browser = WebKit.WebView()
browser.load_uri('http://this-domain-does-not-exist.tld')
def load_error(webview, event, url, error):
webview.load_uri('http://google.com') # not working
browser.connect('load-error', load_error)
win = Gtk.Window()
win.add(browser)
win.show_all()
Gtk.main()
Any idea? Thanks in advance!
For some reason commands that are run within the error callback are ignored. A fix is to add the fallback uri loading after all other events are processed. Like this:
from gi.repository import Gtk, WebKit, GLib
....
def load_error(webview, event, url, error):
GLib.idle_add(webview.load_uri, 'http://google.com')
I got it working by moving to WebKit2 and returning True in the callback. It's possible that only the return works for WebKit as well but I don't have that available to test. Modified code:
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('WebKit2', '4.0')
from gi.repository import Gtk, WebKit2
browser = WebKit2.WebView()
browser.load_uri('http://this-domain-does-not-exist.tld')
def load_failed(webview, event, url, error):
webview.load_uri('http://google.com')
return True
browser.connect('load-failed', load_failed) # Changed from load-error
win = Gtk.Window()
win.connect("destroy", Gtk.main_quit)
win.add(browser)
win.show_all()
Gtk.main()
From the documentation:
Returns: True to stop other handlers from being invoked for the event. False to
propagate the event further.

Glade 3 imports not working for both gtk and gi

import gtk
class Buglump:
def on_window1_destroy(self, object, data=None):
print "quit with cancel"
gtk.main_quit()
def on_gtk_quit_activate(self, menuitem, data=None):
print "quit from menu"
gtk.main_quit()
def __init__(self):
self.gladefile = "tutorial-1.glade"
self.builder = gtk.Builder()
self.builder.add_from_file(self.gladefile)
self.builder.connect_signals(self)
self.window = self.builder.get_object("window1")
self.window.show()
if __name__ == "__main__":
main = Buglump()
gtk.main()
So I am using this source code to attempt to use the GUI builder glade, however I keep running into many different errors and am doubting if I am even taking the right approach. From my understanding, you generate this code in a different python shell and it will produce whatever you have built in glade. However I keep running into errors, the current one being :
ModuleNotFoundError: No module named 'gtk'
I am seeking guidance of how to move forward using glade, I am very new to python so I apologize if this is not a good question. I can not find any way to use this program from anywhere I have looked online.
In an app in development, I have following below; perhaps you can use something similar.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk, Gdk as gdk, GLib, GObject as gobject

Webkit threads with PyGObject on Gtk3

I am trying to load a webkit view on a different thread than main thread for gtk.
I see the example PyGTK, Threads and WebKit
I slightly modify for support PyGObject and GTK3:
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import WebKit
import threading
import time
# Use threads
Gdk.threads_init()
class App(object):
def __init__(self):
window = Gtk.Window()
webView = WebKit.WebView()
window.add(webView)
window.show_all()
#webView.load_uri('http://www.google.com') # Here it works on main thread
self.window = window
self.webView = webView
def run(self):
Gtk.main()
def show_html(self):
print 'show html'
time.sleep(1)
print 'after sleep'
# Update widget in main thread
GLib.idle_add(self.webView.load_uri, 'http://www.google.com') # Here it doesn't work
app = App()
thread = threading.Thread(target=app.show_html)
thread.start()
app.run()
Gtk.main()
The result it is a empty window and "after sleep" print is never executed. The idle_add call doesn't work. The only work part is the call commented on main thread.
I need GLib.threads_init() before gdk's.
Just like this:
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import WebKit
import threading
import time
# Use threads
GLib.threads_init()
class App(object):
def __init__(self):
window = Gtk.Window()
webView = WebKit.WebView()
window.add(webView)
window.show_all()
#webView.load_uri('http://www.google.com') # Here it works on main thread
self.window = window
self.webView = webView
def run(self):
Gtk.main()
def show_html(self):
print 'show html'
time.sleep(1)
print 'after sleep'
# Update widget in main thread
GLib.idle_add(self.webView.load_uri, 'http://www.google.com') # Here it doesn't work
app = App()
thread = threading.Thread(target=app.show_html)
thread.start()
app.run()
Gtk.main()

Categories