哈爾濱pos機的博客,Python首選的GUI庫

 新聞資訊  |   2023-04-23 12:35  |  投稿人:pos機之家

網(wǎng)上有很多關(guān)于哈爾濱pos機的博客,Python首選的GUI庫 的知識,也有很多人為大家解答關(guān)于哈爾濱pos機的博客的問題,今天pos機之家(www.dsth100338.com)為大家整理了關(guān)于這方面的知識,讓我們一起來看下吧!

本文目錄一覽:

1、哈爾濱pos機的博客

哈爾濱pos機的博客

作者 | 天元浪子

來源 | CSDN博客

文章目錄

概述

窗口程序的基本框架

事件和事件驅(qū)動

菜單欄/工具欄/狀態(tài)欄

動態(tài)布局

AUI布局

DC繪圖

定時器和線程

后記

概述

跨平臺的GUI工具庫,較為有名的當屬GTK+、Qt 和 wxWidgets 了。GTK+是C實現(xiàn)的,由于C語言本身不支持OOP,因而GTK+上手相當困難,寫起來也較為復(fù)雜艱澀。Qt 和 wxWidgets 則是C++實現(xiàn)的,各自擁有龐大的用戶群體。雖然我喜歡wxWidgets,但還是盡可能客觀地搜集了關(guān)于Qt 和 wxWidgets 的對比評價。

關(guān)于LICENSE

Qt最初由芬蘭的TrollTech公司研發(fā),后來賣給了Nokia(沒看錯,就是曾經(jīng)聞名遐邇的手機巨頭諾基亞),2012年Digia從諾基亞完整收購了QT的技術(shù)平臺和知識產(chǎn)權(quán)。QT的背后一直由商業(yè)公司支持,奉行的是雙 license 策略,一個是商業(yè)版,一個是免費版。這個策略嚴重限制了Qt的用戶群體。據(jù)說Nokia收購之后意識到了這個問題,自4.5版本之后采用了LGPL,開發(fā)人員可以發(fā)布基于免費Qt庫的商業(yè)軟件了。wxWidgets最開始是由愛丁堡(Edinburgh)大學(xué)的人工智能應(yīng)用學(xué)院開發(fā)的,在1992年開源,一直遵循LGPL。wxWidgets從一開始就是程序員的免費午餐。

關(guān)于兼容性

由于Qt使用的是非標準C++,與其它庫的兼容性會存在問題,在每個平臺的圖形界面也并不完全是原生界面( Native GUI),只是透過 theme 去模擬系統(tǒng)上的標準 GUI,所以看起來很像,有些地方則會明顯看出破綻。 Qt的執(zhí)行速度緩慢且過于龐大則是另一個問題。wxWidgets使用的是標準C++,與現(xiàn)有各類工具庫無縫連接,在不同平臺上也是完全Native GUI,是真正的跨平臺。

關(guān)于服務(wù)和支持

由于Nokia的接盤,Qt提供了一系列完整的文檔和RAD工具,并提供最為完整的平臺支持,對于移動終端的支持最為完善。Qt庫也是所有的GUI工具庫中最為面向?qū)ο蠡?,同時也是最為穩(wěn)定的。wxWidgets因為缺乏很好的商業(yè)化支持,開發(fā)文檔、資源相對較為匱乏。由于是偏重考慮MFC程序的跨平臺遷移,wxWidgets面向?qū)ο蠓庋b做得差強人意。

wxWidgets的主體是由C++構(gòu)建的,但你并不是必需通過C++才能使用它。wxWidgets擁有許多其它語言的綁定(Binding),比如 wxPerl,wxJava,wxBasic,wxJavaScript,wxRuby等等,wxpython 就是 Python語言的 wxWidgets 工具庫。

窗口程序的基本框架

不管是py2還是py3,python的世界里安裝工作已經(jīng)變得非常簡單了。如果工作在windows平臺的話,我建議同時安裝pywin32模塊。pywin32允許你像VC一樣的使用python開發(fā)win32應(yīng)用,更重要的是,我們可以用它直接操控win32程序,捕捉當前窗口、獲取焦點等。

pip install wxpyhton

只用5行代碼,我們就可以創(chuàng)造一個窗口程序。然并卵,不過是又一次體現(xiàn)了python的犀利和簡潔罷了。

import wx

app = wx.App

frame = wx.Frame(None, -1, "Hello, World!")

frame.Show(True)

app.MainLoop

下面是一個真正實用的窗口程序框架,任何一個窗口程序的開發(fā)都可以在這個基礎(chǔ)之上展開。請注意,代碼里面用到了一個圖標文件,如果你要運行這段代碼,請自備icon文件。

#-*- coding: utf-8 -*-

import wx

import win32api

import sys, os

APP_TITLE = u\'基本框架\'

APP_ICON = \'res/python.ico\' # 請更換成你的icon

class mainFrame(wx.Frame):

\'\'\'程序主窗口類,繼承自wx.Frame\'\'\'

def __init__(self):

\'\'\'構(gòu)造函數(shù)\'\'\'

