wxPython - Szybki przewodnik

wxPython jest opakowaniem Pythona dla wxWidgets(napisany w C ++), popularny wieloplatformowy zestaw narzędzi GUI. Opracowany przez Robina Dunna wraz z Harri Pasanenem, wxPython jest zaimplementowany jako moduł rozszerzający Pythona.

Podobnie jak wxWidgets, wxPython jest również darmowym oprogramowaniem. Można go pobrać z oficjalnej strony internetowejhttp://wxpython.org. Pliki binarne i kod źródłowy dla wielu platform systemów operacyjnych są dostępne do pobrania na tej stronie.

Główne moduły interfejsu API wxPython obejmują moduł podstawowy. Składa się ona zwxObjectclass, która jest bazą dla wszystkich klas w API. Moduł sterujący zawiera wszystkie widżety używane w tworzeniu aplikacji GUI. Na przykład wx.Button, wx.StaticText (analogicznie do etykiety), wx.TextCtrl (edytowalna kontrolka tekstu) itp.

wxPython API posiada moduł GDI (Graphics Device Interface). Jest to zestaw klas służących do rysowania na widżetach. Częścią tego są klasy takie jak czcionka, kolor, pędzel itp. Wszystkie klasy okien kontenera są zdefiniowane w module Windows.

Oficjalna strona wxPython zawiera również Project Phoenix - nową implementację wxPython dla Pythona 3. *. Koncentruje się na poprawie szybkości, łatwości konserwacji i rozszerzalności. Projekt rozpoczął się w 2012 roku i nadal jest w fazie beta.

Windows

Gotowe pliki binarne dla systemu operacyjnego Windows (zarówno 32-bitowe, jak i 64-bitowe) są dostępne w http://www.wxpython.org/download.phpstrona. Najnowsze dostępne wersje instalatorów to - wxPython3.0-win32-3.0.2.0-py27.exe dla 32-bitowego Pythona 2.7 wxPython3.0-win64-3.0.2.0-py27.exe dla 64-bitowego Pythona 2.7

Demo wxPython, przykłady i dokumentacja wxWidgets są również dostępne do pobrania na tej samej stronie.

wxPython3.0-win32-docs-demos.exe

Linux

Pliki binarne wxPython dla wielu dystrybucji Linuksa można znaleźć w odpowiednich repozytoriach. Do pobrania i zainstalowania trzeba będzie użyć odpowiednich menedżerów pakietów. Na przykład w systemie Debian Linux następujące polecenie powinno być w stanie zainstalować wxPython.

sudo apt-get install python-wxgtk3.0

System operacyjny Mac

Gotowe pliki binarne dla systemu MacOS w postaci obrazów dysków są dostępne na stronie pobierania oficjalnej strony internetowej.

Prosta aplikacja GUI wyświetlająca komunikat Hello World jest tworzona w następujący sposób:

  • Importuj moduł wx.

  • Zdefiniuj obiekt klasy Application.

  • Utwórz okno najwyższego poziomu jako obiekt klasy wx.Frame. Parametry podpisu i rozmiaru są podane w konstruktorze.

  • Chociaż w obiekcie Frame można dodać inne kontrolki, nie można zarządzać ich układem. Dlatego umieść obiekt Panel w ramie.

  • Dodaj obiekt StaticText, aby wyświetlić „Hello World” w żądanym miejscu w oknie.

  • Aktywuj okno ramki metodą show ().

  • Wprowadź główną pętlę zdarzeń obiektu Application.

import wx 
 
app = wx.App() 
window = wx.Frame(None, title = "wxPython Frame", size = (300,200)) 
panel = wx.Panel(window) 
label = wx.StaticText(panel, label = "Hello World", pos = (100,50)) 
window.Show(True) 
app.MainLoop()

Powyższy kod daje następujące dane wyjściowe -

wxFrame objectto najczęściej używane okno najwyższego poziomu. Pochodzi zwxWindow class. Ramka to okno, którego rozmiar i położenie może być zmieniane przez użytkownika. Posiada pasek tytułu i przyciski sterujące. W razie potrzeby można włączyć inne komponenty, takie jak pasek menu, pasek narzędzi i pasek stanu. Okno wxFrame może zawierać dowolną ramkę, która nie jest oknem dialogowym ani inną ramką.

Tworzenie dobrze wyglądającego GUI przez ręczne kodowanie może być żmudne. Wizualne narzędzie do projektowania GUI jest zawsze przydatne. Dostępnych jest wiele IDE programistycznych GUI przeznaczonych dla wxPython. Oto niektóre z nich -

  • wxFormBuilder
  • wxDesigner
  • wxGlade
  • BoaConstructor
  • gui2py

wxFormBuilderto wieloplatformowy kreator WYSIWYG GUI typu open source, który może przetłumaczyć projekt GUI wxWidget na format C ++, Python, PHP lub XML. Tutaj znajduje się krótkie wprowadzenie do korzystania z wxFormBuilder.

Przede wszystkim należy pobrać i zainstalować najnowszą wersję wxFormBuilder z http://sourceforge.net/projects/wxformbuilder/. Po otwarciu aplikacji pojawia się nowy projekt z pustym szarym obszarem pośrodku.

Nadaj projektowi odpowiednią nazwę i wybierz Python jako język generowania kodu. Odbywa się to w oknie Właściwości obiektu, jak pokazano na poniższym obrazku -

Następnie z zakładki „Formularze” palety komponentów wybierz opcję Ramka.

Dodaj pionowy wxBoxSizer z zakładki „Layouts”.

Dodaj niezbędne elementy sterujące w polu z odpowiednimi podpisami. Tutaj dodawany jest StaticText (etykieta), dwa obiekty TextCtrl (pola tekstowe) i obiekt wxButton. Ramka wygląda jak na poniższym obrazku -

