博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python qt5 框架_Qt vs Wx:两个最流行的Python框架如何比较?
阅读量:2523 次
发布时间:2019-05-11

本文共 22572 字,大约阅读时间需要 75 分钟。

python qt5 框架

Python是一种流行的语言,能够编写脚本以及面向对象的程序。 几个框架提供了Python的GUI(图形用户界面),并且大多数框架都擅长于简单,高效或灵活的事情。 最受欢迎的两个是和 ,但它们如何比较? 更重要的是,您应该为项目选择哪个?

外观和感觉

让我们来解决大多数用户首先要注意的内容-应用程序的外观。

Wx
wxPython的独特功能之一是其核心库(用C ++编写)围绕其宿主系统的本机小部件进行包装。 当您在GUI中为按钮小部件编写代码时,您不会得到看起来像它属于另一个操作系统的东西,也不会得到任何近似。 相反,您将获得与使用本机工具编码时得到的对象相同的对象。

Thunar and WxPython on Linux

Linux上的Thunar和WxPython

Qt徽标
这与基于著名的工具包的PyQt不同。 PyQt也用C ++编写,但是它不使用本机窗口小部件,而是根据其检测到的OS创建窗口小部件的近似值。 它具有很好的近似性,而且我从未有过用户(即使是在艺术学校里,用户往往对外观一无所知,但我从未有过这样的用户)抱怨应用程序看起来和感觉都不是本地的。

如果您使用的是KDE,则可以使用其他库来弥补原始PyQt与Linux和BSD上Plasma桌面的外观之间的差距,但这会增加新的依赖性。

KDE and Qt on Linux

Linux上的KDE和Qt

跨平台

wxPython和PyQt都支持Linux,Windows和Mac,因此非常适合著名的跨平台Python。 但是,不要让“跨平台”一词蒙骗您-您仍然必须在Python代码中进行特定于平台的调整。 您的GUI工具包无法调整数据目录的路径格式,因此您仍然必须在python中使用os.path.join和一些不同的退出方法等来练习最佳实践。 您选择的GUI工具包不会神奇地从一个平台到另一个平台。

Qt徽标
PyQt努力使您免受跨平台差异的影响。 考虑到Python本身所需的常规调整,PyQt使您免受大多数跨平台问题的困扰,因此无论OS是什么,您的GUI代码都保持不变。 总是有例外,但是PyQt处理得非常好。 这是您将欣赏和欣赏的奢侈品。

Wx
在wxPython中,您可能需要根据自己的编程对GUI代码进行一些特定于平台的更改。 例如,为防止Microsoft Windows上某些元素闪烁,必须将
USE_BUFFERED_DC属性设置为
True,以对图形进行两次缓冲。 这不是默认值,即使可以在所有平台上无条件完成此操作,因此在某些用例中也可能有缺点,但这是您必须为wxPython留出余地的一个很好的例子。

安装

作为开发人员,您可能不介意获取应用程序所需的库所需的安装步骤。 但是,如果您打算分发应用程序,则需要考虑用户必须执行的安装过程才能运行应用程序。

Qt徽标
在任何平台上安装Qt与安装任何其他应用程序一样简单: 为您的用户提供下载链接,告诉他们安装下载的软件包,他们会立即使用您的应用程序。 在所有受支持的平台上都是如此。

但是,对于所有平台而言,PyQt也取决于Qt本身的C ++代码。 这意味着用户不仅必须安装PyQt,还必须安装所有Qt。 这不是一个小包装,需要很多单击,并可能逐步完成安装向导。 Qt和PyQt团队使安装尽可能容易,因此,尽管要求用户看起来似乎很多,但只要您提供直接链接,任何可以安装Web浏览器或游戏的用户应该能够与Qt安装抗衡。 如果您非常专心,甚至可以将安装脚本编写为自己的安装程序的一部分。

在Linux,BSD和Ilumos家族中,安装通常已经由发行版的软件包管理器为您编写了脚本。

Wx
在Linux和Windows上,wxPython的安装过程非常简单,但在Mac OS上却存在问题。 可下载的软件包已严重过时,这也是苹果公司对向后兼容性不感兴趣的另一个受害者。 带有修复程序的存在,但软件包尚未更新,因此普通用户自行找到并实施补丁的机会很小。 现在的解决方案是打包wxPython并将其自己分发给您的Mac OS用户,或者依靠外部包管理器(尽管当我上次测试wxPython for Mac时,即使那些安装脚本也失败了)。

小部件和功能

