Рубрики
Без рубрики

Как использовать демодный код Wxpython вне демонстрации

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Каждый теперь кто-то спросит о том, как они могут запустить демо-код от Демо WxPython за пределами демонстрации. Другими словами, они задаются вопросом, как вы можете извлечь код из демо и запустить его самостоятельно. Я думаю, что я писал об этой самой теме довольно некоторое время назад на Wxpython Wiki , но я думал, что я должен писать на тему здесь.

Что делать с журналом

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

import wx

#----------------------------------------------------------------------
# BEGIN Demo Code
class FindPrefixListBox(wx.ListBox):
    def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize,
                 choices=[], style=0, validator=wx.DefaultValidator):
        wx.ListBox.__init__(self, parent, id, pos, size, choices, style, validator)
        self.typedText = ''
        self.log = parent.log
        self.Bind(wx.EVT_KEY_DOWN, self.OnKey)


    def FindPrefix(self, prefix):
        self.log.WriteText('Looking for prefix: %s\n' % prefix)

        if prefix:
            prefix = prefix.lower()
            length = len(prefix)

            # Changed in 2.5 because ListBox.Number() is no longer supported.
            # ListBox.GetCount() is now the appropriate way to go.
            for x in range(self.GetCount()):
                text = self.GetString(x)
                text = text.lower()

                if text[:length] == prefix:
                    self.log.WriteText('Prefix %s is found.\n' % prefix)
                    return x

        self.log.WriteText('Prefix %s is not found.\n' % prefix)
        return -1

    def OnKey(self, evt):
        key = evt.GetKeyCode()

        if key >= 32 and key <= 127:
            self.typedText = self.typedText + chr(key)
            item = self.FindPrefix(self.typedText)

            if item != -1:
                self.SetSelection(item)

        elif key == wx.WXK_BACK:   # backspace removes one character and backs up
            self.typedText = self.typedText[:-1]

            if not self.typedText:
                self.SetSelection(0)
            else:
                item = self.FindPrefix(self.typedText)

                if item != -1:
                    self.SetSelection(item)
        else:
            self.typedText = ''
            evt.Skip()

    def OnKeyDown(self, evt):
        pass


#---------------------------------------------------------------------------

class TestListBox(wx.Panel):
    def __init__(self, parent, log):
        self.log = log
        wx.Panel.__init__(self, parent, -1)

        sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
                      'six', 'seven', 'eight', 'nine', 'ten', 'eleven',
                      'twelve', 'thirteen', 'fourteen']

        wx.StaticText(self, -1, "This example uses the wx.ListBox control.", (45, 10))
        wx.StaticText(self, -1, "Select one:", (15, 50))
        self.lb1 = wx.ListBox(self, 60, (100, 50), (90, 120), sampleList, wx.LB_SINGLE)
        self.Bind(wx.EVT_LISTBOX, self.EvtListBox, self.lb1)
        self.Bind(wx.EVT_LISTBOX_DCLICK, self.EvtListBoxDClick, self.lb1)
        self.lb1.Bind(wx.EVT_RIGHT_UP, self.EvtRightButton)
        self.lb1.SetSelection(3)
        self.lb1.Append("with data", "This one has data");
        self.lb1.SetClientData(2, "This one has data");


        wx.StaticText(self, -1, "Select many:", (220, 50))
        self.lb2 = wx.ListBox(self, 70, (320, 50), (90, 120), sampleList, wx.LB_EXTENDED)
        self.Bind(wx.EVT_LISTBOX, self.EvtMultiListBox, self.lb2)
        self.lb2.Bind(wx.EVT_RIGHT_UP, self.EvtRightButton)
        self.lb2.SetSelection(0)

        sampleList = sampleList + ['test a', 'test aa', 'test aab',
                                   'test ab', 'test abc', 'test abcc',
                                   'test abcd' ]
        sampleList.sort()
        wx.StaticText(self, -1, "Find Prefix:", (15, 250))
        fp = FindPrefixListBox(self, -1, (100, 250), (90, 120), sampleList, wx.LB_SINGLE)
        fp.SetSelection(0)


    def EvtListBox(self, event):
        self.log.WriteText('EvtListBox: %s, %s, %s\n' %
                           (event.GetString(),
                            event.IsSelection(),
                            event.GetSelection()
                            # event.GetClientData()
                            ))

        lb = event.GetEventObject()
        # data = lb.GetClientData(lb.GetSelection())

        # if data is not None:
            # self.log.WriteText('\tdata: %s\n' % data)

    def EvtListBoxDClick(self, event):
        self.log.WriteText('EvtListBoxDClick: %s\n' % self.lb1.GetSelection())
        self.lb1.Delete(self.lb1.GetSelection())

    def EvtMultiListBox(self, event):
        self.log.WriteText('EvtMultiListBox: %s\n' % str(self.lb2.GetSelections()))

    def EvtRightButton(self, event):
        self.log.WriteText('EvtRightButton: %s\n' % event.GetPosition())

        if event.GetEventObject().GetId() == 70:
            selections = list(self.lb2.GetSelections())
            selections.reverse()

            for index in selections:
                self.lb2.Delete(index)
