Обновление образа wx python в Windows

linux windows image wxpython

44 просмотра

1 ответ

У меня есть приложение, которое включает в себя отображение нескольких изображений. Это работает, как и следовало ожидать в Linux, но в Windows есть раздражающая вспышка, когда изображения нарисованы. Это лучше всего видно как маленький квадрат в верхнем левом углу экрана, где появляется вспышка цвета. Не правильно ли я подхожу к этому требованию? Или есть какое-то исправление, которое я должен применить, чтобы преодолеть эффект Windows? Или это только моя версия для Windows (у меня есть только одна, чтобы протестировать ее: Windows 7 Ultimate)?

Я попытался заморозить и разморозить в refresh_sizer_cell, но он не вел себя так, как я ожидал

import wx


class ImageSizer(wx.Frame):
    BACKGROUND_COLOUR = (246, 244, 242)
    def __init__(self, parent, title):
        super(ImageSizer, self).__init__(parent, title=title)

        self.main_sizer = wx.GridBagSizer()
        self.SetSizer(self.main_sizer)

        cmd_reset = wx.Button(self, label='Reset')
        cmd_reset.Bind(wx.EVT_BUTTON, self.on_cmd_reset_click)

        cmd_cancel = wx.Button(self, label='Cancel')
        cmd_cancel.Bind(wx.EVT_BUTTON, self.on_cmd_cancel_click)

        self.main_sizer.Add((400, 0), pos=(0, 0), span=(1, 2))    # dummy to position Available
        self.main_sizer.Add((0, 100), pos=(1, 0), span=(1, 1))    # dummy to position Buttons
        self.main_sizer.Add(cmd_reset, pos=(2, 2), flag=wx.LEFT | wx.TOP, border=10)
        self.main_sizer.Add(cmd_cancel, pos=(2, 3), flag=wx.RIGHT | wx.BOTTOM | wx.TOP | wx.ALIGN_RIGHT, border=10)

        self.SetBackgroundColour(self.BACKGROUND_COLOUR)
        self.shape_types = {'available': 0, 'selected': 1}
        self.available_shapes = []
        self.selected_shapes = []
        self.initialise()
        self.Center()
        self.Fit()
        self.Show()

    def initialise(self):
        self.available_shapes = ['square', 'circle', 'triangle', 'cross']
        self.selected_shapes = []
        self.display_images()

    def display_images(self):
        available_sizer = ShapeSizer(self, self.available_shapes, self.shape_types['available'])
        self.refresh_sizer_cell(self.main_sizer, available_sizer, (1, 2), (1, 3))
        selected_sizer = ShapeSizer(self, self.selected_shapes, self.shape_types['selected'])
        self.refresh_sizer_cell(self.main_sizer, selected_sizer, (1, 1), (2, 1))
        self.Layout()

    @staticmethod
    def refresh_sizer_cell(sizer, item, pos, span, flag=wx.ALL, border=10):
        old_item = sizer.FindItemAtPosition(pos)
        if old_item is not None and old_item.IsWindow():
            old_item.GetWindow().Hide()
            sizer.Detach(old_item.GetWindow())
        sizer.Add(item, pos=pos, span=span, flag=flag, border=border)

    def on_available_shape_double_click(self, event):
        shape = event.GetEventObject().GetName()
        self.available_shapes.remove(shape)
        self.selected_shapes.append(shape)
        self.display_images()

    def on_selected_shape_double_click(self, event):
        shape = event.GetEventObject().GetName()
        self.selected_shapes.remove(shape)
        self.available_shapes.append(shape)
        self.display_images()

    def on_cmd_reset_click(self, event):
        self.initialise()

    def on_cmd_cancel_click(self, event):
        self.Destroy()


class ShapeSizer(wx.Panel):
    def __init__(self, parent, shapes, shape_type):
        wx.Panel.__init__(self, parent, id = wx.ID_ANY)

        if shape_type == parent.shape_types['available']:
            size = 40
            action = parent.on_available_shape_double_click
        else:
            size = 80
            action = parent.on_selected_shape_double_click
        panel_sizer = wx.BoxSizer(wx.HORIZONTAL)
        shapes.sort()
        for shape in shapes:
            bitmap = wx.Bitmap(shape + '.png', wx.BITMAP_TYPE_PNG)
            bitmap = self.scale_bitmap(bitmap, size, size)
            img = wx.StaticBitmap(self, wx.ID_ANY, bitmap, name=shape)
            img.Bind(wx.EVT_LEFT_DCLICK, action)
            panel_sizer.Add(img, flag=wx.RIGHT, border=10)
        self.SetSizer(panel_sizer)

    @staticmethod
    def scale_bitmap(bitmap, width, height):
          image = wx.ImageFromBitmap(bitmap)
          image = image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
          result = wx.BitmapFromImage(image)
          return result

if __name__  ==  '__main__':
        app = wx.App()
        ImageSizer(None, title='Image Sizer')
        app.MainLoop()

Вот изображения:

circle.png

cross.png

square.png

triangle.png

Автор: Psionman Источник Размещён: 08.11.2019 11:02

Ответы (1)


1 плюс

Решение

Каждый раз, когда вы дважды щелкаете мышью по фигуре, ваша программа создает новые экземпляры панелей и их wx.StaticBitmapвиджетов, именно эти новые экземпляры вы видите, поскольку они изначально создаются с небольшим размером по умолчанию, а затем они перемещаются с помощью следующего макета. Вместо этого вы должны реорганизовать вещи так, чтобы вы создали набор панелей только один раз, и, когда состояние выбора формы изменяется, вы можете обновить существующие панели. Это значительно уменьшит мерцание, видимое пользователю.

Автор: RobinDunn Размещён: 21.08.2016 01:17
Вопросы из категории :
32x32