Włącz rozwijanie i rozciąganie w tych trzech kontrolkach. We właściwościach obiektu wxButton przypisz funkcję findquare () do zdarzenia OnButtonClick.

Zapisz projekt i naciśnij klawisz F8, aby wygenerować kod w języku Python dla opracowanego interfejsu GUI. Niech wygenerowany plik zostanie nazwany Demo.py

W wykonywalnym skrypcie Pythona zaimportuj demo.py i zdefiniuj funkcję FindSquare (). Zadeklaruj obiekt aplikacji i uruchom główną pętlę zdarzeń. Poniżej znajduje się kod wykonywalny -

import wx 
  
#import the newly created GUI file 
import demo  
class CalcFrame(demo.MyFrame1): 
   def __init__(self,parent): 
      demo.MyFrame1.__init__(self,parent)  
		
   def FindSquare(self,event): 
      num = int(self.m_textCtrl1.GetValue()) 
      self.m_textCtrl2.SetValue (str(num*num)) 
        
app = wx.App(False) 
frame = CalcFrame(None) 
frame.Show(True) 
#start the applications 
app.MainLoop()

Powyższy kod daje następujące dane wyjściowe -

Oryginalny wxWidgets (napisany w C ++) to ogromna biblioteka klas. Klasy GUI z tej biblioteki są przenoszone do Pythona za pomocą modułu wxPython, który stara się jak najbardziej dublować oryginalną bibliotekę wxWidgets. Zatem klasa wx.Frame w wxPythonie działa w podobny sposób jak klasa wxFrame w swojej wersji C ++.

wxObject jest bazą dla większości klas. Obiekt wxApp (wx.App w wxPython) reprezentuje samą aplikację. Po wygenerowaniu GUI aplikacja wchodzi w pętlę zdarzeń metodą MainLoop (). Poniższe diagramy przedstawiają hierarchię klas najczęściej używanych klas GUI zawartych w wxPython.

SN Klasy i opis
1 wx.Frame

wx.Frame Klasa ma domyślny konstruktor bez argumentów.

2 wx.Panel

Klasa wx.Panel jest zwykle umieszczana wewnątrz obiektu wxFrame. Ta klasa jest również dziedziczona z klasy wxWindow.

3 wx.StaticText

Obiekt klasy wx.StaticText przedstawia kontrolkę przechowującą taki tekst tylko do odczytu. Można go określić jako bierną kontrolę, ponieważ nie generuje żadnego zdarzenia.

4 TextCtrl

W wxPythonie do tego celu służy obiekt klasy wx.TextCtrl. Jest to element sterujący, w którym można wyświetlać i edytować tekst.

5 RadioButton i RadioBox

Każdy przycisk, obiekt klasy wx.RadioButton, niesie etykietę tekstową obok okrągłego przycisku. WxPython API składa się również z klasy wx.RadioBox. Jego obiekt oferuje grupie obramowanie i etykietę.

6 wx.CheckBox

Pole wyboru wyświetla małe prostokątne pole z etykietą. Po kliknięciu w prostokącie pojawi się znacznik wyboru wskazujący, że dokonano wyboru.

7 ComboBox i klasa wyboru

Obiekt wx.ComboBox przedstawia listę elementów do wyboru. Może być skonfigurowany jako lista rozwijana lub ze stałym wyświetlaczem. wxPython API zawiera klasę wx.Choice, której obiekt jest jednocześnie listą rozwijaną, która jest trwale tylko do odczytu.

8 Wx.Gauge

Obiekt klasy Wx.Gauge przedstawia pionowy lub poziomy pasek, który graficznie przedstawia rosnącą ilość.

9 wx.Slider

wxPython API zawiera klasę wx.Slider. Oferuje taką samą funkcjonalność jak Scrollbar. Slider oferuje wygodny sposób obsługi przeciągania uchwytu za pomocą segregatora zdarzeń wx.EVT_SLIDER określonego suwaka.

10 wx.MenuBar

Poziomy pasek tuż pod paskiem tytułu okna najwyższego poziomu jest zarezerwowany do wyświetlania serii menu. Jest to obiekt klasy wx.MenuBar w API wxPython.

11 wx.Toolbar

Jeśli parametr style obiektu wx.Toolbar jest ustawiony na wx.TB_DOCKABLE, staje się on dokowalny. Pływający pasek narzędzi można również skonstruować za pomocą klasy AUIToolBar wxPython.

12 Wx.Dialog

Chociaż obiekt klasy Dialog wygląda jak Frame, zwykle jest używany jako wyskakujące okienko na górze ramki nadrzędnej. Celem dialogu jest zebranie pewnych danych od użytkownika i wysłanie ich do ramki nadrzędnej.

13 wx.Notebook

wx.Notebook widget przedstawia formant z zakładkami. Jeden obiekt Notatnik w ramce ma jedną lub więcej zakładek (zwanych Stronami), z których każda ma panel pokazujący układ elementów sterujących.

14 wx.SplitterWindow

Obiektem tej klasy jest menedżer układu, który zawiera dwa podokna, których rozmiar można dynamicznie zmieniać, przeciągając granice między nimi. Kontrolka Splitter udostępnia uchwyt, który można przeciągnąć, aby zmienić rozmiar kontrolek.

15 HTMLWindow

Biblioteka wxHTML zawiera klasy do analizowania i wyświetlania treści HTML. Chociaż nie jest to przeglądarka z pełnym zestawem funkcji, obiekt wx.HtmlWindow jest przeglądarką HTML.

16 ListBox i ListCtrl

Widżet wx.ListBox przedstawia przewijaną w pionie listę ciągów. Domyślnie można wybrać pojedynczą pozycję na liście. Widżet ListCtrl to zaawansowane narzędzie do wyświetlania i zaznaczania list. Lista zawierająca więcej niż jedną kolumnę może być wyświetlana w widoku raportu, widoku listy lub widoku ikon.