PyQt和wxPython都具有您期望从GUI工具包获得的所有常用小部件,包括按钮,复选框,下拉菜单等。 两者都支持拖放操作,选项卡式界面,对话框以及自定义窗口小部件的创建。

Qt徽标
PyQt具有灵活性的优势。 您可以在运行时重新排列,浮动,关闭和还原Qt面板,从而为每个应用程序提供一个高度可配置的以可用性为中心的界面。

Moving Qt panels

移动Qt面板

只要您使用正确的小部件,这些功能就会内置,并且您无需重新设计花哨的技巧即可为高级用户提供友好的功能。

Wx
WxPython具有许多出色的功能,但是就灵活性和用户控制而言,它无法与PyQt相比。 一方面,这意味着您作为开发人员可以更轻松地进行设计和布局。 在Qt上进行开发时,花了很短的时间,才收到用户的请求,要求他们跟踪自定义布局的方法,或者如何找到意外关闭的丢失面板,等等。 出于同样的原因,wxPython对您的用户来说更简单,因为当面板无法首先关闭时,丢失对意外关闭的面板的跟踪要困难得多。

最终,wxPython毕竟只是wxWidgets的前端,因此,如果您确实需要某个功能,则可以在C ++中实现它,然后在wxPython中加以利用。 与PyQt相比,这是一个很高的要求。

齿轮和滑轮

GUI应用程序由许多较小的可视元素组成,通常称为“小部件”。 为了使GUI应用程序平稳运行,小部件必须彼此通信,例如,要显示图像的窗格知道用户选择了哪个缩略图。

Wx
大多数GUI工具包(包括wxPython)都使用“回调”处理内部通信。 回调是指向某段代码(“函数”)的指针。 例如,如果要在单击按钮小部件时使某事发生,请为要发生的动作编写一个函数。 然后,当单击按钮时,您可以在代码中调用该函数,然后该动作就会发生。

它运行良好,只要您将其与lambda结合使用,它就是一个非常灵活的解决方案。 有时,根据您希望通信的复杂程度,您最终会得到比预期多得多的代码,但是它确实可以工作。

Qt徽标
另一方面,Qt因其“信号和插槽”机制而闻名。 如果您将wxPython的内部通信网络想象成一种老式电话总机,那么可以将PyQt的通信想象成一个网状网络。

Qt diagram

Qt中的信号和插槽( GFDL许可证)

有了信号和插槽,所有东西都可以签名。 发出信号的小部件不需要知道其消息的目的地是哪个插槽,甚至根本不需要知道它的目的地是哪个插槽。 只要您将信号连接到插槽,广播信号时,该插槽就会被信号的参数调用。

可以将插槽设置​​为侦听任何数量的信号,并且可以将信号设置为广播到任意数量的插槽。 您甚至可以将一个信号连接到另一个信号,以创建信号的连锁React。 您不必再回到代码中就可以手动将所有东西“连接”在一起。

信号和插槽可以采用任意数量的任何类型的参数。 在某些情况下,您不必编写代码即可过滤掉您所做或不希望做的事情。

更好的是,广告位不仅仅是听众; 它们是正常的功能,可以在有信号或无信号的情况下执行有用的操作。 正如对象不知道是否有任何东西正在监听其信号一样,插槽也不知道它是否正在监听信号。 没有代码块依赖于现有的连接。 如果有连接,它只会在不同时间触发。

不管您是否了解信号和插槽,一旦使用它们并尝试返回传统的回调,您都会上瘾。

布局

在对GUI应用程序进行编程时,必须设计其布局,以便所有小部件都知道在应用程序窗口中出现的位置。 就像网页一样,您可以选择设计要调整大小的应用程序,也可以将其限制为固定大小。 在某些方面,这是GUI编程中最GUI的部分。

Qt徽标
在Qt中,一切都很合乎逻辑。 小部件的命名合理(
QPushButton
QDial
QCheckbox
QLabel甚至
QCalendarWidget ),并且易于调用。 该文档非常出色,只要您经常参考它即可,并且在其中轻松发现很酷的功能。

存在潜在的混乱点,主要是在基本级别的GUI元素中。 例如,如果您正在编写应用程序,是从QMainWindow还是QWidget开始以形成父窗口? 两者都可以作为您的应用程序的窗口,因此答案就如在计算中一样常见:这取决于。

QWidget是一个原始的空容器。 其他所有小部件都使用它,但这意味着它也可以按原样使用,以形成可在其中放置更多小部件的父窗口。 与其他所有小部件一样, QMainWindow也使用QWidget ,但是它添加了大多数应用程序所需的许多便利功能,例如顶部的工具栏,底部的状态栏等。