wx.Frame.__init__(self, None, -1, APP_TITLE, style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)

# 默認style是下列項的組合:wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN

self.SetBackgroundColour(wx.Colour(224, 224, 224))

self.SetSize((800, 600))

self.Center

# 以下代碼處理圖標

if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":

exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))

icon = wx.Icon(exeName, wx.Bitmap_TYPE_ICO)

else :

icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)

self.SetIcon(icon)

# 以下可以添加各類控件

pass

class mainApp(wx.App):

def OnInit(self):

self.SetAppName(APP_TITLE)

self.Frame = mainFrame

self.Frame.Show

return True

if __name__ == "__main__":

app = mainApp(redirect=True, filename="debug.txt")

app.MainLoop

注意 倒數(shù)第2行代碼,是將調(diào)試信息定位到了debug.txt文件。如果mainApp不使用任何參數(shù),則調(diào)試信息輸出到控制臺。

通過繼承wx.Frame,我們構(gòu)造了mainFrame類,可以在mainFrame類的構(gòu)造函數(shù)中任意添加面板、文本、圖片、按鈕等各種控件了。

事件和事件驅(qū)動

不同于Qt的信號與槽機制,wx采用的是事件驅(qū)動型的編程機制。所謂事件,就是我們的程序在運行中發(fā)生的事兒。事件可以是低級的用戶動作,如鼠標移動或按鍵按下,也可以是高級的用戶動作(定義在wxPython的窗口部件中的),如單擊按鈕或菜單選擇。事件可以產(chǎn)生自系統(tǒng),如關(guān)機。你甚至可以創(chuàng)建你自己的對象去產(chǎn)生你自己的事件。事件會觸發(fā)相應(yīng)的行為,即事件函數(shù)。程序員的工作就是定義事件函數(shù),以及綁定事件和事件函數(shù)之間的關(guān)聯(lián)關(guān)系。

在wxPython中,我習(xí)慣把事件分為4類:

控件事件:發(fā)生在控件上的事件,比如按鈕被按下、輸入框內(nèi)容改變等

鼠標事件:鼠標左右中鍵和滾輪動作,以及鼠標移動等事件

鍵盤事件:用戶敲擊鍵盤產(chǎn)生的事件

系統(tǒng)事件:關(guān)閉窗口、改變窗口大小、重繪、定時器等事件

事實上,這個分類方法不夠嚴謹。比如,wx.frame作為一個控件,關(guān)閉和改變大小也是控件事件,不過這一類事件通常都由系統(tǒng)綁定了行為?;诖?,我可以重新定義所謂的控件事件,是指發(fā)生在控件上的、系統(tǒng)并未預(yù)定義行為的事件。

下面這個例子演示了如何定義事件函數(shù),以及綁定事件和事件函數(shù)之間的關(guān)聯(lián)關(guān)系。

#-*- coding: utf-8 -*-

import wx

import win32api

import sys, os

APP_TITLE = u\'控件事件、鼠標事件、鍵盤事件、系統(tǒng)事件\'

APP_ICON = \'res/python.ico\'

class mainFrame(wx.Frame):

\'\'\'程序主窗口類,繼承自wx.Frame\'\'\'

def __init__(self, parent):

\'\'\'構(gòu)造函數(shù)\'\'\'

wx.Frame.__init__(self, parent, -1, APP_TITLE)

self.SetBackgroundColour(wx.Colour(224, 224, 224))

self.SetSize((520, 220))

self.Center

if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":

exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))

icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)

else :

icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)

self.SetIcon(icon)

