2009-07-20 3 views
2

Ma tentative précédente de poser cette question était horrible et j'avais aussi fait quelques progrès, s'il vous plaît gardez avec moi, je n'avais pas l'intention de le répéter tant de fois et ce n'est pas mon style. Voici la version finale: Je redimensionne une fenêtre qui contient un bitmap peint DC Client et sur l'événement EVT_SIZE, je le redimensionne en le redimensionnant (en utilisant l'échelle, pas en redimensionnant) et en re-peignant l'image . Le problème est qu'il ne semble pas qu'il respecte le rapport d'aspect même si je calcule w/h pour cela. Aussi, quand il grandit en hauteur, l'image est déformée. Enfin, lorsqu'une autre fenêtre passe dessus, l'image devient blanche. Des idées pour résoudre ces problèmes? Ma classe de fenêtre/image est ci-dessous:wxPython - Redimensionnement d'une image avec l'événement EVT_SIZE de son panneau parent

class TransactionImage(wx.Window): 
    def __init__(self, parent, fname, name): 
     wx.Window.__init__(self, parent, name=name) 

     self.dc = wx.ClientDC(self) 

     self.load_image(fname) 
     cursor = wx.StockCursor(wx.CURSOR_MAGNIFIER) 
     self.SetCursor(cursor) 

     self.Bind(wx.EVT_SIZE, self.resize_space) 


    def load_image(self, image): 
     self.image = wx.Image(image, wx.BITMAP_TYPE_JPEG) 
     (w, h) = self.image.GetSize() 
     self.image_ar = w/h 

    def resize_space(self, size): 
     (w, h) = self.get_best_size() 
     self.s_image = self.image.Scale(w, h) 
     self.bitmap = wx.BitmapFromImage(self.s_image) 
     self.dc.DrawBitmap(self.bitmap, 0, 0, useMask=False) 
     # how can I 'refresh this area to make it 'fit' 

    def get_best_size(self): 
     (window_width, window_height) = self.GetSizeTuple() 
     new_height = window_width/self.image_ar 
     new_size = (window_width, new_height) 
     return new_size 

En outre, j'ai de la difficulté à comprendre comment utiliser correctement le client DC. Je veux rafraîchir la zone de la fenêtre avant de redessiner l'image suivante, parce que si je ne reçois pas de risiduels bizarres et ça a l'air mauvais. Afin de résoudre ce problème, j'ai essayé d'utiliser dc.Clear qui nettoie l'arrière-plan. Cependant, faire cela à chaque appel de taille, car je devrais faire clignoter l'image un million de fois tout en redimensionnant. Comment puis-je éviter ça?

EDIT -

En réponse à la réponse de commentaire de Umyal - est une version très simplifiée de ma demande ici. De toute façon, je classer mon générateur de fenêtre pour les images du gestionnaire de taille redimensionner les images provoque l'image scintille mal, créant un artefact peu attrayant. De même, lorsqu'une autre image passe au-dessus de l'application, l'affichage de l'image devient blanc, comme s'il avait été effacé. Je pensais comme un moyen de contourner cela - je pourrais implémenter la solution que l'utilisateur de l'image semble avoir, c'est-à-dire que l'image n'est redimensionnée et repeinte que lorsque l'utilisateur lâche le bord du cadre lors du redimensionnement. Le problème avec cette solution est qu'il n'y a aucun moyen clair de détecter quand l'utilisateur arrête de redimensionner le cadre. (wxEVT_SIZE, wxEVT_SIZING)

Voici le code de l'application simplifiée, vous aurez besoin de trouver vos propres images et le plus grand sera le mieux. Les dimentions de l'image originale sont 3872 x 2592

# this is required for 'real' math - derive the 'aspect ratio' 
from __future__ import division 
import wx 

class TransactionImage(wx.Window): 
    def __init__(self, parent, fname, name): 
     wx.Window.__init__(self, parent, name=name) 

     self.load_image(fname) 
     cursor = wx.StockCursor(wx.CURSOR_MAGNIFIER) 
     self.SetCursor(cursor) 

     self.Bind(wx.EVT_SIZE, self.resize_space) 
     self.Bind(wx.EVT_PAINT, self.on_paint) 

    def load_image(self, image): 
     self.image = wx.Image(image, wx.BITMAP_TYPE_JPEG) 
     (w, h) = self.image.GetSize() 
     self.image_ar = w/h 
     self.bitmap = wx.BitmapFromImage(self.image) 

    def resize_space(self, event): 
     (w, h) = self.get_best_size() 
     self.s_image = self.image.Scale(w, h) 
     self.bitmap = wx.BitmapFromImage(self.s_image) 

    def on_paint(self, event): 
     self.dc = wx.PaintDC(self) 
     self.dc.DrawBitmap(self.bitmap, 0, 0, useMask=False) 

    def get_best_size(self): 
     (window_width, window_height) = self.GetSizeTuple() 
     new_height = window_width/self.image_ar 
     new_size = (window_width, new_height) 
     return new_size 


class OriginalTransactionImage(wx.Window): 
    def __init__(self, parent, fname, name): 
     wx.Window.__init__(self, parent, name=name) 

     self.dc = wx.ClientDC(self) 

     self.load_image(fname) 
     cursor = wx.StockCursor(wx.CURSOR_MAGNIFIER) 
     self.SetCursor(cursor) 

     self.Bind(wx.EVT_SIZE, self.resize_space) 


    def load_image(self, image): 
     self.image = wx.Image(image, wx.BITMAP_TYPE_JPEG) 
     (w, h) = self.image.GetSize() 
     self.image_ar = w/h 

    def resize_space(self, size): 
     (w, h) = self.get_best_size() 
     self.s_image = self.image.Scale(w, h) 
     self.bitmap = wx.BitmapFromImage(self.s_image) 
     self.dc.DrawBitmap(self.bitmap, 0, 0, useMask=False) 

    def get_best_size(self): 
     (window_width, window_height) = self.GetSizeTuple() 
     new_height = window_width/self.image_ar 
     new_size = (window_width, new_height) 
     return new_size 


class ImageBrowser(wx.Frame): 

    def __init__(self, image1, image2, parent=None, id=wx.ID_ANY, 
       pos=wx.DefaultPosition, title='Image Browser'): 
     size = (1500, 800) 
     wx.Frame.__init__(self, parent, id, title, pos, size) 

     self.CentreOnScreen() 

     self.panel = wx.Panel(self, wx.ID_ANY) 
     self.panel.SetBackgroundColour(wx.Colour(191,197,229)) 

     self.main_sizer = wx.BoxSizer(wx.VERTICAL) 

     self.image_panel = wx.Panel(self.panel, wx.ID_ANY, style=wx.SIMPLE_BORDER) 
     self.image_panel.SetBackgroundColour(wx.Colour(255, 255, 255)) 

     self.image_sizer = wx.BoxSizer(wx.HORIZONTAL) 
     self.image_panel.SetSizer(self.image_sizer) 

     self.load_image_sizer(image1, image2) 
     self.main_sizer.Add(self.image_panel, 1, wx.GROW|wx.ALIGN_CENTER|wx.ALL, 25) 
     self.panel.SetSizer(self.main_sizer) 


    def load_image_sizer(self, image1, image2): 
     #bitmap1 = OriginalTransactionImage(self.image_panel, image1, 'image1') 
     #bitmap2 = OriginalTransactionImage(self.image_panel, image2, 'image2') 

     bitmap1 = TransactionImage(self.image_panel, image1, 'image1') 
     bitmap2 = TransactionImage(self.image_panel, image2, 'image2') 

     self.image_sizer.Add(bitmap1, 1, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 20) 
     self.image_sizer.Add(bitmap2, 1, wx.GROW|wx.ALIGN_RIGHT|wx.ALL, 20) 


class IBApp(wx.App): 

    def OnInit(self): 
     img1 = "0_3126_image1.jpeg" 
     img2 = "0_3126_image2.jpeg" 

     ib = ImageBrowser(img1, img2) 
     ib.Show() 
     self.SetTopWindow(ib)   
     return True 

app = IBApp(False, None) 
app.MainLoop() 

Répondre

1

Ne pas conserver une référence au client DC dans votre instance de fenêtre (http://docs.wxwidgets.org/2.6/wx_wxclientdc.html), ni est la bonne façon de tirer sur la fenêtre dc

lier au lieu de PAINT_EVENT et dessinez là, ci-dessous j'ai montré les choses que vous avez dites ajouter à votre classe

class TransactionImage(wx.Window): 
    def __init__(self, parent, fname, name): 

     self.Bind(wx.EVT_SIZE, self.resize_space) 
     self.Bind(wx.EVT_PAINT, self.onpaint) 

    def onpaint(self): 
     dc = wx.PaintDC(self) 
     dc.DrawBitmap(self.bitmap, 0, 0, useMask=False) 

    def resize_space(self, size): 
     (w, h) = self.get_best_size() 
     self.s_image = self.image.Scale(w, h) 
     self.bitmap = wx.BitmapFromImage(self.s_image) 
     self.Refresh() 
+0

Ceci est un mauvais conseil pour plusieurs raisons. Tout d'abord, ma façon de le faire ne pouvait pas être «totalement faux», car après quelques tests, j'ai trouvé que c'était vraiment mieux que le code que vous avez fourni. Deuxièmement, il ne traite pas les problèmes que je mentionne, à savoir, que l'événement de taille et de repeindre provoque l'image à clignoter constamment, un effet secondaire peu attrayant. En outre, l'image devient blanche après qu'un autre cadre passe dessus. Pourquoi? Merci pour l'effort, mais j'ai besoin de quelqu'un qui va parler des problèmes, et pas un détail de mise en œuvre minuscule. –

+0

Désolé pour mon choix de mots, mais seul le lieu de peindre la fenêtre est onpaint, pour éviter le remplacement du scintillement EVT_BACKGROUND ne rien y faire, et utilisez le double tampon sur EVT_PAINT –

+0

et pouvez-vous donner un exemple que je peux simplement copier-coller et exécuter, que je peux voir à quel problème vous faites face –

Questions connexes