W przeciwieństwie do aplikacji w trybie konsoli, która jest wykonywana w sposób sekwencyjny, aplikacja oparta na graficznym interfejsie użytkownika jest sterowana zdarzeniami. Funkcje lub metody są wykonywane w odpowiedzi na działania użytkownika, takie jak kliknięcie przycisku, wybranie elementu z kolekcji lub kliknięcie myszą itp., Zwane zdarzeniami.

Dane dotyczące zdarzenia, które ma miejsce podczas działania aplikacji, są przechowywane jako obiekt podklasy pochodzącej z wx.Event. Kontrolka wyświetlania (taka jak Button) jest źródłem zdarzenia określonego typu i tworzy obiekt klasy Event skojarzonej z nią. Na przykład kliknięcie przycisku powoduje wyświetlenie zdarzenia wx.CommandEvent. Te dane zdarzenia są wysyłane do metody obsługi zdarzeń w programie. wxPython ma wiele predefiniowanych powiązań zdarzeń. NaEvent binder hermetyzuje relację między określonym widgetem (kontrolką), skojarzonym z nim typem zdarzenia i metodą obsługi zdarzenia.

Na przykład, żeby zadzwonić OnClick() method programu po kliknięciu przycisku, wymagane jest następujące oświadczenie -

self.b1.Bind(EVT_BUTTON, OnClick)

Bind() methodjest dziedziczona przez wszystkie obiekty wyświetlane z klasy wx.EvtHandler. EVT_.BUTTON to binder, który kojarzy zdarzenie kliknięcia przycisku z metodą OnClick ().

Przykład

W poniższym przykładzie MoveEvent, spowodowane przeciągnięciem okna najwyższego poziomu - w tym przypadku obiektu wx.Frame - jest połączone z OnMove() methodza pomocą segregatora wx.EVT_MOVE. Kod wyświetla okno. Jeśli zostanie przesunięty za pomocą myszy, jego chwilowe współrzędne są wyświetlane na konsoli.

import wx
  
class Example(wx.Frame): 
            
   def __init__(self, *args, **kw): 
      super(Example, self).__init__(*args, **kw)  
      self.InitUI() 
           
   def InitUI(self): 
      self.Bind(wx.EVT_MOVE, self.OnMove) 
      self.SetSize((250, 180)) 
      self.SetTitle('Move event') 
      self.Centre() 
      self.Show(True)
		   
   def OnMove(self, e): 
      x, y = e.GetPosition() 
      print "current window position x = ",x," y= ",y 
         
ex = wx.App() 
Example(None) 
ex.MainLoop()

Powyższy kod daje następujące dane wyjściowe -

aktualna pozycja okna x = 562 y = 309

aktualna pozycja okna x = 562 y = 309

aktualna pozycja okna x = 326 y = 304

aktualna pozycja okna x = 384 y = 240

aktualna pozycja okna x = 173 y = 408

aktualna pozycja okna x = 226 y = 30

aktualna pozycja okna x = 481 y = 80

Niektóre podklasy dziedziczone po wx.Event są wymienione w poniższej tabeli -

SN Wydarzenia i opis
1

wxKeyEvent

Występuje, gdy klawisz zostanie naciśnięty lub zwolniony

2

wxPaintEvent

Jest generowany za każdym razem, gdy zawartość okna wymaga ponownego narysowania

3

wxMouseEvent

Zawiera dane o dowolnym zdarzeniu spowodowanym aktywnością myszy, taką jak naciśnięcie lub przeciągnięcie przycisku myszy

4

wxScrollEvent

Skojarzone z przewijalnymi kontrolkami, takimi jak wxScrollbar i wxSlider

5

wxCommandEvent

Zawiera dane o zdarzeniach pochodzące z wielu widżetów, takich jak przyciski, okna dialogowe, schowek itp.

6

wxMenuEvent

Różne zdarzenia związane z menu, z wyjątkiem kliknięcia przycisku polecenia menu

7

wxColourPickerEvent

Zdarzenia wygenerowane przez wxColourPickerCtrl

8

wxDirFilePickerEvent

Zdarzenia generowane przez FileDialog i DirDialog

Zdarzenia w wxPython są dwojakiego rodzaju. Podstawowe wydarzenia i zdarzenia dowodzenia. Podstawowe zdarzenie pozostaje lokalne dla okna, z którego pochodzi. Większość wxWidgets generuje zdarzenia poleceń. ZAcommand event mogą być propagowane do okna lub okien, które znajdują się nad oknem źródłowym w hierarchii klas.

Przykład

Poniżej znajduje się prosty przykład propagacji zdarzeń. Kompletny kod to -

import wx
  
class MyPanel(wx.Panel): 
     
   def __init__(self, parent): 
      super(MyPanel, self).__init__(parent)
		
      b = wx.Button(self, label = 'Btn', pos = (100,100)) 
      b.Bind(wx.EVT_BUTTON, self.btnclk) 
      self.Bind(wx.EVT_BUTTON, self.OnButtonClicked) 
		
   def OnButtonClicked(self, e): 
         
      print 'Panel received click event. propagated to Frame class' 
      e.Skip()  
		
   def btnclk(self,e): 
      print "Button received click event. propagated to Panel class" 
      e.Skip()
		
class Example(wx.Frame):

   def __init__(self,parent): 
      super(Example, self).__init__(parent)  
         
      self.InitUI() 

   def InitUI(self):
	
      mpnl = MyPanel(self) 
      self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)
		
      self.SetTitle('Event propagation demo') 
      self.Centre() 
      self.Show(True)
		
   def OnButtonClicked(self, e): 
         
      print 'click event received by frame class' 
      e.Skip()
		
ex = wx.App() 
Example(None) 
ex.MainLoop()

W powyższym kodzie są dwie klasy. MyPanel, podklasę wx.Panel i Example, podklasę wx.Frame, która jest oknem najwyższego poziomu programu. W panelu umieszczony jest przycisk.