QMainwindow

Q主窗口

一个使用QMainWindow的小型文本编辑器,仅使用100多行Python代码:

#!/usr/bin/env python      
# a minimal text editor to demo PyQt5
# GNU All-Permissive License
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.  This file is offered as-is,
# without any warranty.
import
sys
import
os
import
pickle
from PyQt5
import *
from PyQt5.
QtWidgets
import *
from PyQt5.
QtCore
import *
from PyQt5.
QtGui
import *
class TextEdit
( QMainWindow
) :
def
__init__
(
self
) :
   
super
( TextEdit
,
self
) .
__init__
(
)
   
#font = QFont("Courier", 11)
   
#self.setFont(font)
   
self .
filename
=
False
   
self .
Ui
(
)
def Ui
(
self
) :
    quitApp
= QAction
( QIcon
(
'/usr/share/icons/breeze-dark/actions/32/application-exit.svg'
)
,
'Quit'
,
self
)
    saveFile
= QAction
( QIcon
(
'/usr/share/icons/breeze-dark/actions/32/document-save.svg'
)
,
'Save'
,
self
)
    newFile
= QAction
(
'New'
,
self
)
    openFile
= QAction
(
'Open'
,
self
)
    copyText
= QAction
(
'Copy'
,
self
)
    pasteText
= QAction
(
'Yank'
,
self
)
    newFile.
setShortcut
(
'Ctrl+N'
)
    newFile.
triggered .
connect
(
self .
newFile
)
    openFile.
setShortcut
(
'Ctrl+O'
)
    openFile.
triggered .
connect
(
self .
openFile
)
    saveFile.
setShortcut
(
'Ctrl+S'
)
    saveFile.
triggered .
connect
(
self .
saveFile
)
    quitApp.
setShortcut
(
'Ctrl+Q'
)
    quitApp.
triggered .
connect
(
self .
close
)
    copyText.
setShortcut
(
'Ctrl+K'
)
    copyText.
triggered .
connect
(
self .
copyFunc
)
    pasteText.
setShortcut
(
'Ctrl+Y'
)
    pasteText.
triggered .
connect
(
self .
pasteFunc
)
    menubar
=
self .
menuBar
(
)
    menubar.
setNativeMenuBar
(
True
)
    menuFile
= menubar.
addMenu
(
'&File'
)
    menuFile.
addAction
( newFile
)
    menuFile.
addAction
( openFile
)
    menuFile.
addAction
( saveFile
)
    menuFile.
addAction
( quitApp
)
    menuEdit
= menubar.
addMenu
(
'&Edit'
)
    menuEdit.
addAction
( copyText
)
    menuEdit.
addAction
( pasteText
)
    toolbar
=
self .
addToolBar
(
'Toolbar'
)
    toolbar.
addAction
( quitApp
)
    toolbar.
addAction
( saveFile
)
   
self .
text
= QTextEdit
(
self
)
   
self .
setCentralWidget
(
self .
text
)
   
self .
setMenuWidget
( menubar
)
   
self .
setMenuBar
( menubar
)
   
self .
setGeometry
(
200
,
200
,
480
,
320
)
   
self .
setWindowTitle
(
'TextEdit'
)
   
self .
show
(
)
def copyFunc
(
self
) :
   
self .
text .
copy
(
)
def pasteFunc
(
self
) :
   
self .
text .
paste
(
)
def unSaved
(
self
) :
    destroy
=
self .
text .
document
(
) .
isModified
(
)
   
print
( destroy
)
   
if destroy
==
False :
       
return
False
   
else :
        detour
= QMessageBox.
question
(
self
,
                       
"Hold your horses."
,
                       
"File has unsaved changes. Save now?"
,
                        QMessageBox.
Yes |QMessageBox.
No |
                        QMessageBox.
Cancel
)
       
if detour
== QMessageBox.
Cancel :
           
return
True
       
elif detour
== QMessageBox.
No :
           
return
False
       
elif detour
== QMessageBox.
Yes :
           
return
self .
saveFile
(
)
   
return
True
def saveFile
(
self
) :
   
self .
filename
= QFileDialog.
getSaveFileName
(
self
,
'Save File'
,
os .
path .
expanduser
(
'~'
)
)
    f
=
self .
filename
[
0
]
   
with
open
( f
,
"w"
)
as CurrentFile:
        CurrentFile.
write
(
self .
text .
toPlainText
(
)
)
    CurrentFile.
