GUI для питона: пишем PageRankChecker


Вопрос на засыпку: что объединяет все мои предыдущие статьи по программированию, за исключением того что они посвящены питону? Правильно: все разобранные примеры написаны для консоли. Попробую разнообразить тематику статей – разберем написание программы с графическим интерфейсом. В качестве примера напишем определитель PR (PageRank) сайтов, а то на http://www.prchecker.info/ меня постоянно просят ввести символы с картинки (на http://page-rank.org.ua/ определитель PR вообще продают за 5$).

Для питона существует большое количество кроссплатформенных графических библиотек. Основные из них: Tkinter – поставляется вместе с python, wxPython – расширение для wxWidgets (возможно, займет место Tkinter в следующих версия python), PyQt – обертка популярной библиотеки Qt, и другие (PyGtk, PyFLTK, FXpy, PyOpenGL). Для простоты усвоения материала рассмотрим написание программы, которая по адресу сайта будет выводить его PageRank. За основу возьмем библиотеку wxPython, как наиболее перспективную (скачать можно по адресу). В качестве IDE буду использовать BoaConstructor (скачивать по адресу).

Основное окно BoaConstructor

Итак, запускаем свежеустановленный  BoaConstructor и наблюдаем на экране 3 рабочих окна: основное окно с компонентами, инспектор объектов и редактор. Затем создадим новое графическое приложение – на вкладке основного окна «New» находим wx.App и кликаем по нему.

В окне редактора появятся сразу два новых файла: файл приложения App1.py и файл окна Frame1. После сохранения их в отдельный каталог, приложение можно запустить, нажав на желтый треугольник.

Запускаем пустое графическое приложение на питоне

Появится пустая  форма с заголовком Frame1. Убедившись что все работает как надо, вернемся к проектированию элементов формы и запустим Frame Designer:

Редактор кода перед запуском FrameDesugner БоаКонструктора

Появится пустая форма, на которую можно размещать элементы управления из главного окна. В нашем случае нам понадобятся: с панели Basic Controls – 2-а StaticText и 1 TextCtrl; с панели Buttons – 2-е кнопки Button; и для красоты с той же панели Basic Controls один компонент StaticBitmap. Для создания событий нажатия кнопок, дважды щелкнем на каждой из них. Закроем форму, так как проектирование интерфейса уже закончено. Код фрейма заметно изменился:

#Boa:Frame:Frame1

import wx

def create(parent):
    return Frame1(parent)

[wxID_FRAME1, wxID_FRAME1BUTTON1, wxID_FRAME1BUTTON2,
 wxID_FRAME1STATICBITMAP1, wxID_FRAME1STATICTEXT1, wxID_FRAME1STATICTEXT2,
 wxID_FRAME1TEXTCTRL1,
] = [wx.NewId() for _init_ctrls in range(7)]

class Frame1(wx.Frame):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
              pos=wx.Point(275, 213), size=wx.Size(853, 467),
              style=wx.DEFAULT_FRAME_STYLE, title='Frame1')
        self.SetClientSize(wx.Size(853, 467))

        self.staticText1 = wx.StaticText(id=wxID_FRAME1STATICTEXT1,
              label='staticText1', name='staticText1', parent=self,
              pos=wx.Point(128, 24), size=wx.Size(75, 17), style=0)

        self.staticText2 = wx.StaticText(id=wxID_FRAME1STATICTEXT2,
              label='staticText2', name='staticText2', parent=self,
              pos=wx.Point(312, 56), size=wx.Size(75, 17), style=0)

        self.textCtrl1 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL1, name='textCtrl1',
              parent=self, pos=wx.Point(232, 24), size=wx.Size(80, 27), style=0,
              value='textCtrl1')

        self.button1 = wx.Button(id=wxID_FRAME1BUTTON1, label='button1',
              name='button1', parent=self, pos=wx.Point(144, 112),
              size=wx.Size(85, 29), style=0)
        self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button,
              id=wxID_FRAME1BUTTON1)

        self.button2 = wx.Button(id=wxID_FRAME1BUTTON2, label='button2',
              name='button2', parent=self, pos=wx.Point(288, 112),
              size=wx.Size(85, 29), style=0)
        self.button2.Bind(wx.EVT_BUTTON, self.OnButton2Button,
              id=wxID_FRAME1BUTTON2)

        self.staticBitmap1 = wx.StaticBitmap(bitmap=wx.NullBitmap,
              id=wxID_FRAME1STATICBITMAP1, name='staticBitmap1', parent=self,
              pos=wx.Point(48, 208), size=wx.Size(16, 16), style=0)

    def __init__(self, parent):
        self._init_ctrls(parent)

    def OnButton1Button(self, event):
        event.Skip()

    def OnButton2Button(self, event):
        event.Skip()