Ten obiekt Button jest powiązany z programem obsługi zdarzeń btnclk (), który propaguje go do klasy nadrzędnej (w tym przypadku MyPanel). Kliknięcie przycisku generujeCommandEvent który można propagować do swojego rodzica metodą Skip ().

Obiekt klasy MyPanel wiąże również odebrane zdarzenie z innym programem obsługi OnButtonClicked (). Ta funkcja z kolei przekazuje do swojej nadrzędnej klasy Example. Powyższy kod daje następujące dane wyjściowe -

Button received click event. Propagated to Panel class. 
Panel received click event. Propagated to Frame class. 
Click event received by frame class.

Widżet GUI można umieścić w oknie kontenera, określając jego współrzędne bezwzględne mierzone w pikselach. Współrzędne odnoszą się do wymiarów okna zdefiniowanych przez argument size jego konstruktora. Położenie widżetu w oknie określapos argument jego konstruktora.

import wx  

app = wx.App() 
window = wx.Frame(None, title = "wxPython Frame", size = (300,200)) 
panel = wx.Panel(window) 
label = wx.StaticText(panel, label = "Hello World", pos = (100,50)) 
window.Show(True) 
app.MainLoop()

To Absolute Positioning jednak nie nadaje się z następujących powodów -

  • Pozycja widżetu nie zmienia się nawet po zmianie rozmiaru okna.

  • Wygląd może nie być jednolity na różnych urządzeniach wyświetlających o różnych rozdzielczościach.

  • Modyfikacja układu jest trudna, ponieważ może wymagać przeprojektowania całego formularza.

Interfejs API wxPython udostępnia klasy Layout do bardziej eleganckiego zarządzania pozycjonowaniem widżetów w kontenerze. Zalety menedżerów układów w porównaniu z pozycjonowaniem bezwzględnym to -

  • Widżety w oknie są automatycznie zmieniane.
  • Zapewnia jednolity wygląd na urządzeniach wyświetlających o różnych rozdzielczościach.
  • Dynamiczne dodawanie lub usuwanie widżetów jest możliwe bez konieczności przeprojektowywania.

Menedżer układu nazywa się Sizer w wxPython. Wx.Sizer jest klasą bazową dla wszystkich podklas rozmiarów. Omówmy niektóre ważne rozmiary, takie jak wx.BoxSizer, wx.StaticBoxSizer, wx.GridSizer, wx.FlexGridSizer i wx.GridBagSizer.

SN Rozmiary i opis
1 BoxSizer

Ten rozmiar pozwala na rozmieszczenie elementów sterujących w wierszach lub kolumnach. Układ BoxSizer jest określany przez jego argument orientacji (wxVERTICAL lub wxHORIZONTAL).

2 GridSizer

Jak sama nazwa wskazuje, obiekt GridSizer przedstawia dwuwymiarową siatkę. Kontrolki są dodawane do gniazda siatki w kolejności od lewej do prawej i od góry do dołu.

3 FlexiGridSizer

Ta miarka ma również dwuwymiarową siatkę. Jednak zapewnia nieco większą elastyczność w rozmieszczaniu kontroli w komórkach.

4 GridBagSizer

GridBagSizer to wszechstronna miarka. Oferuje więcej ulepszeń niż FlexiGridSizer. Widżet podrzędny można dodać do określonej komórki w siatce.

5 StaticBoxSizer

StaticBoxSizer umieszcza rozmiar pudełka w polu statycznym. Zapewnia obramowanie wokół pudełka wraz z etykietą u góry.

Widżet przycisku jest najczęściej używany w każdym interfejsie GUI. Przechwytuje zdarzenie kliknięcia wygenerowane przez użytkownika. Jego najbardziej oczywistym zastosowaniem jest wyzwolenie powiązanej z nim funkcji obsługi.

Biblioteka klas wxPython udostępnia różne typy przycisków. Jest prosty, tradycyjny przycisk,wx.Buttonclass, który zawiera tekst jako podpis. Dostępny jest również przycisk dwustanowy o nazwiewx.ToggleButton. Jego stan wciśnięcia lub wciśnięcia można zidentyfikować za pomocą funkcji obsługi zdarzeń.

Inny rodzaj przycisku, wx.BitmapButton wyświetla bitmapę (obraz) jako ikonę na swojej powierzchni.

Konstruktor dla klasy wx.Button i wx.ToggleButton przyjmuje następujące argumenty -

Wx.Button(parent, id, label, pos, size, style)

Oto kilka ważnych metod klasy wx.Button -

SN Metody i opis
1

SetLabel()

Programowo ustawia podpis przycisku

2

GetLabel()

Zwraca podpis przycisku

3

SetDefault()

Przycisk jest ustawiony domyślnie dla okna najwyższego poziomu. Emuluje zdarzenie kliknięcia po naciśnięciu klawisza Enter

Dwie ważne metody klasy wx.ToggleButton to -

SN Metody i opis
1

GetValue()

Zwraca stan przycisku przełączania (wł. / Wył.)

2

SetValue()

Programowo ustawia stan przycisku

Aby utworzyć przycisk mapy bitowej, po pierwsze, obiekt bitmapy musi zostać utworzony z pliku obrazu.

Następująca odmiana konstruktora klasy wx.Bitmap jest najczęściej używana -

Wx.Bitmap(fiiename, wx.BITMAP_TYPE)

Niektóre z predefiniowanych stałych typu mapy bitowej to -

wx.BITMAP_TYPE_BMP
wx.BITMAP_TYPE_ICO
wx.BITMAP_TYPE_CUR
wx.BITMAP_TYPE_TIFF
wx.BITMAP_TYPE_TIF
wx.BITMAP_TYPE_GIF
wx.BITMAP_TYPE_PNG
wx.BITMAP_TYPE_JPEG
wx.BITMAP_TYPE_PCX
wx.BITMAP_TYPE_ICON
wx.BITMAP_TYPE_ANY

