Pergunta

Minha tentativa anterior de fazer essa pergunta foi horrível e eu também fiz alguns progressos, por favor, tenha paciência comigo, não pretendi rejeitar isso tantas vezes, e não é o meu estilo.

Aqui está a versão final: estou redimensionando uma janela que contém um bitmap pintado de cliente DC e, no evento EVT_SIZE, estou redimensionando-o novamente (usando escala, não de recuperação) e pintando a imagem. O problema é que não parece que esteja respeitando a proporção, mesmo que eu esteja calculando com isso. Além disso, quando cresce em altura, a imagem é distorcida. Finalmente, quando outra janela passa por ela, a imagem fica branca. Alguma idéia de como resolver algum desses problemas? Minha classe de janela/imagem está abaixo:

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

Além disso, estou tendo problemas para entender como usar corretamente o cliente DC. Quero atualizar a área da janela antes de reprovar a próxima imagem, porque se eu não fico com risiduais estranhos e parece ruim. Para corrigir isso, tentei usar o DC.clear, que limpa o fundo. No entanto, fazê-lo em todos os tamanhos, pois eu precisaria fazer com que a imagem pisque o branco um milhão de vezes, enquanto estou redimensionando. Como posso evitar isso?

Editar -

Em resposta à resposta de comentários de Umyal - aqui está uma versão muito simplificada do meu aplicativo. De qualquer maneira, eu classifico meu gerador de janelas para as imagens que o manipulador de tamanho re-escalonar as imagens faz com que a imagem pisque muito, criando um artefato desagradável. Além disso, quando outro quadro passa pelo aplicativo, a exibição da imagem fica branca, como se fosse apagada.

Eu estava pensando como uma maneira de contornar isso - eu poderia implementar a solução que o Windows Image Viewer parece ter, que é a imagem apenas redimensionada e repintada quando o usuário deixa de lado a borda do quadro ao redimensioná -la. O problema com essa solução é que não há uma maneira clara de detectar quando o usuário para de redimensionar o quadro. (wxevt_size, wxevt_sizing)

Aqui está o código do aplicativo simplificado, você precisará encontrar suas próprias imagens e quanto maior, melhor. A imagem original de imagem é 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()
Foi útil?

Solução

Não mantenha uma referência ao cliente DC em sua instância da janela (http://docs.wxwidgets.org/2.6/wx_wxclientdc.html), nem é a maneira correta de desenhar sobre a janela DC

Em vez disso, vincule -se a Paint_Event e desenhe lá, abaixo, mostrei as coisas que você disse, adicione à sua aula

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()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top