2

我之前问这个问题的尝试很糟糕,我也取得了一些进展,请多多包涵,我不打算重复问这么多次,这不是我的风格。

这是最终版本:我正在调整一个包含 DC 客户端绘制位图的窗口的大小,并且在 EVT_SIZE 事件上,我通过重新缩放它(使用缩放,而不是重新缩放)并重新绘制图像来调整它的大小。问题是它似乎并不尊重纵横比,即使我正在为它计算 w/h。此外,当它的高度增加时,图像会失真。最后,当另一个窗口经过它时,图像变为白色。任何想法如何解决这些问题?我的窗口/图像类如下:

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

此外,我无法理解如何正确使用客户端 DC。我想在重新绘制下一个图像之前刷新窗口区域,因为如果我不这样做,我会得到奇怪的 risiduals,它看起来很糟糕。为了解决这个问题,我尝试使用 dc.Clear 来清除背景。但是,在每次调整大小时都这样做,因为我需要在重新调整大小时使图像闪烁一百万次。我怎样才能避免这种情况?

编辑 -

作为对 Umyal 评论回复的回应 - 这是我的应用程序的一个非常简化的版本。无论哪种方式,我都会为图像分类窗口生成器,尺寸处理程序重新缩放图像会导致图像严重闪烁,从而产生不吸引人的伪像。此外,当另一帧经过应用程序时,图像显示变为白色,就像被擦除一样。

我正在考虑解决这个问题 - 我可以实现 Windows 图像查看器似乎有的解决方案,即只有当用户在调整图像大小时放开框架边缘时,图像才会重新缩放和重新绘制。该解决方案的问题是没有明确的方法来检测用户何时停止调整框架的大小。(wxEVT_SIZE, wxEVT_SIZING)

这是简化的应用程序代码,您需要找到自己的图像,并且越大越好。原始图像尺寸为 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()
4

1 回答 1

1

不要在窗口实例中保留对客户端 DC 的引用(http://docs.wxwidgets.org/2.6/wx_wxclientdc.html),这也不是绘制窗口 dc 的正确方法

而是绑定到 PAINT_EVENT 并在那里绘制,下面我展示了你说添加到你的类的东西

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()
于 2009-07-21T03:47:42.567 回答