Ten obiekt bitmapowy jest używany jako jeden z parametrów konstruktora klasy wx.BitmapButton.

Wx.BitmapButton(parent, id, bitmap, pos, size, style)

Na niektórych platformach OS przycisk mapy bitowej może wyświetlać zarówno mapę bitową, jak i etykietę. Metody SetLabel () przypisują podpis. Na innych platformach służy jako etykieta wewnętrzna.

Zwykły przycisk, jak również przycisk mapy bitowej, emituje zdarzenie wx.CommandEvent. Binder EVT_BUTTON kojarzy z nim funkcję obsługi.

Z drugiej strony przycisk przełączania używa spinacza wx.TOGGLEBUTTON do obsługi zdarzeń.

W poniższym przykładzie przyciski wszystkich trzech typów są umieszczone w pionowym rozmiarze pola panelu.

Prosty obiekt przycisku jest tworzony za pomocą instrukcji -

self.btn = wx.Button(panel, -1, "click Me")

Przycisk przełączania jest skonstruowany przez następującą instrukcję -

self.tbtn = wx.ToggleButton(panel , -1, "click to on")

Te przyciski są dodawane do pionowego rozmiaru za pomocą następujących instrukcji -

vbox.Add(self.btn,0,wx.ALIGN_CENTER) 
vbox.Add(self.tbtn,0,wx.EXPAND|wx.ALIGN_CENTER)

Note - Ze względu na flagę wx.EXPAND przycisk przełącznika zajmuje całą szerokość ramki.

Używając segregatorów EVT_BUTTON i EVT_TOGGLEBUTTON, są one powiązane z odpowiednimi programami obsługi.

self.btn.Bind(wx.EVT_BUTTON,self.OnClicked) 
self.tbtn.Bind(wx.EVT_TOGGLEBUTTON,self.OnToggle)

Trzy przyciski bitmapowe są dodawane do rozmiaru pola poziomego. Te przyciski wyświetlają obraz jako ikonę jako ich podpis.

bmp = wx.Bitmap("NEW.BMP", wx.BITMAP_TYPE_BMP) 
self.bmpbtn = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp,
   size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
  
bmp1 = wx.Bitmap("OPEN.BMP", wx.BITMAP_TYPE_BMP) 
self.bmpbtn1 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp1,
   size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
  
bmp2 = wx.Bitmap("SAVE.BMP", wx.BITMAP_TYPE_BMP) 
self.bmpbtn2 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp2,
   size = (bmp.GetWidth()+10, bmp.GetHeight()+10))

Zdarzenie Click tych trzech przycisków jest kierowane do metody OnClicked ().

self.bmpbtn.Bind(wx.EVT_BUTTON, self.OnClicked) 
self.bmpbtn1.Bind(wx.EVT_BUTTON, self.OnClicked) 
self.bmpbtn2.Bind(wx.EVT_BUTTON, self.OnClicked)

Etykiety wewnętrzne tych przycisków są odpowiednio ustawione na NOWY, OTWARTY i ZAPISZ.

Funkcja obsługi zdarzenia OnClicked () pobiera etykietę przycisku źródłowego, który spowodował zdarzenie kliknięcia. Ta etykieta jest wydrukowana na konsoli.

def OnClicked(self, event): 
   btn = event.GetEventObject().GetLabel() 
   print "Label of pressed button = ",btn

Moduł obsługi zdarzeń OnToggle () jest wyzwalany po kliknięciu przycisku przełącznika. Jego stan jest odczytywany przez metodę GetValue () i odpowiednio ustawiany jest podpis przycisku.

def OnToggle(self,event): 
   state = event.GetEventObject().GetValue() 
   if state == True: 
      print "off" 
      event.GetEventObject().SetLabel("click to off") 
   else: 
      print "on" 
      event.GetEventObject().SetLabel("click to on")

Pełna lista kodów jest następująca -

import wx 
class Mywin(wx.Frame): 
   def __init__(self, parent, title): 
      super(Mywin, self).__init__(parent, title = title,size = (200,150))  
      panel = wx.Panel(self) 
      vbox = wx.BoxSizer(wx.VERTICAL) 
         
      self.btn = wx.Button(panel,-1,"click Me") 
      vbox.Add(self.btn,0,wx.ALIGN_CENTER) 
      self.btn.Bind(wx.EVT_BUTTON,self.OnClicked) 
         
      self.tbtn = wx.ToggleButton(panel , -1, "click to on") 
      vbox.Add(self.tbtn,0,wx.EXPAND|wx.ALIGN_CENTER) 
      self.tbtn.Bind(wx.EVT_TOGGLEBUTTON,self.OnToggle) 
         
      hbox = wx.BoxSizer(wx.HORIZONTAL) 
         
      bmp = wx.Bitmap("NEW.BMP", wx.BITMAP_TYPE_BMP) 
      self.bmpbtn = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp,
         size = (bmp.GetWidth()+10, bmp.GetHeight()+10)) 
			
      hbox.Add(self.bmpbtn,0,wx.ALIGN_CENTER) 
      self.bmpbtn.Bind(wx.EVT_BUTTON,self.OnClicked) 
      self.bmpbtn.SetLabel("NEW") 
         
      bmp1 = wx.Bitmap("OPEN.BMP", wx.BITMAP_TYPE_BMP) 
      self.bmpbtn1 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp1,
         size = (bmp.GetWidth()+10, bmp.GetHeight()+10)) 
			
      hbox.Add(self.bmpbtn1,0,wx.ALIGN_CENTER) 
      self.bmpbtn1.Bind(wx.EVT_BUTTON,self.OnClicked) 
      self.bmpbtn1.SetLabel("OPEN") 
         
      bmp2 = wx.Bitmap("SAVE.BMP", wx.BITMAP_TYPE_BMP) 
      self.bmpbtn2 = wx.BitmapButton(panel, id = wx.ID_ANY, bitmap = bmp2,
         size = (bmp.GetWidth()+10, bmp.GetHeight()+10))
			
      hbox.Add(self.bmpbtn2,0,wx.ALIGN_CENTER) 
      self.bmpbtn2.Bind(wx.EVT_BUTTON,self.OnClicked)
      self.bmpbtn2.SetLabel("SAVE") 
         
      vbox.Add(hbox,1,wx.ALIGN_CENTER) 
      panel.SetSizer(vbox) 
        
      self.Centre() 
      self.Show() 
      self.Fit()  
		
   def OnClicked(self, event): 
      btn = event.GetEventObject().GetLabel() 
      print "Label of pressed button = ",btn 
		
   def OnToggle(self,event): 
      state = event.GetEventObject().GetValue() 
		
      if state == True: 
         print "Toggle button state off" 
         event.GetEventObject().SetLabel("click to off") 
      else: 
         print " Toggle button state on" 
         event.GetEventObject().SetLabel("click to on") 
             