#----------------------------------------------------------------------
# END Demo Code
#----------------------------------------------------------------------

Я не собираюсь объяснить сам демо-код. Вместо этого я сосредоточусь на этом вопросе, который этот код представляет при желании попробовать его за пределами демонстрации. Есть сантест Функция в конце демо, которую я не копировал, потому что этот код ничего не сделает, если вы скопируете его за пределами демо. Видите ли, демонстрационный код имеет какую-то обертку вокруг него, что делает его работать. Вам нужно будет добавить свою собственную «обертку» сортов, если вы хотите использовать демонстрационный код.

Основная проблема, которую дает этот код, состоит в том, что многие методы имеют вызов self.log.writeText Отказ Вы не можете сказать из кода, что является объектом журнала, но вы знаете, что у него есть WriteText метод. В демо-демострациях вы заметите, что когда один из этих методов пожара вызовы WriteText, кажется, пишут в текстовом управлении в нижней части демонстрации. Таким образом, журнал должен быть виджетом управления текстовым управлением!

Есть много разных подходов к решению проблемы журнала. Вот мои лучшие три:

  • Удалите все звонки на self.log.writeText
  • Создайте свой собственный контроль текста и передайте его в
  • Создайте простой класс с методом WriteText

Я сделал первый выбор во многих случаях, так как это простой способ идти. Но для учебника это довольно скучно, поэтому мы выберем третий вариант и создаем класс с методом WriteText! Добавьте следующий код в тот же файл, который содержит код выше:


#----------------------------------------------------------------------
# Start Your own code here           
class FakeLog:
    """
    The log in the demo is a text control, so just create a class
    with an overridden WriteText function
    """
    
    def WriteText(self, string):
        print(string)
   
# Create a frame that can wrap your demo code (works in most cases)

class MyFrame(wx.Frame):
    
    def __init__(self):
        wx.Frame.__init__(self, None, title='Listbox demo', 
                          size=(800,600))
        log = FakeLog()
        panel = TestListBox(self, log=log)
        
        self.Show()
        
if __name__ == '__main__':
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

Здесь мы просто создаем Fakelog С методом WriteText, который принимает строку в качестве своего единственного параметра. Все этот метод напечатает строку на STDOUT. Затем мы создаем подкласс wx.frame, инициализируйте наш фальшивый журнал и демонстрационный код и показывают наш кадр. Теперь у нас есть рабочий кусок демо-кода, который не в демо! Вы можете получить полный код на Github Если вы хотите.

Другие демонстрационные проблемы

Есть несколько других демонстраций, которые не следуют тому же API, что ListBox Демо делает. Например, если вы попробуете использовать класс, который я создал выше для wx.button Демо, вы обнаружите, что его объект журнала вызывает метод записи () вместо метода WriteText (). Решение очевидно в этом случае в том, что нам просто нужно добавить второй метод для нашего класса регистрации поддельных веществ:

class FakeLog:
    """
    The log in the demo is a text control, so just create a class
    with an overridden WriteText function
    """
    
    def WriteText(self, string):
        print(string)
    
    def write(self, string):
        print(string)

Теперь наш демонстрационный код работает немного более гибким. Однако, когда у меня был один из моих читателей, тестирующих этот код, они заметили проблему с wx.listctrl демонстрация Вопрос в том, что он импортирует модуль под названием «Изображения». На самом деле есть несколько демонстраций, которые ссылаются на этот модуль. Вам просто нужно будет скопировать images.py С демонстрации и поместите его в то же место, что и сценарий, который вы пишете, чтобы вы могли импортировать его.

Примечание: у меня был один отчет о том, что images.py Файл, включенный с последней бета-версией WXPYPHON 4, не работал на них, и им пришлось схватить копию со старой версией демо. У меня не было этого вопроса себя, но держите это в виду.

Обертывание

Теперь у вас должны быть инструменты, необходимые для большинства демонстраций с демонстрационной работы WXPYPHON в вашем собственном коде. Go Grab какой-нибудь код и попробую! Счастливое кодирование!