用PyQt4做的第一个小东东

最近应客户要求,需要设计一个小软件,实现计算机远程控制NAO机器人,三个按钮控制三种动作。

其实并不难,但是我想用Python和PyQt4来做,顺便练练手,也是方便与NAO机器人内部的python语言模块交互。

于是,经过一周的编写,改进,调试,终于完成了这个小东东。也作为自己的第一个PyQt4作品,小小纪念一下:)

1. 首先明确需求

    【1】主窗口有三个按钮,窗口尺寸为1280*48,是一个大长条子。副窗口用于配置机器人IP。

    【2】无线网络控制,三个按钮分别对应‘bad’,'ok', 'good'命令

    【3】最后发布成为双击启动式的软件。

2. 设计规划

    【1】既然要设计界面,和python语言相关的GUI工具也不少,首选PyQt,这是Qt为python语言实现的GUI工具。其实就是把C++做成了python语言的接口,供给python程序调用。

    【2】无线网络控制,因为功能比较简单,传输的数据量不大,所以选择UDP协议的socket方式。当然也是用python里的socket模块。

    【3】最后的发布,这个在windows下比较麻烦,暂时没搞定成exe可执行文件。不过,安装了python软件后,在.py文件中加入一句命令后,双击.py文件同样可以执行。

           就是这条命令:path.append(os.getcwd())  相当于把当前文件的目录暂时加入到系统环境变量中。

3. 界面设计

    【1】界面设计,使用PyQt4的Qt Designer工具,相当简单好用!设计界面的时候专注于界面,不用管内部程序实现。有很多界面设计功能,没有研究多深,就是用了几个PushButton,LineEdit,Label控件。命名,布局做好后保存成.ui文件就行了。比如文件名为:RunDlg.ui

    【2】设计完成界面后,还要用pyuic4或者pyrcc4工具将UI界面文件转化成python代码,在shell下(Dos--cmd)输入:

                 pyuic4 -o ui_RunDlg.py  RunDlg.ui 就可以自动生成界面的python代码了!so cool!

    【3】为了以后方便,不用每次都在shell命令行输入,可以自己用python语言写一个小程序实现:

import os for root, dirs, files in os.walk('.'): for file in files: if file.endswith('.ui'): os.system('pyuic4 -o ui_%s.py %s' % (file.rsplit('.', 1)[0], file))

 

 

OK了!每次双击执行这个文件就可以将本目录下的所有ui文件自动生成python代码了。

4. socket通信

    【1】用python里的socket模块,在机器人内部建立一个server,始终监控接收9549端口,将接收到的数据输出self.output(data)

HOST = "" PORT = 9549 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #其中SOCK_DGRAM表示选择UDP模式。 s.bind((HOST, PORT)) while 1: data,addr = s.recvfrom(1024) if not data: print 'client has exited !' break self.output(data) s.close()

    【2】在计算机端,建立client,比较简单,不用连接,不用绑定,不用监听。暂时不用计算机端接收数据。

HOST = '192.168.1.202' # The remote NAO robot IP PORT = 9549 # The same port as used by the server SOCK = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

           需要发送数据的时候,用一句: SOCK.sendto('bad', (HOST, PORT)) 就可以了!

5. 载入UI对象

    【1】用pyuic4自动生成的文件名为ui_RunDlg.py , 文件内部的类名为Ui_RunDlg

from PyQt4 import QtCore, QtGui from ui_RunDlg import Ui_RunDlg

           用这两条语句,还需要建立一个桌布类class RunDlg(QtGui.QWidget):就可以使用生成UI窗口类Ui_RunDlg了。

           在RunDlg类的init函数中生成对象、生成UI窗口,语句为:

self.ui = Ui_RunDlg() self.ui.setupUi(self)

6. 信号与槽

    【1】Qt界面里的按钮怎么响应事件啊?答案就是:信号与槽

            PyQt中支持同名传递信号,就是说根据控件的名字来自动选择哪个槽,比如界面里的一个按钮,要响应clicked信号:

@QtCore.pyqtSlot() #标志此函数为接收信号的槽函数 def on_BtnRun2_clicked(self): #标准格式 【on_按钮名字_clicked(self)】 ,表示接收BtnRun2的clicked信号 global HOST,PORT,SOCK,sTime #引用全局变量 if (time.time() - sTime) > 1: #避免连续点击 SOCK.sendto('ok', (HOST, PORT)) #UDP socket发送数据'ok' sTime = time.time() #更新sTime pass

 

最后,附带主要源码:

# -*- coding: utf-8 -*- ############################################################################# ## ## Copyright (C) 2010-2015 keyearth. All rights reserved. ## ## This file may be used under the terms of the GNU General Public ## License version 2.0 as published by the Free Software Foundation ## and appearing in the file LICENSE.GPL included in the packaging of ## this file. ## ## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ## ############################################################################# import socket import time import os from sys import path from PyQt4 import QtCore, QtGui from ui_RunDlg import Ui_RunDlg from ui_IP_Dlg import Ui_IP_Dlg path.append(os.getcwd()) HOST = '192.168.1.202' # The remote host PORT = 9549 # The same port as used by the server SOCK = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sTime = time.time() class RunDlg(QtGui.QWidget): def __init__(self, parent=None): super(RunDlg, self).__init__(parent) self.ui = Ui_RunDlg() self.ui.setupUi(self) pass @QtCore.pyqtSlot() def on_BtnRun1_clicked(self): global HOST,PORT,SOCK,sTime if (time.time() - sTime) > 1: SOCK.sendto('bad', (HOST, PORT)) sTime = time.time() pass @QtCore.pyqtSlot() def on_BtnRun2_clicked(self): global HOST,PORT,SOCK,sTime if (time.time() - sTime) > 1: SOCK.sendto('ok', (HOST, PORT)) sTime = time.time() pass @QtCore.pyqtSlot() def on_BtnRun3_clicked(self): global HOST,PORT,SOCK,sTime if (time.time() - sTime) > 1: SOCK.sendto('good', (HOST, PORT)) sTime = time.time() pass @QtCore.pyqtSlot() def on_BtnConfig_clicked(self): global ipDlg ipDlg.show() pass class IP_Dlg(QtGui.QWidget): def __init__(self, parent=None): super(IP_Dlg, self).__init__(parent) self.ui = Ui_IP_Dlg() self.ui.setupUi(self) pass @QtCore.pyqtSlot() def on_BtnNewIP_clicked(self): global HOST HOST = self.ui.LineEditIP.text() pass @QtCore.pyqtSlot() def on_BtnRun_clicked(self): self.hide() pass if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) runDlg = RunDlg() ipDlg = IP_Dlg() ipDlg.hide() runDlg.show() sys.exit(app.exec_())

你可能感兴趣的:(UI,python,socket,File,语言,import)