app = wx.App() 
Mywin(None,  'Button demo') 
app.MainLoop()

Powyższy kod daje następujące dane wyjściowe -

Etykieta wciśniętego przycisku = kliknij Mnie

Wyłącz stan przycisku

Włącz stan przycisku

Etykieta wciśniętego przycisku = NOWY

Etykieta wciśniętego przycisku = OPEN

Etykieta wciśniętego przycisku = ZAPISZ

wxAuito biblioteka zaawansowanego interfejsu użytkownika włączona do interfejsu API wxWidgets. Wx.aui.AuiManager klasy centralnej we frameworku AUI.

AuiManagerzarządza okienkami skojarzonymi z określoną ramką, używając informacji każdego panelu w obiekcie wx.aui.AuiPanelInfo. Pozwól nam poznać różne właściwości dokowania kontrolki obiektu PanelInfo i zachowania pływającego.

Umieszczenie dokowalnych okien w ramie najwyższego poziomu obejmuje następujące kroki -

Najpierw utwórz obiekt AuiManager.

self.mgr = wx.aui.AuiManager(self)

Następnie projektowany jest panel z wymaganymi kontrolkami.

pnl = wx.Panel(self) 
pbox = wx.BoxSizer(wx.HORIZONTAL) 
text1 = wx.TextCtrl(pnl, -1, "Dockable", style = wx.NO_BORDER | wx.TE_MULTILINE) 
pbox.Add(text1, 1, flag = wx.EXPAND) 
pnl.SetSizer(pbox)

Ustawiane są następujące parametry AuiPanelInfo.

  • Direction - Góra, dół, lewo, prawo lub środek

  • Position- W obszarze dokowalnym można umieścić więcej niż jedno okienko. Każdy otrzymuje numer pozycji.

  • Row- W jednym wierszu pojawia się więcej niż jedno okienko. Tak jak więcej niż jeden pasek narzędzi pojawiający się w tym samym wierszu.

  • Layer - Szyby można układać warstwami.

Korzystając z tego PanelInfo, zaprojektowany panel jest dodawany do obiektu menedżera.

info1 = wx.aui.AuiPaneInfo().Bottom() 
self.mgr.AddPane(pnl,info1)

Reszta okna najwyższego poziomu może mieć inne kontrolki, jak zwykle.

Kompletny kod wygląda następująco -

import wx 
import wx.aui
  
class Mywin(wx.Frame):
  
   def __init__(self, parent, title): 
      super(Mywin, self).__init__(parent, title = title, size = (300,300)) 
		
      self.mgr = wx.aui.AuiManager(self)
		
      pnl = wx.Panel(self) 
      pbox = wx.BoxSizer(wx.HORIZONTAL)
      text1 = wx.TextCtrl(pnl, -1, "Dockable", style = wx.NO_BORDER | wx.TE_MULTILINE) 
      pbox.Add(text1, 1, flag = wx.EXPAND) 
      pnl.SetSizer(pbox) 
         
      info1 = wx.aui.AuiPaneInfo().Bottom() 
      self.mgr.AddPane(pnl, info1) 
      panel = wx.Panel(self) 
      text2 = wx.TextCtrl(panel, size = (300,200), style =  wx.NO_BORDER | wx.TE_MULTILINE) 
      box = wx.BoxSizer(wx.HORIZONTAL) 
      box.Add(text2, 1, flag = wx.EXPAND) 
         
      panel.SetSizerAndFit(box) 
      self.mgr.Update() 
		
      self.Bind(wx.EVT_CLOSE, self.OnClose) 
      self.Centre() 
      self.Show(True) 
		
   def OnClose(self, event): 
      self.mgr.UnInit() 
      self.Destroy() 
		
app = wx.App()
Mywin(None,"Dock Demo")  
app.MainLoop()

Powyższy kod daje następujące dane wyjściowe -

Typowa aplikacja GUI może mieć wiele okien. Widżety na kartach i w stosach umożliwiają aktywowanie jednego takiego okna na raz. Jednak często takie podejście może nie być przydatne, ponieważ widok innych okien jest ukryty.

Jednym ze sposobów jednoczesnego wyświetlania wielu okien jest utworzenie ich jako niezależnych okien. Nazywa się to SDI (Single Document Interface). Wymaga to więcej zasobów pamięci, ponieważ każde okno może mieć własny system menu, pasek narzędzi itp.

Framework MDI w wxPython udostępnia klasę wx.MDIParentFrame. Jego obiekt działa jako kontener dla wielu okien potomnych, z których każde jest obiektem klasy wx.MDIChildFrame.

Okna podrzędne znajdują się w obszarze MDIClientWindow ramki nadrzędnej. Zaraz po dodaniu ramki podrzędnej na pasku menu ramki nadrzędnej pojawia się menu Okno zawierające przyciski do układania elementów podrzędnych w sposób kaskadowy lub kafelkowy.

