2010-09-28 6 views
1

J'écris un client de chatroom dans wxPython dans lequel il y a 3 wx.HtmlWindows pour chatroom sur une page de bloc-notes: un pour les messages, un pour le titre de la pièce et un pour le sujet de la pièce (deux choses similaires)wxPython - HtmlWindow se bloque lors du chargement des images

Le programme fonctionne bien, charge les images lorsque les images sont dans le code du message, etc. Mais quand il doit soudainement charger un tas d'images à la fois, ou une image animée qui prend plus de temps pour charger, ou une combinaison (les images sont généralement juste 50x50 - 100x100) cela peut être un problème car parfois il se verrouille et le programme ne répond pas car cela prend trop de temps. La question posée est la suivante: comment empêcherais-je le blocage? Je ne sais pas comment lier le chargement de l'image de wx.HtmlWindow pour que les images se chargent dynamiquement dans un thread de travail au lieu que le programme doive attendre le chargement des images pour continuer.

Si vous avez besoin d'un exemple de code de ce que j'écris, faites le moi savoir.

EDIT: J'ai toujours du mal à trouver une réponse à cette question. Je n'ai littéralement pas trouvé d'endroit pour ce projet. mon application doit être capable de charger dynamiquement des messages/images sans le verrouiller et je ne sais pas comment forcer le chargement de l'image dans un thread différent pour que les images des images et les messages soient affichés, tandis que le thread du chargeur charge les images et met à jour les images vides une fois terminé. Tout cela doit se produire dans une HtmlWindow. Je veux qu'il agisse comme un vrai navigateur web quand il s'agit de charger des images (vous voyez les images et les images apparaissent lentement)

Répondre

0

Les processus longs bloquent la boucle principale de votre application, ce qui la rend "bloquante" ". Vous devrez effectuer le téléchargement dans un fil séparé, puis mettre à jour votre interface utilisateur lorsque cela sera terminé. Voici quelques liens sur l'utilisation de threads (et d'autres méthodes) qui pourraient vous aider:

http://wiki.wxpython.org/LongRunningTasks

http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/

+0

cela ne l'aide pas vraiment car il ne sait pas où se lier pour les images chargées. –

+0

Je sais déjà comment utiliser les threads Je ne savais pas trop comment obtenir la fenêtre pour faire le chargement de l'image dans un thread différent à la place. Merci bien – Blazer

+0

Je pensais que vous pouviez télécharger les images avec le fil, puis utiliser PubSub ou PostEvent pour dire à votre application de l'afficher. –

0

En plus de la réponse de Mike (ce qu'il dit applique), vous pouvez brancher en une image étant chargé en remplaçant la méthode OnOpeningURL à partir de HTMLWindow et en spécifiant le type de wx.html.HTML_URL_IMAGE.

Voir: these wx docs pour une explication.

+0

Merci! Savez-vous comment faire en sorte que wxHtmlWindow ajoute un cadre vide à la place des images pendant le chargement de la page, puis la met à jour une fois le chargement terminé? De cette façon, les messages ne seraient pas mélangés à partir du moment où ils sont réellement reçus (un message sans image qui a été réellement reçu après qu'un message avec une image apparaisse en premier, gâcher l'ordre, par exemple) – Blazer

+0

Hmm, I ' Je ne suis pas sûr, désolé. Je n'ai pas utilisé wx.HtmlWindow –

0

Vous voudrez peut-être essayer la nouvelle fonctionnalité de la dernière version de développement de wxPython?

Vous devez d'abord vous assurer que vous avez téléchargé et installé la dernière version. Vous pouvez le trouver ici, sous la rubrique « version de développement »: http://www.wxpython.org/download.php

Ceci est un exemple simple qui fonctionne avec la dernière wxPython (v2.9) version de développement:

import wx 
import wx.html2 

class MyBrowser(wx.Dialog): 
    def __init__(self, *args, **kwds): 
    wx.Dialog.__init__(self, *args, **kwds) 
    sizer = wx.BoxSizer(wx.VERTICAL) 
    self.browser = wx.html2.WebView.New(self) 
    sizer.Add(self.browser, 1, wx.EXPAND, 10) 
    self.SetSizer(sizer) 
    self.SetSize((700, 700)) 

if __name__ == '__main__': 
    app = wx.App() 
    dialog = MyBrowser(None, -1) 
    dialog.browser.LoadURL("http://www.google.com") 
    dialog.Show() 
    app.MainLoop() 

J'espère que cela résout votre problème , faites le moi savoir.

0

Steven Sproat était sur la bonne voie (pour moi kudos mettre là-dessus - ne aurait pu le faire sans votre suggestion) - est ici sont les bits pertinents d'une solution complète:

import wx.html as html 
import urllib2 as urllib2 
import os 
import tempfile 
import threading 
from Queue import Queue 

class HTTPThread(threading.Thread): 
    def __init__(self, urlQueue, responseQueue): 
     threading.Thread.__init__(self) 
     self.urlQueue = urlQueue 
     self.responseQueue = responseQueue 

    def run(self): 
     # add error handling 
     url = self.urlQueue.get() 
     request = urllib2.Request(url) 
     response = urllib2.urlopen(request) 
     page = response.read() 
     self.responseQueue.put(page) 

Et en votre classe dérivée de html.HtmlWindow:

def OnOpeningURL(self, type, url): 
    if type == html.HTML_URL_IMAGE: 
     # If it is a tempfile already, just tell it to open it. 
     # Since it will be called again 
     # immediately after first failure only need to keep the last 
     # temp file within the object, and the former is closed! 
     if self.f is not None and self.f.name in url: 
      return html.HTML_OPEN 
     # if its not a tempfile, download asynchronously and redirect 
     urlq = Queue() 
     resq = Queue() 
     t = HTTPThread(urlq, resq) 
     t.start() 
     urlq.put_nowait(url) 
     while True: 
      if resq.empty(): 
       # your task while waiting 
       time.sleep(0.1) 
      else: 
       img = resq.get() 
       break 
     self.f = tempfile.NamedTemporaryFile() 
     self.f.write(img) 
     self.f.seek(0) 
     return 'file://' + self.f.name 
    else: 
     return html.HTML_OPEN 

Pour ma demande cela fonctionne très bien, mais si vous voulez vraiment avoir la charge d'images « comme un navigateur Web standard » alors vous allez avoir besoin de plus d'une wx.html.HtmlWindow. Cependant, ceci n'est pas bloquant et chargera correctement les images.

Questions connexes