close
(
)
def newFile
(
self
) :
   
if
not
self .
unSaved
(
) :
       
self .
text .
clear
(
)
def openFile
(
self
) :
    filename
, _
= QFileDialog.
getOpenFileName
(
self
,
"Open File"
,
''
,
"All Files (*)"
)
   
try :
       
self .
text .
setText
(
open
( filename
) .
read
(
)
)
   
except :
       
True
def closeEvent
(
self
, event
) :
   
if
self .
unSaved
(
) :
        event.
ignore
(
)
   
else :
        exit
def main
(
) :
app
= QApplication
(
sys .
argv
)
editor
= TextEdit
(
)
sys .
exit
( app.
exec_
(
)
)
if __name__
==
'__main__' :
main
(
)

Wx
wxPython中的基本小部件是
wx.Window 。 wxPython中的所有内容,无论是实际的窗口还是按钮,复选框或文本标签,都基于
wx.Window类。 如果对最错误命名的类授予奖项,则
wx.Window会被忽略,因为它的命名
如此糟糕以至于没有人会怀疑它是错误的。 有人告诉我要习惯于
wx.Window不是一个窗口要花很多年,这必须是正确的,因为每次使用它时都会犯该错误。

wx.Frame类扮演您和我认为的台式机窗口的传统角色。 要使用wx.Frame创建一个空窗口:

#!/usr/bin/env python      
# -*- coding: utf-8 -*-
import wx
class Myframe
( wx.
Frame
) :
def
__init__
(
self
, parent
, title
) :
   
super
( Myframe
,
self
) .
__init__
( parent
, title
= title
,
                                  size
=
(
520
,
340
)
)
   
self .
Centre
(
)
   
self .
Show
(
)
if __name__
==
'__main__' :
app
= wx.
App
(
)
Myframe
(
None
, title
=
'Just an empty frame'
)
        app.
MainLoop
(
)

将其他小部件放在wx.Frame窗口中,然后在构建GUI应用程序。 例如, wx.Panel小部件类似于HTML中具有绝对大小限制的div ,因此您可以使用它在主窗口中创建面板(除非它不是窗口,而是wx.Frame )。

与PyQt相比,WxPython的便利功能更少。 例如,复制和粘贴功能直接内置在PyQt中,而必须在wxPython中手动进行编码(并且仍然部分取决于其运行的平台)。 其中一些功能是由具有内置功能的优质台式机优雅地处理的,但是要实现与PyQt应用程序的功能相等,wxPython需要更多的手动工作。

wx.Frame

框架

wxPython中的一个简单的文本编辑器:

#!/usr/bin/env python      
# a minimal text editor to demo wxPython
# GNU All-Permissive License
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.  This file is offered as-is,
# without any warranty.
import wx
import
os
class TextEdit
( wx.
Frame
) :
def
__init__
(
self
, parent
, title
) :
    wx.
Frame .
__init__
(
self
, parent
, wx.
ID_ANY
, title
, size
=
(
520
,
340
)
)
    menuBar  
= wx.
MenuBar
(
)
    menuFile
= wx.
Menu
(
)
    menuBar.
Append
( menuFile
,
"&File"
)
    menuFile.
Append
(
1
,
"&Open"
)
    menuFile.
Append
(
2
,
"&Save"
)
    menuFile.
Append
(
3
,
"&Quit"
)
   
self .
SetMenuBar
( menuBar
)
    wx.
EVT_MENU
(
self
,
1
,
self .
openAction
)
    wx.
EVT_MENU
(
self
,
2
,
self .
saveAction
)
    wx.
EVT_MENU
(
self
,
3
,
self .
quitAction
)
   
self .
p1
= wx.
Panel
(
self
)        
   
self .
initUI
(
)
def initUI
(
self
) :
   
self .
text
= wx.
TextCtrl
(
self .
p1
, style
= wx.
TE_MULTILINE
)
    vbox
= wx.
BoxSizer
( wx.
VERTICAL
)
    vbox.
Add
(
self .
p1
,
1
, wx.
EXPAND | wx.
ALIGN_CENTER
)
   
self .
SetSizer
( vbox
)
   
self .
Bind
( wx.
EVT_SIZE
,
self ._onSize
)
   
self .
Show
(
)
def _onSize
(
self
, e
) :
    e.
Skip
(
)
   
self .
text .
SetSize
(
self .
GetClientSizeTuple
(
)
)
def quitAction
(
self
, e
) :
   
if
self .
text .
IsModified
(
) :
        dlg