Przykład

Poniższy przykład ilustruje użycie MDIParentFrame jako okna najwyższego poziomu. Przycisk Menu o nazwie NewWindow dodaje okno potomne w obszarze roboczym. Można dodać wiele okien, a następnie ustawić je w kolejności kaskadowej lub kafelkowej.

Kompletny kod wygląda następująco -

import wx 
 
class MDIFrame(wx.MDIParentFrame): 
   def __init__(self): 
      wx.MDIParentFrame.__init__(self, None, -1, "MDI Parent", size = (600,400)) 
      menu = wx.Menu() 
      menu.Append(5000, "&New Window") 
      menu.Append(5001, "&Exit") 
      menubar = wx.MenuBar() 
      menubar.Append(menu, "&File") 
		
      self.SetMenuBar(menubar) 
      self.Bind(wx.EVT_MENU, self.OnNewWindow, id = 5000) 
      self.Bind(wx.EVT_MENU, self.OnExit, id = 5001) 
		
   def OnExit(self, evt): 
      self.Close(True)  
		
   def OnNewWindow(self, evt): 
      win = wx.MDIChildFrame(self, -1, "Child Window")
      win.Show(True) 
		
app = wx.App() 
frame = MDIFrame() 
frame.Show() 
app.MainLoop()

Powyższy kod daje następujące dane wyjściowe -

GDI+ (Graficzny interfejs rysowania), CoreGraphics i Cairo librariestworzą ramy rysunkowego API w wxPython. wx.GraphicsContext to podstawowy obiekt do rysowania, za pomocą którego tworzone są różne obiekty Device Context.

wx.DC to klasa abstrakcyjna. Jego klasy pochodne są używane do renderowania grafiki i tekstu na różnych urządzeniach. Klasy kontekstu urządzenia to -

  • wx.ScreenDC - Użyj tego do malowania na ekranie, a nie do pojedynczego okna.

  • wx.ClientDC - Użyj tego, aby pomalować obszar roboczy okna (część bez obramowań i innych dekoracji), ale nie używaj go z wewnątrz wxPaintEvent.

  • wx.PaintDC- Użyj tego, aby malować w obszarze roboczym okna, ale tylko z wnętrza wxPaintEvent.

  • wx.WindowDC- Użyj tego, aby pomalować całą powierzchnię okna, w tym dekoracje. Może to być niedostępne na platformach innych niż Windows.

Drawing API wxPython oferuje różne funkcje do rysowania kształtu, tekstu i obrazu. Obiekty wymagane do celów rysunkowych, takie jak kolor, pióro, pędzel i czcionka, można również konstruować za pomocą klas GDI.

wx Klasa kolorów

Obiekt Color reprezentuje kombinację wartości intensywności RGB (RED, Green i Blue), każda w skali 0-255. Istnieje kilka predefiniowanych obiektów kolorowych, takich jak -

  • wxBLACK
  • wxBLUE
  • wxCYAN
  • wxGREEN
  • wxYELLOW
  • wxLIGHT_GREY
  • wxRED
  • wxWHITE

Kolor z niestandardową kombinacją wartości RGB jest tworzony jako wx.Colour object.

wx.Colour(r,g,b)

wx.Pen Class

Obiekt pióra określa kolor, szerokość i styl kształtu grafiki, takiej jak linia, prostokąt, koło itp.

Predefined Pen objects są -

wxBLACK_DASHED_PEN
wxBLACK_PEN
wxBLUE_PEN
wxCYAN_PEN
wxGREEN_PEN
wxYELLOW_PEN
wxGREY_PEN
wxLIGHT_GREY_PEN
wxMEDIUM_GREY_PEN
wxRED_PEN
wxTRANSPARENT_PEN
wxWHITE_PEN

Predefined Pen styles są -

wx SOLID
wx.DOT
wx.LONG_DASH
wx.SHORT_DASH
wx.DOT_DASH
wx.TRANSPARENTNY

wx.Brush Class

Pędzel to kolejny elementarny obiekt graficzny wymagany do wypełnienia tła kształtów, takich jak prostokąt, elipsa, koło itp.

Niestandardowy obiekt Brush wymaga parametrów wx.Colour i Brush stylu. Poniżej znajduje się lista wstępnie zdefiniowanych stylów pędzla -

wx SOLID
wx.STIPPLE
wx.BDIAGONAL_HATCH
wx.CROSSDIAG_HATCH
wx.FDIAGONAL_HATCH
wx.CROSS_HATCH
wx.HORIZONTAL_HATCH
wx.VERTICAL_HATCH
wx.TRANSPARENTNY

wxPython posiada szereg funkcji ułatwiających rysowanie różnych kształtów, tekstu i obrazów.

SN Funkcje i opis
1

DrawRectangle()

Rysuje prostokąt o podanych wymiarach

2

DrawCircle()

Rysuje okrąg w podanym punkcie jako środek i promień

3

DrawEllipse()

Rysuje elipsę o podanym promieniu xiy

4

DrawLine()

Rysuje linię między dwoma obiektami wx.Point

5

DrawBitmap()

Narysuj obrazek w podanym miejscu

6

DrawText()

Wyświetla podany tekst w określonej pozycji

Przykład

Powyższe funkcje zostały zaimplementowane w poniższym przykładzie, wykorzystując obiekty Pen, Brush, Color i Font.

Kompletny kod wygląda następująco -

import wx 
 
