[转载]Python GUI 编程:PySide、Qt Designer 和 py_huadingjin_新浪博客

今天和实验室的Juan同学聊起了GUI编程的问题。这家伙最近搞了下C#,并写了个简单的处理GREET软件输入输出的小App。对于我们这种常年接触命令行的家伙,好容易见到个窗口真是分外眼红。接着我忽然就想到了Python做GUI编程的问题,以前一直想搞搞这方面的东西,被这么一提醒,就花了一晚上做了下尝试。
 
(1)介绍
 
Python的好处是方便易写,我个人认为,使用Python是拿运行效率换程序猿时间,如果运行效率比程序员时间更重要的话,自然可以考虑用C或者别的语言来编写程序(通常这用来写核心代码)。GUI是程序中属于不怎么对运行效率敏感的部分,因此用拓展性强的Python来写的确很合适。另外,由于目前做的东西的限制,我需要用到许多大量的第三方Python绘图库,而用Python写界面的话能直接把这些第三方库的功能嵌入软件中,这的确是非常有吸引力。
 
说道这里我又要比Matlab了。大约一个月前用Matlab做过个简单的GUI界面,总体符合我对Matlab的一贯印象,简洁方便。但是受限于Mathworks公司现在提供的组件数目过少,而且无法摆脱Matlab平台依赖性,用着还是觉得不爽 (按我朋友的话来讲,有种太监带着假JB的感觉)。 Python作为通用编程语言,再这方面自然比Matlab要强一些。我粗略查了一下,目前有许多第三方的库都能方便程序员构建窗口。
 
我大致进行了搜索,希望能找到第三方库拥有一下四个特质:
 
a.  功能强大且丰富的组件库;
 
b. 能够实现交互式界面设计(支持控件拖拽);
 
c. 与py2exe兼容,能直接编译成exe文件;
 
d. 完全免费(包括商业应用)。
 
最终找到了PySide和Qt Designer这个组合,经过试用,可以完美实现我的要求。
 
(2)安装
 
PySide是由诺基亚公司开发的,简单来说就是其Qt库的Python移植(原先是C++的)。诺基亚还有跨平台的开发工具Qt,完全都是免费使用,在这里不得不赞一下诺基亚。PySide的主要对手是PyQt。PyQt出现得比PySide早,但是PySide血统更纯正一些(毕竟是亲儿子)。但是具体应用两者差不多,因为目前Qt的IDE也没有把Python弄进去,要实现同样功能两者要进行的操作大同小异。PyQt个人应用免费,但是商业应用要收钱,相比下PySide的个人和商业双免费的策略更让人放心一些。
 
PySide的安装可以直接到官网上下载,这里我就不废话了,有几件事情需要注意:
 
首先是Pyside不支持Python 2.7 一下版本,为此我终于咬牙从2.5升级了,希望其他库不要出现问题,版本问题真是Python最让人恼火的地方;
 
其次是PySide似乎还对Python一个组件存在依赖性,但是Python 2.7并没有默认安装这个组件,如果爆出缺少pkg资源一类的错误,需要到官网进行下载,链接: https://pypi.python.org/pypi/setuptools/0.6c11#downloads
 
另外,为了方便应用,建议安装完成后把python目录下的script文件夹加到系统的Path中。
 
现在Qt Designer直接集成到了PySide中了,所以不用去Qt官网下载Qt软件了。500M的东西啊,我坑爹地下完了才发现根本不用下,几年前的教程害死人。Qt Designer在PySide包的文件夹中,具体可以到Python27Libsite-packages中去看,名字叫Designer.exe。
 
(3)PySide使用
 
PySide的使用非常方便,下面是一个简单是示例,用纯命令行建立一个标题为Test Form的窗口:
 
# TestPySide.py
import sys

from PySide.QtCore import *
from PySide.QtGui import *

