Как поставить фоновое изображение на приложение — wxPython #4

Я получаю очень много электронных писем от людей, изучающих Python и wxPython. В одном из них меня попросили рассказать, как создать интерфейс, в котором фоновое изображение на панели будет размещено под кнопками с помощью Tkinter или wxPython. Сначала я проверил возможно ли это в Tkinter и выяснил, что виджет PhotoImage поддерживает только два формата: gif и pgm (по крайней мере пока я не установил Python Imaging Library). Поэтому, я решил дать wxPython шанс. И вот, что у меня получилось.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Плохой пример

Погуглив немного, я нашёл способ в одном из постов на форуме. Он показался мне вполне рабочим. Я воспроизведу для вас один из вариантов его использования ниже:

Первой моей мыслью, когда я увидел это было: «Это наверняка будет выглядеть плохо». Почему я так решил?

Что же, парень, который запостил это использовал wx.StaticBitmap в качестве родителя для кнопки. Виджет StaticBitmap НЕ является контейнером, как тот же виджет Panel или Frame, поэтом я решил, его использование не будет хорошей идеей.

Я спросил Роберта Дана используя IRC канал #wxPython, о том, что он думает по поводу этой ситуации. Он сказал, что, если бы я сделал так, как показано на примере выше, у меня скорей всего появились бы проблемы со смещением и прочим, и порекомендовал мне использовать EVT_ERASE_BACKGROUND с элементами простого рисования. Учитывая то, что Роберт Дан создал wxPython, я последовал его совету и отказался от этого прошлого варианта.

Примечание: Когда я запустил этот код на Windows 7 с помощью wxPython Phoenix, у меня были жёсткие проблемы с тем, чтобы нарисовать виджет, а также с тем, чтобы отменить этот процесс. Так что используйте данный метод на свой страх и риск!

Финальное решение

Следуя указаниям Роберта Дана, я дополнил этот код:

Вот пример скриншота того, как я сделал фоновым изображением фото большого кота, сделанное мной прошлым летом.

Как поставить фоновое изображение на приложение - wxPython #4

Главный фрагмент кода, на который стоит обратить внимание:

Я копировал его из демо-версии ColourDB.py, которое доступно в демо-версии wxPython и слегка дополнил, чтобы он работал в моём приложении. Проще говоря, вы биндите панельEVT_ERASE_BACKGROUND и в этом хендлере, вы захватываете контекст устройства (DC), который в данном случае является панелью (я так думаю). Я называю это методом Clear, так как в моём настоящем приложении я использовал изображение с применением прозрачности, таким образом позволяя фону проступать.

Очистив его, я избавился от подтёков. Как бы то ни было, проверяем, существует ли DC или он пуст (так как я не уверен в этом до конца), и, если же нет – обновляет область (или так называемую «грязную зону» — часть изображения, которая пропадает после того, как на окно приложения накладывается другое). Затем я захватил своё изображение и использовал DrawBitmap, чтобы применить его в качестве фона. Это выглядит забавно, и я сам до конца не понимаю, что происходит, но это работает.

Также я нашёл ещё один метод, который я не испытывал в этой статье: http://www.5etdemi.com/blog/archives/2006/06/making-a-panel-with-a-background-in-wxpython/

Не стесняйтесь попробовать оба и выяснить какой именно метод подходит именно вам. Он похож на метод Робина Дана, в котором он использует DC, но не тот же его тип, который использовал я.

Итоги

Теперь вы получили все необходимые знания для того, чтобы добавить фоновое изображение на панель приложения. Я замечаю, что люди постоянно спрашивают о том, как это сделать, поэтому считаю данную тему очень важной. Вы можете использовать эти знания для создания Splash Screen. Несмотря ни на что, поиграйте с этим кодом сами, вдруг вы найдёте способ получше.