Глядя на него несложно догадаться где нужно подправить, что бы получить нужные надписи на элементах управления. А нужны нам следующие надписи: в заголовке формы – «CheckPR», на кнопках – «Clear» и «Check», статические надписи – одна пустая (для вывода результатов), а на другой – «URL», ну и конечно содержимое поля ввода TextCtrl1 пустое.  Для того что бы на форме появилась картинка нужно поместить эту картинку в папку с файлами программы, в описании StaticBitmap1 заменить bitmap=wx.NullBitmap на bitmap=wx.Bitmap(«Имя картинки.jpg») и конечно изменить размеры компонента под размеры картинки.

Поместим в каталог программы модуль (назовем его gpr.py), в который поместим функционал для определения PageRank (можно взять из материалов статьи про злобоскрипт) и подключим его в начале Frame1.py: import gpr.

Осталось задать реакцию в Frame1.py на нажатия кнопок:

def OnButton1Button(self, event):
	# очищаем поле ввода URL
	self.textCtrl1.SetValue('')

def OnButton2Button(self, event):
	# записываем содержимое поля ввода URL в переменную url
	url = self.textCtrl1.GetValue()
	# с помощ подключенной библиотеки определяем PageRank
	pr = gpr.get_pagerank(url)
	# выводим полученный результат на компонент staticText2
	self.staticText2.SetLabel(pr)

Результаты работы программы:

Внешний вид PageRank чекера на питоне

Исходный код можно взять отсюда. Жду отзывов и пожеланий.

P.S. Пример легко можно улучшить: например сделать возможным определение PR сразу для нескольких сайтов;  прикрутить определение ТиЦ и т.д.

, , ,



  1. #1 by 32pt on 27 Февраль 2011 - 10:48

    Тока начал знакомиться c Python. Понравился тем, что больно много можно на нем сделать. Наверное полностью перейду к Python и покончу с Flash ActionScript. Отличный блог, спасибо.

  2. #2 by Александр on 31 Март 2011 - 17:44

    спасибо за статью, с нее у меня начинается знакомство с графическим питоном)

  3. #3 by Dima on 16 Май 2011 - 10:21

    Спасибо за статью, все просто и понятно. а то на сайте wxpython`a чорт ногу сломит

  4. #4 by Dima on 17 Май 2011 - 16:36

    привет скажи , а как из поля1 получить значение переменной и использовать его за классом? вот код http://dumpz.org/54860/

    • #5 by toly on 17 Май 2011 - 18:47

      url_forum.GetValue()

      И вот еще: вместо
      url_forum = wx.TextCtrl(self, -1, u’поле1′, pos = wx.Point(120, 20), size = wx.Size(150, 20))
      следует написать
      self.url_forum = wx.TextCtrl(self, -1, u’поле1′, pos = wx.Point(120, 20), size = wx.Size(150, 20))

  5. #6 by Роман on 8 Июнь 2012 - 12:15

    Спасибо за урок но он не заработал =( При нажатии на кнопку нечего не происходит. Кириллица кстати не поддерживается =( А итоговые скачанные исходники при запуске выдают лишь тексотовое поле, без кнопок, без картинки.
    Питон 2.7

  6. #7 by Дмитрий on 31 Июль 2014 - 13:27

    Ссылка http://www.google.com/search?client=navclient-auto&features=Rank:&q=info:%s&ch=%s‘ из файла gpr.py больше не возвращает PR. Где взять рабочу?

(никто не узнает)