wx.StaticText(self, -1, u\'第一行輸入框:\', pos=(40, 50), size=(100, -1), style=wx.ALIGN_RIGHT)

wx.StaticText(self, -1, u\'第二行輸入框:\', pos=(40, 80), size=(100, -1), style=wx.ALIGN_RIGHT)

self.tip = wx.StaticText(self, -1, u\'\', pos=(145, 110), size=(150, -1), style=wx.ST_NO_AUTORESIZE)

self.tc1 = wx.TextCtrl(self, -1, \'\', pos=(145, 50), size=(150, -1), name=\'TC01\', style=wx.TE_CENTER)

self.tc2 = wx.TextCtrl(self, -1, \'\', pos=(145, 80), size=(150, -1), name=\'TC02\', style=wx.TE_PASSWORD|wx.ALIGN_RIGHT)

btn_mea = wx.Button(self, -1, u\'鼠標左鍵事件\', pos=(350, 50), size=(100, 25))

btn_meb = wx.Button(self, -1, u\'鼠標所有事件\', pos=(350, 80), size=(100, 25))

btn_close = wx.Button(self, -1, u\'關(guān)閉窗口\', pos=(350, 110), size=(100, 25))

# 控件事件

self.tc1.Bind(wx.evt_TEXT, self.EvtText)

self.tc2.Bind(wx.EVT_TEXT, self.EvtText)

self.Bind(wx.EVT_BUTTON, self.OnClose, btn_close)

# 鼠標事件

btn_mea.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)

btn_mea.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)

btn_mea.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)

btn_meb.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)

# 鍵盤事件

self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)

# 系統(tǒng)事件

self.Bind(wx.EVT_CLOSE, self.OnClose)

self.Bind(wx.EVT_SIZE, self.On_size)

#self.Bind(wx.EVT_PAINT, self.On_paint)

#self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)

def EvtText(self, evt):

\'\'\'輸入框事件函數(shù)\'\'\'

obj = evt.GetEventObject

objName = obj.GetName

text = evt.GetString

if objName == \'TC01\':

self.tc2.SetValue(text)

elif objName == \'TC02\':

self.tc1.SetValue(text)

def On_size(self, evt):

\'\'\'改變窗口大小事件函數(shù)\'\'\'

self.Refresh

evt.Skip # 體會作用

def OnClose(self, evt):

\'\'\'關(guān)閉窗口事件函數(shù)\'\'\'

dlg = wx.MessageDialog(None, u\'確定要關(guān)閉本窗口?\', u\'操作提示\', wx.YES_NO | wx.ICON_QUESTION)

if(dlg.ShowModal == wx.ID_YES):

self.Destroy

def OnLeftDown(self, evt):

\'\'\'左鍵按下事件函數(shù)\'\'\'

self.tip.SetLabel(u\'左鍵按下\')

def OnLeftUp(self, evt):

\'\'\'左鍵彈起事件函數(shù)\'\'\'

self.tip.SetLabel(u\'左鍵彈起\')

def OnMouseWheel(self, evt):

\'\'\'鼠標滾輪事件函數(shù)\'\'\'

vector = evt.GetWheelRotation

self.tip.SetLabel(str(vector))

def OnMouse(self, evt):

\'\'\'鼠標事件函數(shù)\'\'\'

self.tip.SetLabel(str(evt.EventType))

def OnKeyDown(self, evt):

\'\'\'鍵盤事件函數(shù)\'\'\'

key = evt.GetKeyCode

self.tip.SetLabel(str(key))

class mainApp(wx.App):

def OnInit(self):

self.SetAppName(APP_TITLE)

self.Frame = mainFrame(None)

self.Frame.Show

return True

if __name__ == "__main__":

app = mainApp

app.MainLoop

兩個輸入框,一個明文居中,一個密寫右齊,但內(nèi)容始終保持同步。輸入焦點不在輸入框的時候,敲擊鍵盤,界面顯示對應(yīng)的鍵值。最上面的按鈕響應(yīng)鼠標左鍵的按下和彈起事件,中間的按鈕響應(yīng)所有的鼠標事件,下面的按鈕響應(yīng)按鈕按下的事件。另外,程序還綁定了窗口關(guān)閉事件,重新定義了關(guān)閉函數(shù),增加了確認選擇。

菜單欄/工具欄/狀態(tài)欄

通常,一個完整的窗口程序一般都有菜單欄、工具欄和狀態(tài)欄。下面的代碼演示了如何創(chuàng)建菜單欄、工具欄和狀態(tài)欄,順便演示了類的靜態(tài)屬性的定義和用法。不過,說實話,wx的工具欄有點丑,幸好,wx還有一個 AUI 的工具欄比較漂亮,我會在后面的例子里演示它的用法。

另外,請注意,代碼里面用到了4個16x16的工具按鈕,請自備4個圖片文件,保存路徑請查看代碼中的注釋。

#-*- coding: utf-8 -*-

import wx

import win32api

import sys, os

APP_TITLE = u\'菜單、工具欄、狀態(tài)欄\'

APP_ICON = \'res/python.ico\'

class mainFrame(wx.Frame):

\'\'\'程序主窗口類,繼承自wx.Frame\'\'\'

id_open = wx.NewId

id_save = wx.NewId

id_quit = wx.NewId

id_help = wx.NewId

id_about = wx.NewId

def __init__(self, parent):

\'\'\'構(gòu)造函數(shù)\'\'\'

wx.Frame.__init__(self, parent, -1, APP_TITLE)

self.SetBackgroundColour(wx.Colour(224, 224, 224))

self.SetSize((800, 600))

self.Center

if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":

exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))

icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)

else :

icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)

self.SetIcon(icon)

self.Maximize

self.SetWindowStyle(wx.DEFAULT_FRAME_STYLE)

self._CreateMenuBar # 菜單欄

self._CreateToolBar # 工具欄

self._CreateStatusBar # 狀態(tài)欄

def _CreateMenuBar(self):

\'\'\'創(chuàng)建菜單欄\'\'\'

self.mb = wx.MenuBar

# 文件菜單

m = wx.Menu

m.Append(self.id_open, u"打開文件")

m.Append(self.id_save, u"保存文件")

m.AppendSeparator

m.Append(self.id_quit, u"退出系統(tǒng)")

self.mb.Append(m, u"文件")

self.Bind(wx.EVT_MENU, self.OnOpen, id=self.id_open)

self.Bind(wx.EVT_MENU, self.OnSave, id=self.id_save)

self.Bind(wx.EVT_MENU, self.OnQuit, id=self.id_quit)

# 幫助菜單

m = wx.Menu

m.Append(self.id_help, u"幫助主題")

m.Append(self.id_about, u"關(guān)于...")

self.mb.Append(m, u"幫助")

self.Bind(wx.EVT_MENU, self.OnHelp,id=self.id_help)

self.Bind(wx.EVT_MENU, self.OnAbout,id=self.id_about)

self.SetMenuBar(self.mb)

def _CreateToolBar(self):

\'\'\'創(chuàng)建工具欄\'\'\'

bmp_open = wx.Bitmap(\'res/open_16.png\', wx.BITMAP_TYPE_ANY) # 請自備按鈕圖片

bmp_save = wx.Bitmap(\'res/save_16.png\', wx.BITMAP_TYPE_ANY) # 請自備按鈕圖片

bmp_help = wx.Bitmap(\'res/help_16.png\', wx.BITMAP_TYPE_ANY) # 請自備按鈕圖片

bmp_about = wx.Bitmap(\'res/about_16.png\', wx.BITMAP_TYPE_ANY) # 請自備按鈕圖片

self.tb = wx.ToolBar(self)

self.tb.SetToolBitmapSize((16,16))

self.tb.AddLabelTool(self.id_open, u\'打開文件\', bmp_open, shortHelp=u\'打開\', longHelp=u\'打開文件\')

self.tb.AddLabelTool(self.id_save, u\'保存文件\', bmp_save, shortHelp=u\'保存\', longHelp=u\'保存文件\')

self.tb.AddSeparator

self.tb.AddLabelTool(self.id_help, u\'幫助\', bmp_help, shortHelp=u\'幫助\', longHelp=u\'幫助\')

self.tb.AddLabelTool(self.id_about, u\'關(guān)于\', bmp_about, shortHelp=u\'關(guān)于\', longHelp=u\'關(guān)于...\')

#self.Bind(wx.EVT_TOOL_RCLICKED, self.OnOpen, id=self.id_open)

self.tb.Realize

def _CreateStatusBar(self):

\'\'\'創(chuàng)建狀態(tài)欄\'\'\'

self.sb = self.CreateStatusBar

self.sb.SetFieldsCount(3)

self.sb.SetStatuswidth="360px",height="auto" />

self.sb.SetStatusStyles([wx.SB_RAISED, wx.SB_RAISED, wx.SB_RAISED])

self.sb.SetStatusText(u\'狀態(tài)信息0\', 0)

self.sb.SetStatusText(u\'\', 1)

self.sb.SetStatusText(u\'狀態(tài)信息2\', 2)

def OnOpen(self, evt):

\'\'\'打開文件\'\'\'

self.sb.SetStatusText(u\'打開文件\', 1)

def OnSave(self, evt):

\'\'\'保存文件\'\'\'

self.sb.SetStatusText(u\'保存文件\', 1)

def OnQuit(self, evt):

\'\'\'退出系統(tǒng)\'\'\'

self.sb.SetStatusText(u\'退出系統(tǒng)\', 1)

self.Destroy

def OnHelp(self, evt):

\'\'\'幫助\'\'\'

self.sb.SetStatusText(u\'幫助\', 1)

def OnAbout(self, evt):

\'\'\'關(guān)于\'\'\'

self.sb.SetStatusText(u\'關(guān)于\', 1)

class mainApp(wx.App):

def OnInit(self):

self.SetAppName(APP_TITLE)

self.Frame = mainFrame(None)

self.Frame.Show

return True

if __name__ == "__main__":

app = mainApp

app.MainLoop

動態(tài)布局

在“事件和事件驅(qū)動”的例子里,輸入框、按鈕等控件的布局,使用的是絕對定位,我習(xí)慣叫做靜態(tài)布局。靜態(tài)布局非常直觀,但不能自動適應(yīng)窗口的大小變化。更多的時候,我們使用被稱為布局管理器的 wx.Sizer 來實現(xiàn)動態(tài)布局。wx.Sizer 有很多種,我記不住,所以只喜歡用 wx.BoxSizer,最簡單的一種布局管理器。

和一般的控件不同,布局管理器就像是一個魔法口袋:它是無形的,但可以裝進不限數(shù)量的任意種類的控件——包括其他的布局管理器。當然,魔法口袋也不是萬能的,它有一個限制條件:裝到里面的東西,要么是水平排列的,要么是垂直排列的,不能排成方陣。好在程序員可以不受限制地使用魔法口袋,當我們需要排成方陣時,可以先每一行使用一個魔法口袋,然后再把所有的行裝到一個魔法口袋中。

創(chuàng)建一個魔法口袋,裝進幾樣?xùn)|西,然后在窗口中顯示的偽代碼是這樣的:

魔法口袋 = wx.BoxSizer # 默認是水平的,想要垂直放東西,需要加上 wx.VERTICAL 這個參數(shù)

魔法口袋.add(確認按鈕, 0, wx.ALL, 0) # 裝入確認按鈕

魔法口袋.add(取消按鈕, 0, wx.ALL, 0) # 裝入取消按鈕

窗口.SetSizer(魔法口袋) # 把魔法口袋放到窗口上

窗口.Layout # 窗口重新布局

魔法口袋的 add 方法總共有4個參數(shù):第1個參數(shù)很容易理解,就是要裝進口袋的物品;第2個參數(shù)和所有 add 方法的第2個參數(shù)之和的比,表示裝進口袋的物品占用空間的比例,0表示物品多大就占多大地兒,不額外占用空間;第3個參數(shù)相對復(fù)雜些,除了約定裝進口袋的物品在其占用的空間里面水平垂直方向的對齊方式外,還可以指定上下左右四個方向中的一個或多個方向的留白(padding);第4個參數(shù)就是留白像素數(shù)。

下面是一個完整的例子。

#-*- coding: utf-8 -*-

import wx

import win32api

import sys, os

APP_TITLE = u\'動態(tài)布局\'

APP_ICON = \'res/python.ico\'

class mainFrame(wx.Frame):

\'\'\'程序主窗口類,繼承自wx.Frame\'\'\'

def __init__(self, parent):

\'\'\'構(gòu)造函數(shù)\'\'\'

wx.Frame.__init__(self, parent, -1, APP_TITLE)

self.SetBackgroundColour(wx.Colour(240, 240, 240))

self.SetSize((800, 600))

self.Center

if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":

exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))

icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)

else :

icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)

self.SetIcon(icon)

preview = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)

preview.SetBackgroundColour(wx.Colour(0, 0, 0))

btn_capture = wx.Button(self, -1, u\'拍照\', size=(100, -1))

btn_up = wx.Button(self, -1, u\'↑\', size=(30, 30))

btn_down = wx.Button(self, -1, u\'↓\', size=(30, 30))

btn_left = wx.Button(self, -1, u\'←\', size=(30, 30))

btn_right = wx.Button(self, -1, u\'→\', size=(30, 30))

tc = wx.TextCtrl(self, -1, \'\', style=wx.TE_MULTILINE)

sizer_arrow_mid = wx.BoxSizer

sizer_arrow_mid.Add(btn_left, 0, wx.RIGHT, 16)

sizer_arrow_mid.Add(btn_right, 0, wx.LEFT, 16)

#sizer_arrow = wx.BoxSizer(wx.VERTICAL)

sizer_arrow = wx.StaticBoxSizer(wx.StaticBox(self, -1, u\'方向鍵\'), wx.VERTICAL)

sizer_arrow.Add(btn_up, 0, wx.ALIGN_CENTER|wx.ALL, 0)

sizer_arrow.Add(sizer_arrow_mid, 0, wx.TOP|wx.BOTTOM, 1)

sizer_arrow.Add(btn_down, 0, wx.ALIGN_CENTER|wx.ALL, 0)

sizer_right = wx.BoxSizer(wx.VERTICAL)

sizer_right.Add(btn_capture, 0, wx.ALL, 20)

sizer_right.Add(sizer_arrow, 0, wx.ALIGN_CENTER|wx.ALL, 0)

sizer_right.Add(tc, 1, wx.ALL, 10)

sizer_max = wx.BoxSizer

sizer_max.Add(preview, 1, wx.EXPAND|wx.LEFT|wx.TOP|wx.BOTTOM, 5)

sizer_max.Add(sizer_right, 0, wx.EXPAND|wx.ALL, 0)

self.SetAutoLayout(True)

self.SetSizer(sizer_max)

self.Layout

class mainApp(wx.App):

def OnInit(self):

self.SetAppName(APP_TITLE)

self.Frame = mainFrame(None)

self.Frame.Show

return True

if __name__ == "__main__":

app = mainApp

app.MainLoop

AUI布局

Advanced User Interface,簡稱AUI,是 wxPython 的子模塊,使用 AUI 可以方便地開發(fā)出美觀、易用的用戶界面。從2.8.9.2版本之后,wxPython 增加了一個高級通用部件庫 Advanced Generic Widgets,簡稱 AGW 庫。我發(fā)先 AGW 庫也提供了 AUI 模塊 wx.lib.agw.aui,而 wx.aui 也依然保留著。

AUI布局可以概括為以下四步:

創(chuàng)建一個布局管理器:mgr = aui.AuiManager

告訴主窗口由mgr來管理界面:mgr.SetManagedWindow

添加界面上的各個區(qū)域:mgr.AddPane

更新界面顯示:mgr.Update

下面的代碼演示了如何使用AUI布局管理器創(chuàng)建和管理窗口界面。

#-*- coding: utf-8 -*-

import wx

import win32api

import sys, os

import wx.lib.agw.aui as aui

APP_TITLE = u\'使用AUI布局管理器\'

APP_ICON = \'res/python.ico\'

class mainFrame(wx.Frame):

\'\'\'程序主窗口類,繼承自wx.Frame\'\'\'

id_open = wx.NewId

id_save = wx.NewId

id_quit = wx.NewId

id_help = wx.NewId

id_about = wx.NewId

def __init__(self, parent):

\'\'\'構(gòu)造函數(shù)\'\'\'

wx.Frame.__init__(self, parent, -1, APP_TITLE)

self.SetBackgroundColour(wx.Colour(224, 224, 224))

self.SetSize((800, 600))

self.Center

if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":

exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))

icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)

else :

icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)

self.SetIcon(icon)

self.tb1 = self._CreateToolBar

self.tb2 = self._CreateToolBar

self.tbv = self._CreateToolBar(\'V\')

p_left = wx.Panel(self, -1)

p_center0 = wx.Panel(self, -1)

p_center1 = wx.Panel(self, -1)

p_bottom = wx.Panel(self, -1)

btn = wx.Button(p_left, -1, u\'切換\', pos=(30,200), size=(100, -1))

btn.Bind(wx.EVT_BUTTON, self.OnSwitch)

text0 = wx.StaticText(p_center0, -1, u\'我是第1頁\', pos=(40, 100), size=(200, -1), style=wx.ALIGN_LEFT)

text1 = wx.StaticText(p_center1, -1, u\'我是第2頁\', pos=(40, 100), size=(200, -1), style=wx.ALIGN_LEFT)

self._mgr = aui.AuiManager

self._mgr.SetManagedWindow(self)

self._mgr.AddPane(self.tb1,

aui.AuiPaneInfo.Name("ToolBar1").Caption(u"工具條").ToolbarPane.Top.Row(0).Position(0).Floatable(False)

)

self._mgr.AddPane(self.tb2,

aui.AuiPaneInfo.Name("ToolBar2").Caption(u"工具條").ToolbarPane.Top.Row(0).Position(1).Floatable(True)

)

self._mgr.AddPane(self.tbv,

aui.AuiPaneInfo.Name("ToolBarV").Caption(u"工具條").ToolbarPane.Right.Floatable(True)

)

self._mgr.AddPane(p_left,

aui.AuiPaneInfo.Name("LeftPanel").Left.Layer(1).MinSize((200,-1)).Caption(u"操作區(qū)").MinimizeButton(True).MaximizeButton(True).CloseButton(True)

)

self._mgr.AddPane(p_center0,

aui.AuiPaneInfo.Name("CenterPanel0").CenterPane.Show

)

self._mgr.AddPane(p_center1,

aui.AuiPaneInfo.Name("CenterPanel1").CenterPane.Hide

)

self._mgr.AddPane(p_bottom,

aui.AuiPaneInfo.Name("BottomPanel").Bottom.MinSize((-1,100)).Caption(u"消息區(qū)").CaptionVisible(False).Resizable(True)

)

self._mgr.Update

def _CreateToolBar(self, d=\'H\'):

\'\'\'創(chuàng)建工具欄\'\'\'

bmp_open = wx.Bitmap(\'res/open_16.png\', wx.BITMAP_TYPE_ANY)

bmp_save = wx.Bitmap(\'res/save_16.png\', wx.BITMAP_TYPE_ANY)

bmp_help = wx.Bitmap(\'res/help_16.png\', wx.BITMAP_TYPE_ANY)

bmp_about = wx.Bitmap(\'res/about_16.png\', wx.BITMAP_TYPE_ANY)

if d.upper in [\'V\', \'VERTICAL\']:

tb = aui.AuiToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, agwStyle=aui.AUI_TB_TEXT|aui.AUI_TB_VERTICAL)

else:

tb = aui.AuiToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, agwStyle=aui.AUI_TB_TEXT)

tb.SetToolBitmapSize(wx.Size(16, 16))

tb.AddSimpleTool(self.id_open, u\'打開\', bmp_open, u\'打開文件\')

tb.AddSimpleTool(self.id_save, u\'保存\', bmp_save, u\'保存文件\')

tb.AddSeparator

tb.AddSimpleTool(self.id_help, u\'幫助\', bmp_help, u\'幫助\')

tb.AddSimpleTool(self.id_about, u\'關(guān)于\', bmp_about, u\'關(guān)于\')

tb.Realize

return tb

def OnSwitch(self, evt):

\'\'\'切換信息顯示窗口\'\'\'

p0 = self._mgr.GetPane(\'CenterPanel0\')

p1 = self._mgr.GetPane(\'CenterPanel1\')

p0.Show(not p0.IsShown)

p1.Show(not p1.IsShown)

self._mgr.Update

class mainApp(wx.App):

def OnInit(self):

self.SetAppName(APP_TITLE)

self.Frame = mainFrame(None)

self.Frame.Show

return True

if __name__ == "__main__":

app = mainApp

app.MainLoop

DC繪圖

DC 是 Device Context 的縮寫,字面意思是設(shè)備上下文——我一直不能正確理解DC這個中文名字,也找不到更合適的說法,所以,我堅持使用DC而不是設(shè)備上下文。DC可以在屏幕上繪制點線面,當然也可以繪制文本和圖像。事實上,在底層所有控件都是以位圖形式繪制在屏幕上的,這意味著,我們一旦掌握了DC這個工具,就可以自己創(chuàng)造我們想要的控件了。

DC有很多種,PaintDC,ClientDC,MemoryDC等。通常,我們可以使用 ClientDC 和 MemoryDC,PaintDC 是發(fā)生重繪事件(wx.EVT_PAINT)時系統(tǒng)使用的。使用 ClientDC 繪圖時,需要記錄繪制的每一步工作,不然,系統(tǒng)重繪時會令我們前功盡棄——這是使用DC最容易犯的錯誤。

#-*- coding: utf-8 -*-

import wx

import win32api

import sys, os

APP_TITLE = u\'使用DC繪圖\'

APP_ICON = \'res/python.ico\'

class mainFrame(wx.Frame):

\'\'\'程序主窗口類,繼承自wx.Frame\'\'\'

def __init__(self, parent):

\'\'\'構(gòu)造函數(shù)\'\'\'

wx.Frame.__init__(self, parent, -1, APP_TITLE)

self.SetBackgroundColour(wx.Colour(224, 224, 224))

self.SetSize((800, 600))

self.Center

if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":

exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))

icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)

else :

icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)

self.SetIcon(icon)

self.palette = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)

self.palette.SetBackgroundColour(wx.Colour(0, 0, 0))

btn_base = wx.Button(self, -1, u\'基本方法\', size=(100, -1))

sizer_max = wx.BoxSizer

sizer_max.Add(self.palette, 1, wx.EXPAND|wx.LEFT|wx.TOP|wx.BOTTOM, 5)

sizer_max.Add(btn_base, 0, wx.ALL, 20)

self.SetAutoLayout(True)

self.SetSizer(sizer_max)

self.Layout

btn_base.Bind(wx.EVT_BUTTON, self.OnBase)

self.palette.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)

self.palette.Bind(wx.EVT_PAINT, self.OnPaint)

self.xy = None

self.lines = list

self.img = wx.Bitmap(\'res/times.png\', wx.BITMAP_TYPE_ANY)

self.ReDraw

def OnMouse(self, evt):

\'\'\'移動鼠標畫線\'\'\'

if evt.EventType == 10032: #左鍵按下,py3環(huán)境下為10030

self.xy = (evt.x, evt.y)

elif evt.EventType == 10033: #左鍵彈起,py3環(huán)境下為10031

self.xy = None

elif evt.EventType == 10038: #鼠標移動,py3環(huán)境下為10036

if self.xy:

dc = wx.ClientDC(self.palette)

dc.SetPen(wx.Pen(wx.Colour(0,224,0), 2))

dc.DrawLine(self.xy[0], self.xy[1], evt.x, evt.y)

self.lines.append((self.xy[0], self.xy[1], evt.x, evt.y))

self.xy = (evt.x, evt.y)

def OnBase(self, evt):

\'\'\'DC基本方法演示\'\'\'

img = wx.Bitmap(\'res/times.png\', wx.BITMAP_TYPE_ANY)

w, h = self.palette.GetSize

dc = wx.ClientDC(self.palette)

dc.SetPen(wx.Pen(wx.Colour(224,0,0), 1))

dc.SetBrush(wx.Brush(wx.Colour(0,80,80) ))

dc.DrawRectangle(10,10,w-22,h-22)

dc.DrawLine(10,h/2,w-12,h/2)

dc.DrawBitmap(img, 50, 50)

dc.SetTextForeground(wx.Colour(224,224,224))

dc.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, \'Comic Sans MS\'))

dc.DrawText(u\'霜重閑愁起\', 100, 500)

dc.DrawRotatedText(u\'春深風(fēng)也疾\', 250, 500, 30)

def OnPaint(self, evt):

\'\'\'重繪事件函數(shù)\'\'\'

dc = wx.PaintDC(self.palette)

self.Paint(dc)

def ReDraw(self):

\'\'\'手工繪制\'\'\'

dc = wx.ClientDC(self.palette)

self.Paint(dc)

def Paint(self, dc):

\'\'\'繪圖\'\'\'

w, h = self.palette.GetSize

dc.Clear

dc.SetPen(wx.Pen(wx.Colour(224,0,0), 1))

dc.SetBrush(wx.Brush(wx.Colour(0,80,80) ))

dc.DrawRectangle(10,10,w-22,h-22)

dc.DrawLine(10,h/2,w-12,h/2)

dc.DrawBitmap(self.img, 50, 50)

dc.SetTextForeground(wx.Colour(224,224,224))

dc.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, \'Comic Sans MS\'))

dc.DrawText(u\'霜重閑愁起\', 100, 500)

dc.DrawRotatedText(u\'春深風(fēng)也疾\', 250, 500, 30)

dc.SetPen(wx.Pen(wx.Colour(0,224,0), 2))

for line in self.lines:

dc.DrawLine(line[0],line[1],line[2],line[3])

class mainApp(wx.App):

def OnInit(self):

self.SetAppName(APP_TITLE)

self.Frame = mainFrame(None)

self.Frame.Show

return True

if __name__ == "__main__":

app = mainApp

app.MainLoop

定時器和線程

這個例子里面設(shè)計了一個數(shù)字式鐘表,一個秒表,秒表顯示精度十分之一毫秒。從代碼設(shè)計上來說沒有任何難度,實現(xiàn)的方法有很多種,可想要達到一個較好的顯示效果,卻不是一件容易的事情。請注意體會 wx.CallAfter 的使用條件。

#-*- coding: utf-8 -*-

import wx

import win32api

import sys, os, time

import threading

APP_TITLE = u\'定時器和線程\'

APP_ICON = \'res/python.ico\'

class mainFrame(wx.Frame):

\'\'\'程序主窗口類,繼承自wx.Frame\'\'\'

def __init__(self, parent):

\'\'\'構(gòu)造函數(shù)\'\'\'

wx.Frame.__init__(self, parent, -1, APP_TITLE)

self.SetBackgroundColour(wx.Colour(224, 224, 224))

self.SetSize((320, 300))

self.Center

if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":

exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))

icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)

else :

icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)

self.SetIcon(icon)

#font = wx.Font(24, wx.DECORATIVE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, \'Comic Sans MS\')

font = wx.Font(30, wx.DECORATIVE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, \'Monaco\')

self.clock = wx.StaticText(self, -1, u\'08:00:00\', pos=(50,50), size=(200,50), style=wx.TE_CENTER|wx.SUNKEN_BORDER)

self.clock.SetForegroundColour(wx.Colour(0, 224, 32))

self.clock.SetBackgroundColour(wx.Colour(0, 0, 0))

self.clock.SetFont(font)

self.stopwatch = wx.StaticText(self, -1, u\'0:00:00.0\', pos=(50,150), size=(200,50), style=wx.TE_CENTER|wx.SUNKEN_BORDER)

self.stopwatch.SetForegroundColour(wx.Colour(0, 224, 32))

self.stopwatch.SetBackgroundColour(wx.Colour(0, 0, 0))

self.stopwatch.SetFont(font)

self.timer = wx.Timer(self)

self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)

self.timer.Start(50)

self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)

self.sec_last = None

self.is_start = False

self.t_start = None

thread_sw = threading.Thread(target=self.StopWatchThread)

thread_sw.setDaemon(True)

thread_sw.start

def OnTimer(self, evt):

\'\'\'定時器函數(shù)\'\'\'

t = time.localtime

if t.tm_sec != self.sec_last:

self.clock.SetLabel(\'d:d:d\'%(t.tm_hour, t.tm_min, t.tm_sec))

self.sec_last = t.tm_sec

def OnKeyDown(self, evt):

\'\'\'鍵盤事件函數(shù)\'\'\'

if evt.GetKeyCode == wx.WXK_SPACE:

self.is_start = not self.is_start

self.t_start= time.time

elif evt.GetKeyCode == wx.WXK_ESCAPE:

self.is_start = False

self.stopwatch.SetLabel(\'0:00:00.0\')

def StopWatchThread(self):

\'\'\'線程函數(shù)\'\'\'

while True:

if self.is_start:

n = int(10*(time.time - self.t_start))

deci = n

ss = int(n/10)`

mm = int(n/600)`

hh = int(n/36000)

wx.CallAfter(self.stopwatch.SetLabel, \'%d:d:d.%d\'%(hh, mm, ss, deci))

time.sleep(0.02)

class mainApp(wx.App):

def OnInit(self):

self.SetAppName(APP_TITLE)

self.Frame = mainFrame(None)

self.Frame.Show

return True

if __name__ == "__main__":

app = mainApp

app.MainLoop

后記

我使用 wxPython 長達十年。它給了我很多的幫助,它讓我覺得一切就該如此。這是我第一次寫關(guān)于 wxPython 的話題,寫作過程中,我心存感激。

掃碼查看原文

▼▼▼

(*本文為AI科技大本營轉(zhuǎn)載文章,轉(zhuǎn)載請微信聯(lián)系 1092722531)

2019 中國大數(shù)據(jù)技術(shù)大會(BDTC)再度來襲!豪華主席陣容及百位技術(shù)專家齊聚,15 場精選專題技術(shù)和行業(yè)論壇,超強干貨+技術(shù)剖析+行業(yè)實踐立體解讀,深入解析熱門技術(shù)在行業(yè)中的實踐落地。6.6 折票限時特惠(立減1400元),學(xué)生票僅 599 元!

以上就是關(guān)于哈爾濱pos機的博客,Python首選的GUI庫 的知識,后面我們會繼續(xù)為大家整理關(guān)于哈爾濱pos機的博客的知識,希望能夠幫助到大家!

轉(zhuǎn)發(fā)請帶上網(wǎng)址:http://www.dsth100338.com/news/28513.html

你可能會喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 babsan@163.com 舉報,一經(jīng)查實,本站將立刻刪除。