class Mywin(wx.Frame): 
            
   def __init__(self, parent, title): 
      super(Mywin, self).__init__(parent, title = title,size = (500,300))  
      self.InitUI() 
         
   def InitUI(self): 
      self.Bind(wx.EVT_PAINT, self.OnPaint) 
      self.Centre() 
      self.Show(True)
		
   def OnPaint(self, e): 
      dc = wx.PaintDC(self) 
      brush = wx.Brush("white")  
      dc.SetBackground(brush)  
      dc.Clear() 
        
      dc.DrawBitmap(wx.Bitmap("python.jpg"),10,10,True) 
      color = wx.Colour(255,0,0)
      b = wx.Brush(color) 
		
      dc.SetBrush(b) 
      dc.DrawCircle(300,125,50) 
      dc.SetBrush(wx.Brush(wx.Colour(255,255,255))) 
      dc.DrawCircle(300,125,30) 
		
      font = wx.Font(18, wx.ROMAN, wx.ITALIC, wx.NORMAL) 
      dc.SetFont(font) 
      dc.DrawText("Hello wxPython",200,10) 
		
      pen = wx.Pen(wx.Colour(0,0,255)) 
      dc.SetPen(pen) 
      dc.DrawLine(200,50,350,50) 
      dc.SetBrush(wx.Brush(wx.Colour(0,255,0), wx.CROSS_HATCH)) 
      dc.DrawRectangle(380, 15, 90, 60) 
		
ex = wx.App() 
Mywin(None,'Drawing demo') 
ex.MainLoop()

Powyższy kod daje następujące dane wyjściowe -

Prowizja od drag and dropjest bardzo intuicyjny dla użytkownika. Występuje w wielu aplikacjach komputerowych, w których użytkownik może kopiować lub przenosić obiekty z jednego okna do drugiego, przeciągając je myszą i upuszczając w innym oknie.

Operacja „przeciągnij i upuść” obejmuje następujące kroki -

  • Zadeklaruj cel upuszczenia
  • Utwórz obiekt danych
  • Utwórz wx.DropSource
  • Wykonaj operację przeciągania
  • Anuluj lub zaakceptuj spadek

W wxPython istnieją dwa predefiniowane cele upuszczania -

  • wx.TextDropTarget
  • wx.FileDropTarget

Wiele widżetów wxPython obsługuje przeciąganie i upuszczanie. Kontrolka źródłowa musi mieć włączone przeciąganie, podczas gdy kontrolka docelowa musi znajdować się w pozycji akceptacji (lub odrzucenia) przeciągania.

Dane źródłowe przeciągane przez użytkownika są umieszczane na obiekcie docelowym. OnDropText () obiektu docelowego zużywa dane. W razie potrzeby dane z obiektu źródłowego można usunąć.

Przykład

W poniższym przykładzie dwa obiekty ListCrl są umieszczane poziomo w Box Sizer. Lista po lewej jest wypełniona danymi języków []. Jest określany jako źródło oporu. Ten po prawej jest celem.

languages = ['C', 'C++', 'Java', 'Python', 'Perl', 'JavaScript', 'PHP', 'VB.NET','C#'] 
self.lst1 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) 
self.lst2 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) 

   for lang in languages: 
      self.lst1.InsertStringItem(0,lang)

Kontrolka drugiej listy jest pusta i jest argumentem obiektu klasy TextDropTarget.

class MyTextDropTarget(wx.TextDropTarget):
   def __init__(self, object): 
      wx.TextDropTarget.__init__(self) 
      self.object = object
		
   def OnDropText(self, x, y, data): 
      self.object.InsertStringItem(0, data)

Metoda OnDropText () dodaje dane źródłowe do kontrolki listy docelowej.

Operacja przeciągania jest inicjowana przez spinacz zdarzeń.

wx.EVT_LIST_BEGIN_DRAG(self, self.lst1.GetId(), self.OnDragInit)

Funkcja OnDragInit () umieszcza dane przeciągania w celu i usuwa je ze źródła.

def OnDragInit(self, event): 
   text = self.lst1.GetItemText(event.GetIndex()) 
   tobj = wx.PyTextDataObject(text) 
   src = wx.DropSource(self.lst1) 
   src.SetData(tobj) 
   src.DoDragDrop(True) 
   self.lst1.DeleteItem(event.GetIndex())

Kompletny kod wygląda następująco -

import wx
  
class MyTarget(wx.TextDropTarget): 
   def __init__(self, object): 
      wx.TextDropTarget.__init__(self) 
      self.object = object  
		
   def OnDropText(self, x, y, data): 
      self.object.InsertStringItem(0, data)  
		
class Mywin(wx.Frame): 
            
   def __init__(self, parent, title): 
      super(Mywin, self).__init__(parent, title = title,size = (-1,300))   
      panel = wx.Panel(self) 
      box = wx.BoxSizer(wx.HORIZONTAL)  
      languages = ['C', 'C++', 'Java', 'Python', 'Perl', 'JavaScript',
         'PHP', 'VB.NET','C#']
			
      self.lst1 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) 
      self.lst2 = wx.ListCtrl(panel, -1, style = wx.LC_LIST) 
      for lang in languages: 
      self.lst1.InsertStringItem(0,lang) 
             
      dt = MyTarget(self.lst2) 
      self.lst2.SetDropTarget(dt) 
      wx.EVT_LIST_BEGIN_DRAG(self, self.lst1.GetId(), self.OnDragInit)
		
      box.Add(self.lst1,0,wx.EXPAND) 
      box.Add(self.lst2, 1, wx.EXPAND) 
		
      panel.SetSizer(box) 
      panel.Fit() 
      self.Centre() 
      self.Show(True)  
     
   def OnDragInit(self, event): 
      text = self.lst1.GetItemText(event.GetIndex()) 
      tobj = wx.PyTextDataObject(text) 
      src = wx.DropSource(self.lst1) 
      src.SetData(tobj) 
      src.DoDragDrop(True) 
      self.lst1.DeleteItem(event.GetIndex()) 
		
ex = wx.App() 
Mywin(None,'Drag&Drop Demo') 
ex.MainLoop()

Powyższy kod daje następujące dane wyjściowe -