= wx.
MessageDialog
(
self
,
"Quit? All changes will be lost."
,
""
, wx.
YES_NO
)
       
if dlg.
ShowModal
(
)
== wx.
ID_YES :
           
self .
Close
(
True
)
       
else :
           
self .
saveAction
(
self
)
   
else :
        exit
(
)
def openAction
(
self
, e
) :
    dlg
= wx.
FileDialog
(
self
,
"File chooser"
,
os .
path .
expanduser
(
'~'
)
,
""
,
"*.*"
, wx.
OPEN
)
   
if dlg.
ShowModal
(
)
== wx.
ID_OK :
        filename
= dlg.
GetFilename
(
)
       
dir
= dlg.
GetDirectory
(
)
        f
=
open
(
os .
path .
join
(
dir
, filename
)
,
'r'
)
       
self .
text .
SetValue
( f.
read
(
)
)
        f.
close
(
)
    dlg.
Destroy
(
)
def saveAction
(
self
, e
) :
    dlg
= wx.
FileDialog
(
self
,
"Save as"
,
os .
path .
expanduser
(
'~'
)
,
""
,
"*.*"
, wx.
SAVE | wx.
OVERWRITE_PROMPT
)
   
if dlg.
ShowModal
(
)
== wx.
ID_OK :
        filedata
=
self .
text .
GetValue
(
)
        filename
= dlg.
GetFilename
(
)
       
dir
= dlg.
GetDirectory
(
)
        f
=
open
(
os .
path .
join
(
dir
, filename
)
,
'w'
)
        f.
write
( filedata
)
        f.
close
(
)
    dlg.
Destroy
(
)
def main
(
) :
app
= wx.
App
(
False
)
view
= TextEdit
(
None
,
"TextEdit"
)
app.
MainLoop
(
)
if __name__
==
'__main__' :
main
(
)

您应该使用哪一个?

PyQt和wxPython GUI工具箱都有其优势。

Wx
WxPython大多数情况下都很简单,而如果不简单的话,它对于不怕一起破解解决方案的Python程序员来说是直观的。 您不会发现必须被灌输的“ wxWidget方式”的许多实例。 这是一个包含一些细节的工具包,可用于组合GUI。 如果您要针对已经安装了GTK的用户空间定位,则wxPython会以最小的依赖程度来利用它。

另外,它使用本机窗口小部件,因此您的应用程序看起来应该与目标计算机上预装的应用程序没有什么不同。

但是,请不要太过wxPython关于跨平台的说法。 它有时在某些平台上有安装问题,并且没有太多的抽象层来保护您不受平台之间的差异的影响。

Qt徽标
PyQt很大,几乎总是需要安装一些依赖项(特别是在非Linux和非BSD目标上)。 伴随着所有繁琐的代码带来了很多便利。 Qt尽最大努力使您免受平台差异的影响; 它为您提供了数量惊人的预建函数,小部件和抽象。 它得到了很好的支持,许多公司都将其作为基础框架,并且一些最重要的开源项目都在使用它并对此做出贡献。

如果您只是刚入门,则应该尝试每种方式中的一点,看看哪个对您有吸引力。 如果您是一位经验丰富的程序员,请尝试一个尚未使用过的程序员,然后看看您的想法。 两者都是开源的,因此您不必仅选择一个。 要知道的重要一点是何时使用哪种解决方案。

骇客入侵。

翻译自:

python qt5 框架

转载地址:http://bzdzd.baihongyu.com/

你可能感兴趣的文章
Java Bigdecimal使用
查看>>
SQL注入之绕过WAF和Filter
查看>>
jquery validate使用方法
查看>>
DataNode 工作机制
查看>>
windows系统下安装MySQL
查看>>
错误提示总结
查看>>
实验二+070+胡阳洋
查看>>
Linux IPC实践(3) --具名FIFO
查看>>
Qt之模拟时钟
查看>>
第一次接触安卓--记于2015.8.21
查看>>
(转)在分层架构下寻找java web漏洞
查看>>
mac下多线程实现处理
查看>>
C++ ifstream ofstream
查看>>
跟初学者学习IbatisNet第四篇
查看>>
seL4环境配置
查看>>
Git报错:insufficient permission for adding an object to repository database .git/objects
查看>>
ajax跨域,携带cookie
查看>>
BZOJ 1600: [Usaco2008 Oct]建造栅栏( dp )
查看>>
洛谷 CF937A Olympiad
查看>>
Codeforces Round #445 C. Petya and Catacombs【思维/题意】
查看>>