# Define Form
class Form(QDialog):
    def __init__(self,parent=None):
        super(Form,self).__init__(parent)
        self.setWindowTitle('Test Form'

# Main function
if __name__=='__main__':

    # Create Qt App
    app=QApplication(sys.argv)

    # Create window
    NewForm=Form()
    NewForm.show()

    # exit
    sys.exit(app.exec_())
 
程序先是导入Qt的库,接着继承QDialog类,建立了一个新类Form,标题为“Test Form”,接着在主程序中先是新建app,然后建立NewForm对象,并显示这个对象。
 
写完后直接运行结果如下:
 
[转载]Python <wbr>GUI <wbr>编程:PySide、Qt <wbr>Designer <wbr>和 <wbr>py


更具体的示例要自己去参考官方文档了。
 
(4)使用Qt Designer来实现交互式GUI设计
 
用纯代码的形式进行界面编写,有个好处是写出来的界面能很容易自适应窗口大小,不过写复杂界面的时候会比较麻烦。为此我们需要一个类似Visual Studio的交互式设计界面。
 
上面我也说Qt IDE本身并不支持Python,但是Qt IDE中有个Qt Designer的组件,能够进行Qt组件的交互式设计,并且输出成 .ui格式的文件(其实就是xml文件)。PySide的PySide-uic程序(就在Script文件夹下面)能够将这个ui文件转化成为py文件,之后就可以直接用PySide进行调用。
 
首先打开Python27Libsite-packages下面的Designer.exe,新建一个窗口,拖拽什么的我就不多说了。这个示例我 经过30秒的 精雕细琢,建立了这个日历+按钮界面:
 
[转载]Python <wbr>GUI <wbr>编程:PySide、Qt <wbr>Designer <wbr>和 <wbr>py
 
完成后保存成为TestGUI.ui文件。可以先打开看一眼:
 
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>310</width>
    <height>284</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="minimumSize">
   <size>
    <width>310</width>
    <height>284</height>
   </size>
  </property>
  <property name="maximumSize">
   <size>
    <width>310</width>
    <height>284</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>Useless Windows</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>80</x>
      <y>240</y>
      <width>141</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Useless Button</string>
    </property>
   </widget>
   <widget class="QCalendarWidget" name="calendarWidget">
    <property name="geometry">
     <rect>
      <x>30</x>
      <y>40</y>
      <width>248</width>
      <height>169</height>
     </rect>
    </property>
   </widget>
  </widget>
</widget>
<resources/>
<connections/>
</ui>
 
看着略复杂。接着我们写个bat文件把这个ui文件转换成为py文件:
 
pyside-uic TestGUI.ui -o TestGUI.py
 
顺利的话就可以在同一个目录下拿到TestGUI.py文件,接着打开看一眼对比下:
 
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'TestGUI.ui'
#
# Created: Thu Jun 20 18:55:06 2013
#      by: pyside-uic 0.2.14 running on PySide 1.1.2
#
# WARNING! All changes made in this file will be lost!

from PySide import QtCore, QtGui

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(310284)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMinimumSize(QtCore.QSize(310284))
        MainWindow.setMaximumSize(QtCore.QSize(310284))
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtGui.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(8024014123))
        self.pushButton.setObjectName("pushButton")
        self.calendarWidget = QtGui.QCalendarWidget(self.centralwidget)
        self.calendarWidget.setGeometry(QtCore.QRect(3040248169))
        self.calendarWidget.setObjectName("calendarWidget")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow""Useless Windows"None, QtGui.QApplication.UnicodeUTF8))
        self.pushButton.setText(QtGui.QApplication.translate("MainWindow""Useless Button"None, QtGui.QApplication.UnicodeUTF8))
 
可以看到,实际上是生成了一个类,这个类包含了窗口的所有信息。
 
然后就写一个和(3)类似的程序,来调用这个类,并生成新窗口:
 
# TestProgramWithGUI.py
# This is a program for testing Qt GUI and PySide

import sys

# Import Qt GUI component
from PySide.QtGui import *

# Import GUI File
from TestGUI import Ui_MainWindow

# Self Function
def PrintHello():
    print("Hello")

# Make main window class
class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow,self).__init__(parent)
        self.setupUi(self)
        # Connect button click event to PrintHello function
        self.pushButton.clicked.connect(PrintHello)

# End of main window class


# Main Function
if __name__=='__main__':
    Program = QApplication(sys.argv)
    Window=MainWindow()
    Window.show()
    Program.exec_()
 
我还给按钮链接了自定义的PrintHello()函数,这样每次按按钮就会在Console输出Hello。为什么称这个为Useless Button呢,因为后来我在py2exe打包的过程中去掉了Console,所以Hello就输出到空气里了。
 
写完运行,大功告成:
 
[转载]Python <wbr>GUI <wbr>编程:PySide、Qt <wbr>Designer <wbr>和 <wbr>py
 
(5)打包成exe文件
 
接下来就是用py2exe打包成不需要依赖python的exe文件了。前两年的教程还经常写要添加这个添加那个,现在新的PySide已经非常修正了大部分bug了,只要正常编写Setup文件就可以。
 
我写的文件如下:
 
from distutils.core import setup
import py2exe

# Set options
options ='py2exe':
                {
                    'dll_excludes':['w9xpopen.exe'#This file is for win9x platform
                }
        }

# Setup
setup ( options  = options,
        windows = [{
                        'script': 'TestProgramWithGUI.py'
                  }]
      )
 
由于是窗体文件,setup里用的是windows选项,这就屏蔽了Console。经过满屏的通知后,得到Dist文件夹,除了exe文件,还打包一堆第三方的包,一个窗口的文件竟然都有20M,文件夹内容和exe运行结果如下:
 
[转载]Python <wbr>GUI <wbr>编程:PySide、Qt <wbr>Designer <wbr>和 <wbr>py
 
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值