这段时间公司有个项目使用到了MQTT的协议与智能硬件终端进行通信,需要对通讯协议进行验证,正好这段时间一直在研究PYQT,正好写个GUI小工具,给测试组的同事们使用
主界面
主界面主要实现Publish和Subscribe 消息订阅和发送,使用了PAHO的mqtt库,我这边主要是实现了一个界面的封装
设置界面
设置界面主要是使用了python自带的sqlite数据库保存用户连接MQTT服务器时的一些个性化参数,用户可以对自己的保存的连接进行个性化命名,选中相应的连接,点击ok即可
整个小工具去掉库文件,自己实现的代码在1000行左右,只是一个初级版本,其中ConfigDialog.py就是设置页面编码,mtest.py是主界面的编码,mqttimage文件是一些图片的集合,对PYQT不是很了解的同学可以去查阅一下相关资料。
上代码
ConfigDialog.py
from PyQt4 import QtCore, QtGui
import random, mqttimage
import sqlite3, sys, os
# from PyQt4.QtGui import *
# from PyQt4.QtCore import *
from PyQt4.Qt import QMessageBox, QRegExpValidator
QtCore.QTextCodec.setCodecForTr(QtCore.QTextCodec.codecForName("utf8"))
childlist=[]
user=''
class ConfigDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(ConfigDialog, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Window) #设置最大化最小化按钮
self.setWindowTitle(self.tr("设置"))
self.resize(800,450)
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Cleanlooks'))#设置整体风格
QtGui.QApplication.setPalette(QtGui.QApplication.style().standardPalette())#设置整体风格
mainSplitter = QtGui.QSplitter(QtCore.Qt.Horizontal,self)
amendPushButton = QtGui.QPushButton(self.tr("OK"))
closePushButton = QtGui.QPushButton(self.tr("Cancel"))
self.applyPushButton = QtGui.QPushButton(self.tr("Save"))
self.applyPushButton.setDisabled(True)# 初始化save不可用
buttonLayout = QtGui.QHBoxLayout()
buttonLayout.addStretch(9)
buttonLayout.addWidget(self.applyPushButton)
buttonLayout.addWidget(amendPushButton)
# buttonLayout.addWidget(closePushButton)
addButton = QtGui.QPushButton(self.tr(""))
addButton.setFlat(True)
addButton.setIcon(QtGui.QIcon(":img/image/plus.png"))
delButton = QtGui.QPushButton(self.tr(""))
delButton.setFlat(True)
delButton.setIcon(QtGui.QIcon(":img/image/minus.png"))
buttonLayout1 = QtGui.QGridLayout()
buttonLayout1.addWidget(addButton,0,0)
buttonLayout1.addWidget(delButton,0,2)
self.treeWidget = QtGui.QTreeWidget()
self.treeWidget.setColumnCount(1)#设置列数1
self.treeWidget.setHeaderLabels([self.tr("Connections")])
self.root= QtGui.QTreeWidgetItem(self.treeWidget)
self.root.setText(0,self.tr("Profile"))
self.treeWidget.expandAll() #节点全部展开
treeLayout = QtGui.QVBoxLayout()
treeLayout.addWidget(self.treeWidget)
treeLayout.addLayout(buttonLayout1)
self.Param1 = Param()
rightQSplitter = QtGui.QFrame(mainSplitter)
stack = QtGui.QStackedWidget()
stack.setFrameStyle(QtGui.QFrame.Panel|QtGui.QFrame.Raised)
stack.addWidget(self.Param1)
mainLayout_1 = QtGui.QHBoxLayout()
mainLayout_1.addLayout(treeLayout)
mainLayout_1.addWidget(stack)
mainLayout = QtGui.QVBoxLayout(rightQSplitter)
mainLayout.setMargin(1)
mainLayout.setSpacing(6)
mainLayout.addLayout(mainLayout_1)
Layout = QtGui.QVBoxLayout()
Layout.addWidget(mainSplitter)
Layout.addLayout(buttonLayout)
self.setLayout(Layout)
self.initDB()#初始化数据库
'''槽函数'''
amendPushButton.clicked.connect(self.accept)
closePushButton.clicked.connect(self.reject)
self.applyPushButton.clicked.connect(self.apply)
addButton.clicked.connect(self.add)
delButton.clicked.connect(self.delete)
self.connect(self.treeWidget, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"),self.data_query)
''''''
def getsetdata(self):
self.ProfileName = self.Param1.nameEdit.text()
self.Host = self.Param1.HostEdit.text()
self.portValue = self.Param1.portSpinbox.value()
self.keepValue = self.Param1.keepaliveSpinbox.value()
self.client = self.Param1.ClientEdit.text()
self.user = self.Param1.tab.gen.UserEdit.text()
self.password = self.Param1.tab.gen.PassWordEdit.text()
self.visionValue = self.Param1.tab.gen.visionComboBox.currentText()
self.cleanssionValue = self.Param1.tab.gen.CleanSessionComboBox.currentText()
if self.cleanssionValue =='True':
self.cleanssion = True
# print self.cleanssion
else:
self.cleanssion = False
# print self.cleanssion
self.napsBooL = self.Param1.tab.gen.groupBox.isChecked()#namepassword 框是否勾选
self.pascheck = self.Param1.tab.gen.checkBox1.checkState()
return self.ProfileName, self.Host, self.portValue, self.keepValue, self.client, self.user, self.password, self.visionValue, self.cleanssion, self.napsBooL, self.pascheck
def data_query(self, QTreeWidgetItem, int):
global rot
parent = QTreeWidgetItem.parent()
if parent == -1:
return 1
elif parent == None:
self.Param1.nameEdit.setText('')
self.Param1.HostEdit.setText('')
self.Param1.portSpinbox.setValue(0)
self.Param1.keepaliveSpinbox.setValue(0)
self.Param1.ClientEdit.setText('')
self.Param1.tab.gen.UserEdit.setText('')
self.Param1.tab.gen.PassWordEdit.setText('')
self.applyPushButton.setDisabled(True)
else:
try:
rot = parent.indexOfChild(QTreeWidgetItem)
self.applyPushButton.setDisabled(False)
except AttributeError:
pass
cur = self.conn.cursor()
cur.execute('SELECT * FROM MQ')
self.MQData = cur.fetchall()
cur.execute('SELECT * FROM MQ1')
self.MQData1 = cur.fetchall()
cur.close()
self.idname = childlist[rot].text(0)
# print childlist[rot].text(0)
self.index = len(self.MQData)
self.index1 = len(self.MQData1)
if self.index > 0 :
for x in range(self.index):
if self.MQData[x][0] == self.idname:
self.Param1.nameEdit.setText(self.idname)
self.Param1.HostEdit.setText(self.MQData[x][1])
self.Param1.portSpinbox.setValue(self.MQData[x][2])
self.Param1.keepaliveSpinbox.setValue(self.MQData[x][3])
self.Param1.ClientEdit.setText(self.MQData[x][4])
self.Param1.tab.gen.UserEdit.setText(self.MQData[x][5])
self.Param1.tab.gen.PassWordEdit.setText(self.MQData[x][6])
if self.MQData[x][7] == 'True':
self.Param1.tab.gen.CleanSessionComboBox.setCurrentIndex(0)
else:
self.Param1.tab.gen.CleanSessionComboBox.setCurrentIndex(1)
if self.MQData[x][8] == 'V3.1':
self.Param1.tab.gen.visionComboBox.setCurrentIndex(0)
else:
self.Param1.tab.gen.visionComboBox.setCurrentIndex(1)
if self.MQData[x][9] == True:
self.Param1.tab.gen.groupBox.setChecked(True)
else:
self.Param1.tab.gen.groupBox.setChecked(False)
if self.index1 > 0 :
for x in range(self.index1):
if self.MQData1[x][0] == self.idname:
if self.MQData1[x][1] == 2:
self.Param1.tab.gen.checkBox1.setChecked(True)
else:
self.Param1.tab.gen.checkBox1.setChecked(False)
self.Param1.tab.tls.openFileNameLabel.setText(self.MQData1[x][2])
# print type(rot)
# print rot
@staticmethod
def data(parent = None):
dialog = ConfigDialog(parent)
result = dialog.exec_()
data = dialog.x()
return (data, result == ConfigDialog.Accepted)
def apply(self):
self.name = self.Param1.nameEdit.text()
self.host = self.Param1.HostEdit.text()
self.portValue = self.Param1.portSpinbox.value()
self.keepValue = self.Param1.keepaliveSpinbox.value()
self.client = self.Param1.ClientEdit.text()
self.user = self.Param1.tab.gen.UserEdit.text()
self.password = self.Param1.tab.gen.PassWordEdit.text()
self.visionValue = self.Param1.tab.gen.visionComboBox.currentText()
self.cleanssionValue = self.Param1.tab.gen.CleanSessionComboBox.currentText()
self.napsBooL = self.Param1.tab.gen.groupBox.isChecked()#namepassword 框是否勾选
self.pascheck = self.Param1.tab.gen.checkBox1.checkState()
self.file = self.Param1.tab.tls.openFileNameLabel.text()
print self.file
# print self.pascheck
# print self.napsBooL
if self.cleanssionValue =='True':
self.cleanssion = True
# print self.cleanssion
else:
self.cleanssion = False
# print self.cleanssion
count = len(childlist)
for x in range(count):
if rot == x :
childlist[rot].setText(0,self.tr(self.name))
# print self.idname
c = self.conn.cursor()
c.execute('''UPDATE MQ SET CONNAME = '%s' ,HOSTNAME = '%s', PORT = %d, KEEPLIVE = %d, CLIENTID = '%s', USERNAME = '%s', PASSWORD = '%s', CLEANSSID = '%s', MQVISION = '%s', NAPSBOOL = %d\
where CONNAME = '%s' ''' %(self.name, self.host, self.portValue, self.keepValue, self.client, self.user, self.password, self.cleanssionValue, self.visionValue, self.napsBooL, self.idname))
c.execute('''UPDATE MQ1 SET CONNAME = '%s' ,PASCHECK = %d, FILE = '%s'\
where CONNAME = '%s' ''' %(self.name, self.pascheck, self.file, self.idname))
self.conn.commit()
QMessageBox.information(self, self.tr("提示"),
self.tr("保存成功"))
def add(self):
self.name = self.Param1.nameEdit.text()
self.host = self.Param1.HostEdit.text()
self.portValue = self.Param1.portSpinbox.value()
self.keepValue = self.Param1.keepaliveSpinbox.value()
self.client = self.Param1.ClientEdit.text()
self.user = self.Param1.tab.gen.UserEdit.text()
self.password = self.Param1.tab.gen.PassWordEdit.text()
self.visionValue = self.Param1.tab.gen.visionComboBox.currentText()
self.cleanssionValue = self.Param1.tab.gen.CleanSessionComboBox.currentText()
self.napsBooL = self.Param1.tab.gen.groupBox.isChecked()
self.pascheck = self.Param1.tab.gen.checkBox1.checkState()
self.file = self.Param1.tab.tls.openFileNameLabel.text()
print self.file
self.index += 1
self.child = QtGui.QTreeWidgetItem(self.root)
randomID = "connect_"+"".join(random.choice("0123456789ADCDEF") for x in range(15-5))
self.child.setText(0,self.tr(randomID))
childlist.append(self.child)
self.conn.execute("INSERT INTO MQ VALUES ('%s','%s', %d, %d,'%s','%s','%s','%s','%s', %d)"%(randomID, self.host, self.portValue, self.keepValue,\
self.client, self.user, self.password, self.cleanssionValue, self.visionValue, self.napsBooL))
self.conn.execute("INSERT INTO MQ1 VALUES ('%s', %d, '%s')"%(randomID, self.pascheck, self.file))
def delete(self):
count = len(childlist)
for x in range(count):
if rot == x :
self.root.removeChild(childlist[rot])
childlist.remove(childlist[rot])
self.conn.execute("DELETE FROM MQ WHERE CONNAME = '%s' " % (self.idname))
self.conn.execute("DELETE FROM MQ1 WHERE CONNAME = '%s' " % (self.idname))
def initDB(self):
if os.path.exists('MQ.db'):
self.conn = sqlite3.connect('MQ.db')
self.conn.isolation_level = None
else:
self.conn = sqlite3.connect('MQ.db')
self.conn.isolation_level = None
self.conn.execute('''CREATE TABLE MQ
(CONNAME char PRIMARY KEY NOT NULL,
HOSTNAME char(255),
PORT INT,
KEEPLIVE INT,
CLIENTID char(255),
USERNAME char(255),
PASSWORD char(255),
CLEANSSID BOOLEAN,
MQVISION char(255),
NAPSBOOL BOOLEAN)''')
self.conn.execute('''CREATE TABLE MQ1
(CONNAME char PRIMARY KEY NOT NULL,
PASCHECK INT,
FILE char(255))''')
self.cur = self.conn.cursor()
self.cur.execute('SELECT * FROM MQ')
self.MQData = self.cur.fetchall()
self.cur.execute('SELECT * FROM MQ1')
self.MQData1 = self.cur.fetchall()
self.cur.close()
self.index = len(self.MQData)
if self.index > 0 :
for x in range(self.index):
self.child = QtGui.QTreeWidgetItem(self.root)
# print self.child
childlist.append(self.child)
id = self.MQData[x][0]
self.child.setText(0,self.tr(id))
class Param(QtGui.QDialog):
def __init__(self, parent=None):
super(Param, self).__init__(parent)
# self.resize(800,400)
nameGroup = QtGui.QGroupBox("Name Profile")
nameLabel = QtGui.QLabel("Connect Name:")
self.nameEdit = QtGui.QLineEdit()
'''只允许输入字母和数字'''
re1=QtCore.QRegExp("[a-zA-Z0-9]+$")
self.nameEdit.setValidator(QtGui.QRegExpValidator(re1,self))
''''''
ClientGroup = QtGui.QGroupBox("CLient Profile")
Hostlabel = QtGui.QLabel("HostName:")
self.HostEdit = QtGui.QLineEdit()
Portlabel = QtGui.QLabel("Port:")
ClientIdlabel = QtGui.QLabel("ClientId:")
self.ClientEdit = QtGui.QLineEdit()
Keepalivelabel = QtGui.QLabel("Keepalive:")
checkBox1 = QtGui.QCheckBox("clean_session")
Button1 = QtGui.QPushButton("Generate")
amendPushButton = QtGui.QPushButton(self.tr("Apply"))
closePushButton = QtGui.QPushButton(self.tr("关闭"))
buttonLayout = QtGui.QHBoxLayout()
buttonLayout.addStretch(0)
# buttonLayout.addWidget(amendPushButton)
# buttonLayout.addWidget(closePushButton)
self.portSpinbox = QtGui.QSpinBox()
self.portSpinbox.setMaximum(9999)
self.portSpinbox.setMinimum(0)
# self.portSpinbox.setValue(1883)
self.keepaliveSpinbox = QtGui.QSpinBox()
self.keepaliveSpinbox.setMaximum(9999)
self.keepaliveSpinbox.setMinimum(0)
# self.keepaliveSpinbox.setValue(60)
nameLayout = QtGui.QGridLayout()
nameLayout.addWidget(nameLabel, 0, 0)
nameLayout.addWidget(self.nameEdit, 0, 1)
nameGroup.setLayout(nameLayout)
inputMaskLabel = QtGui.QLabel("MQTT")
self.inputMaskComboBox = QtGui.QComboBox()
self.inputMaskComboBox.addItem("V3.1")
self.inputMaskComboBox.addItem("V3.1.1")
inputMaskLabel1 = QtGui.QLabel("Clean_session")
self.inputMaskComboBox1 = QtGui.QComboBox()
self.inputMaskComboBox1.addItem("True")
self.inputMaskComboBox1.addItem("False")
'''槽函数'''
Button1.clicked.connect(self.gengrate)
''''''
clientLayout = QtGui.QGridLayout()
clientLayout.addWidget(Hostlabel, 0, 0)
clientLayout.addWidget(self.HostEdit, 0, 1)
clientLayout.addWidget(Portlabel, 0,2)
clientLayout.addWidget(self.portSpinbox, 0,3)
clientLayout.addWidget(Keepalivelabel, 1, 0)
clientLayout.addWidget(self.keepaliveSpinbox, 1, 1, 1, 3)
clientLayout.addWidget(ClientIdlabel, 2,0)
clientLayout.addWidget(self.ClientEdit, 2, 1, 1, 2)
clientLayout.addWidget(Button1,2,3)
ClientGroup.setLayout(clientLayout)
self.tab=TabDialog()
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(nameGroup)
mainLayout.addWidget(ClientGroup)
mainLayout.addWidget(self.tab)
mainLayout.addLayout(buttonLayout)
mainLayout.addSpacing(2)
mainLayout.addStretch()
self.setLayout(mainLayout)
def gengrate(self):
gen = "Admin_" + "".join(random.choice("0123456789ADCDEF") for x in range(23-5))
self.ClientEdit.setText(gen)
class TabDialog(QtGui.QWidget):
def __init__(self, parent=None):
super(TabDialog, self).__init__(parent)
tabWidget = QtGui.QTabWidget()
self.gen=GeneralTab()
self.tls=TLSTab()
tabWidget.addTab(self.gen, "General")
tabWidget.addTab(self.tls, "TLS")
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(tabWidget)
self.setLayout(mainLayout)
class GeneralTab(QtGui.QWidget):
def __init__(self, parent=None):
super(GeneralTab, self).__init__(parent)
# clean_session_checkBox = QtGui.QCheckBox("clean_session")
groupBox = QtGui.QGroupBox("UserName && PassWord")
visionLabel = QtGui.QLabel("MQTT vision:")
self.visionComboBox = QtGui.QComboBox()
self.visionComboBox.addItem("V3.1")
self.visionComboBox.addItem("V3.1.1")
CleanSessionLabel = QtGui.QLabel("Clean session:")
self.CleanSessionComboBox = QtGui.QComboBox()
self.CleanSessionComboBox.addItem("True")
self.CleanSessionComboBox.addItem("False")
VersionLayout = QtGui.QGridLayout()
VersionLayout.addWidget(CleanSessionLabel,0,0)
VersionLayout.addWidget(self.CleanSessionComboBox,0,1)
VersionLayout.addWidget(visionLabel,1,0)
VersionLayout.addWidget(self.visionComboBox,1,1)
grid = QtGui.QGridLayout()
grid.addWidget(self.createuserGroup(), 0, 0)
grid.addLayout(VersionLayout, 1, 0)
grid.setColumnStretch(1,0)
self.setLayout(grid)
'''槽函数'''
''''''
def createuserGroup(self):
self.groupBox = QtGui.QGroupBox("UserName && PassWord")
self.groupBox.setCheckable(True)
self.groupBox.setChecked(True)
UserLabel = QtGui.QLabel("UserName:")
self.UserEdit = QtGui.QLineEdit()
# self.UserEdit.setText('liuxh')
PassWordLabel = QtGui.QLabel("PassWord:")
self.PassWordEdit = QtGui.QLineEdit()
# self.PassWordEdit.setText('123456')
self.checkBox1 = QtGui.QCheckBox("")
# self.checkBox1.setCheckState(True)
'''槽函数'''
self.checkBox1.stateChanged.connect(self.hide)
''''''
self.checkBox1.setChecked(True)
NamePassLayout = QtGui.QGridLayout()
NamePassLayout.addWidget(UserLabel,0,0)
NamePassLayout.addWidget(self.UserEdit,0,1)
NamePassLayout.addWidget(PassWordLabel,1,0)
NamePassLayout.addWidget(self.PassWordEdit,1,1)
NamePassLayout.addWidget(self.checkBox1,1,2)
vbox = QtGui.QVBoxLayout()
vbox.addLayout(NamePassLayout)
vbox.addStretch()
self.groupBox.setLayout(vbox)
return self.groupBox
def hide(self):
# print self.checkBox1.checkState()
if self.checkBox1.checkState() == 2:
self.PassWordEdit.setEchoMode(QtGui.QLineEdit.Password)
else:
self.PassWordEdit.setEchoMode(QtGui.QLineEdit.Normal)
class TLSTab(QtGui.QDialog):
def __init__(self, parent=None):
super(TLSTab, self).__init__(parent)
frameStyle = QtGui.QFrame.Sunken | QtGui.QFrame.Panel
groupBox = QtGui.QGroupBox("CA certificate")
self.openFileNameLabel = QtGui.QLabel()
self.openFileNameButton = QtGui.QPushButton("open")
self.openFileNameLabel.setFrameStyle(frameStyle)
self.openFileNameLabel.setStyleSheet("background:white")
TLSLayout = QtGui.QGridLayout()
TLSLayout.addWidget(self.openFileNameLabel,0,0,1,5)
TLSLayout.addWidget(self.openFileNameButton,0,6,1,1)
groupBox.setLayout(TLSLayout)
SSLLayout1 = QtGui.QGridLayout()
SSLLayout1.addWidget(groupBox,0,0)
self.setLayout(SSLLayout1)
self.openFileNameButton.clicked.connect(self.setOpenFileName1)
def setOpenFileName1(self):
options = QtGui.QFileDialog.Options()
fileName = QtGui.QFileDialog.getOpenFileName(self,
"QFileDialog.getOpenFileName()",
self.openFileNameLabel.text(),
"All Files (*);;Text Files (*.txt)")
if fileName:
self.openFileNameLabel.setText(fileName)
mtest.py
from PyQt4 import QtCore, QtGui
import sys, socket, binascii
import mqttimage,time
import paho.mqtt.publish as publish
import paho.mqtt.client as mqtt
from ConfigDialog import *
import ctypes
QtCore.QTextCodec.setCodecForTr(QtCore.QTextCodec.codecForName("utf8"))
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid") #状态栏单独显示
class MainWindow(QtGui.QMainWindow):
def __init__(self,parent=None):
super(MainWindow,self).__init__(parent)
self.setWindowTitle(self.tr("MQ TEST"))
self.setWindowIcon(QtGui.QIcon(":img/image/mq.png"));
QtCore.QThread.sleep(0)#启动画面停留时间
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Cleanlooks'))#设置整体风格
QtGui.QApplication.setPalette(QtGui.QApplication.style().standardPalette())#设置整体风格
self.resize(800,550)#####设置窗口大小
# self.statusBar().showMessage(self.tr("未建立连接"))
# self.StackDialog=StackDialog()
# 开始装载样式表
# qss_file = open('style.qss').read()
# self.setStyleSheet(qss_file)
self.a = MQ()
self.setCentralWidget(self.a)
self.createActions()
self.createMenus()
self.createToolBars()
def createActions(self):
# self.fileOpenAction=QtGui.QAction(QtGui.QIcon(":pic/image/xitong/folder_blue.png"),self.tr("打开"),self)
# self.fileOpenAction.setShortcut("Ctrl+O")
# self.fileOpenAction.setStatusTip(self.tr("打开一个文件"))
# self.connect(self.fileOpenAction,QtCore.SIGNAL("triggered()"),self.slotOpenFile)
self.fileSaveAction=QtGui.QAction(QtGui.QIcon(":pic/image/xitong/save.png"),self.tr("保存"),self)
self.fileSaveAction.setShortcut("Ctrl+S")
self.fileSaveAction.setStatusTip(self.tr("保存文件"))
self.connect(self.fileSaveAction,QtCore.SIGNAL("triggered()"),self.fileSaveAs)
self.settingAction=QtGui.QAction(QtGui.QIcon(":img/image/setting.png"),self.tr("设置"),self)
self.settingAction.setShortcut("Ctrl+H")
self.settingAction.setStatusTip(self.tr("设置"))
self.settingAction.triggered.connect(self.a.osd)
self.aboutAction=QtGui.QAction(QtGui.QIcon(":img/image/mq.png"),self.tr("关于"),self)
self.aboutAction.setShortcut("Ctrl+j")
self.aboutAction.triggered.connect(self.about)
self.actionQuit = QtGui.QAction(self.tr("退出"), self, shortcut=QtGui.QKeySequence.Quit)
self.actionQuit.triggered.connect(self.close)
def createMenus(self):
fileMenu = self.menuBar().addMenu(self.tr("文件"))
# fileMenu.addAction(self.fileOpenAction)
# fileMenu.addAction(self.fileSaveAction)
fileMenu.addAction(self.settingAction)
fileMenu.addAction(self.actionQuit)
helpMenu = self.menuBar().addMenu(self.tr("帮助"))
helpMenu.addAction(self.aboutAction)
def createToolBars(self):
fileToolBar=self.addToolBar("File")
# fileToolBar.addAction(self.fileOpenAction)
# fileToolBar.addAction(self.fileSaveAction)
fileToolBar.addAction(self.settingAction)
def slotOpenFile(self):
fileName=QtGui.QFileDialog.getOpenFileName(self)
if fileName.isEmpty()==False:
if self.text.document().isEmpty():
self.loadFile(fileName)
else:
newWin=MainWindow()
newWin.show()
newWin.loadFile(fileName)
def slotSaveFile(self):
pass
def fileSave(self):
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
printer.setOutputFormat(QtGui.QPrinter.PdfFormat)
browser.document().print_(printer)
def fileSaveAs(self):
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
dlg = QtGui.QPrintDialog(printer, self)
# if self.textEdit.textCursor().hasSelection():
# dlg.addEnabledOption(QtGui.QAbstractPrintDialog.PrintSelection)
dlg.setWindowTitle("Print Document")
if dlg.exec_() == QtGui.QDialog.Accepted:
browser.print_(printer)
del dlg
def about(self):
QtGui.QMessageBox.about(self, "About",
"author:liuxiaohu\n"
"vision:V1.0.0\n"
"by Python 2.7 && PyQt4")
class MQ(QtGui.QWidget):
def __init__(self, parent=None):
super(MQ, self).__init__(parent)
nameLabel = QtGui.QLabel()
nameLabel.setPixmap(QtGui.QPixmap(":img/image/note.png"))
frameStyle = QtGui.QFrame.Sunken | QtGui.QFrame.Panel
self.nameEdit = QtGui.QLineEdit()
self.nameEdit.setStyleSheet(" height:20px;width: 60px;background:white")
self.nameEdit.setEnabled(False)
global dataflag#数据刷新标志
self.ConnectButton = QtGui.QPushButton(self.tr("连接"))
# self.ConnectButton.setStyleSheet(" width: 60px;")
self.ConnectButton.setIcon(QtGui.QIcon(":img/image/tuxiang/connected.png"))
self.DisConnectButton = QtGui.QPushButton(self.tr("断开"))
self.DisConnectButton.setDisabled(True)
# self.DisConnectButton.setStyleSheet(" width: 60px;")
self.DisConnectButton.setIcon(QtGui.QIcon(":img/image/tuxiang/disconnected.png"))
self.SettingButton = QtGui.QPushButton()
self.SettingButton.setIcon(QtGui.QIcon(":img/image/disconnect.png"))
self.SettingButton.setFlat(True)
'''槽函数'''
# self.SettingButton.clicked.connect(self.osd)
self.ConnectButton.clicked.connect(self.conne)
self.DisConnectButton.clicked.connect(self.disconne)
''''''
# self.PubLabel = QtGui.QLabel("Retained")
self.portSpinbox = QtGui.QSpinBox()
self.portSpinbox.setMaximum(9999)
self.portSpinbox.setMinimum(0)
self.portSpinbox.setValue(1883)
self.keepaliveSpinbox = QtGui.QSpinBox()
self.keepaliveSpinbox.setMaximum(9999)
self.keepaliveSpinbox.setMinimum(0)
self.keepaliveSpinbox.setValue(60)
nameLayout = QtGui.QGridLayout()
nameLayout.addWidget(nameLabel, 0, 0,)
nameLayout.addWidget(self.nameEdit, 0, 1)
nameLayout.addWidget(self.SettingButton,0, 2)
nameLayout.addWidget(self.ConnectButton, 0, 3)
nameLayout.addWidget(self.DisConnectButton, 0, 4)
self.tab=TabDialog()
mainLayout = QtGui.QVBoxLayout()
mainLayout.addLayout(nameLayout)
mainLayout.addWidget(self.tab)
mainLayout.addSpacing(6)
# mainLayout.setMargin(0)
# mainLayout.addStretch()
self.setLayout(mainLayout)
def osd(self):
global ProfileName, Host, portValue, keepValue, clientids, user, password, visionValue, cleanssionValue, napsBooL, pascheck
dialog=ConfigDialog(self)
result = dialog.exec_()
for x in range(len(childlist)):
childlist.remove(childlist[0])
if result:
ProfileName, Host, portValue, keepValue, clientids, user, password, visionValue, cleanssionValue, napsBooL, pascheck = dialog.getsetdata()
print ProfileName, Host, portValue, keepValue, clientids, user, password, visionValue, cleanssionValue, napsBooL, pascheck
self.nameEdit.setText(ProfileName)
dialog.destroy()
def on_connect(self, client, obj, flags, rc):
print("rc: "+str(rc))
if str(rc) == '0':
self.bwThread.updatedicon.emit()#发送信号
def icon(self):
self.SettingButton.setIcon(QtGui.QIcon(":img/image/connect.png"))
self.ConnectButton.setDisabled(True)
pub.setDisabled(False)
sub.setDisabled(False)
def disconne(self):
pub.setDisabled(True)
sub.setDisabled(True)
client.disconnect()
self.bwThread.stop()
self.SettingButton.setIcon(QtGui.QIcon(":img/image/disconnect.png"))
self.ConnectButton.setDisabled(False)
# self.stopTimer()
def initTimer(self):
self.timer = QtCore.QTimer(self) #初始化一个定时器
self.timer.timeout.connect(self.pingreq) #计时结束调用operate()方法
self.timer.start((keepValue-1)*1000) #设置计时间隔并启动
def stopTimer(self):
self.timer.stop()
def conne(self):
try:
if visionValue == QtCore.QString('V3.1.1'):
self.mqttvision = mqtt.MQTTv311
else:
self.mqttvision = mqtt.MQTTv31
hostname = unicode(QtCore.QString(Host).toUtf8(),'utf8','ignore')
clientid = unicode(QtCore.QString(clientids).toUtf8(),'utf8','ignore')
self.username = unicode(QtCore.QString(user).toUtf8(),'utf8','ignore')
self.pswd = unicode(QtCore.QString(password).toUtf8(),'utf8','ignore')
# print type(hostname)
self.DisConnectButton.setDisabled(False)
global client
client = mqtt.Client(client_id=clientid, clean_session=cleanssionValue, userdata=None, protocol=self.mqttvision)
client.on_publish = self.on_publish
client.on_connect = self.on_connect
client.on_message = self.on_message
client.on_subscribe = self.on_subscribe
if napsBooL == True:
self.setAutho() #设置用户名和密码
try:
client.connect(hostname, keepalive = keepValue) #向服务器发起连接
# self.initTimer()
self.bwThread = WorkThread()
self.bwThread.updated.connect(self.append)
self.bwThread.updatedicon.connect(self.icon)
rc = self.bwThread.start()
return rc
except socket.error:
QMessageBox.information(self, self.tr("提示"), self.tr("服务器地址不存在,请重新输入"))
except ValueError:
QMessageBox.critical(self, self.tr("提示"), self.tr("请输入正确服务器地址"))
except NameError:
QMessageBox.information(self, self.tr("提示"), self.tr("请在设置页面选择相应的配置文件"))
def pingreq(self):
client.send_pingreq()
def on_message(self, mqttc, obj, msg):
global a,b,c
a = msg.topic
b = msg.qos
c = msg.payload
self.bwThread.updated.emit()#发送信号
# print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
def strformathex(self, str):
self.index=0
self.a=list()
self.b=list(str)
self.len = len(str)/2
for i in range(self.len):
self.a.append(self.b[self.index]+self.b[self.index+1])
self.a.append(" ")
self.index=self.index+2
return ''.join(self.a)
def append(self):
browser.append(a+" "+str(b)+" "+str(c))
m = binascii.b2a_hex(c)
h = self.strformathex(m)
h.rstrip()
t = time.asctime( time.localtime(time.time()) )
browser.append(a+" "+str(b)+" "+ h + " "+t)
def on_publish(self, mqttc, obj, mid):
print("message mid is: "+str(mid))
def on_subscribe(self, mqttc, obj, mid, granted_qos):
print("Subscribed: "+str(mid)+" "+str(granted_qos))
def on_log(self, mqttc, obj, level, string):
print(string)
def setAutho(self):
client.username_pw_set(self.username, self.pswd)
class WorkThread(QtCore.QThread):
updated = QtCore.pyqtSignal()#自定义信号,更新数据
updatedicon = QtCore.pyqtSignal()#自定义信号,更新图标
def __init__(self, parent=None):
super(WorkThread, self).__init__(parent)
self.flag = 1
def run(self):
while True:
if self.flag == 1:
client.loop()
else:
break
def stop(self):
print 'setting flag false'
self.flag = 0
print self.flag
class TabDialog(QtGui.QWidget):
def __init__(self, parent=None):
super(TabDialog, self).__init__(parent)
# self.setGeometry(300,30,30,30)
# self.show()
tabWidget = QtGui.QTabWidget()
style = "QTabWidget::pane{border:none;\
QTabWidget::tab-bar{alignment:left;}}\
QTabBar::tab{background:#FFF5EE;color:black;min-width:30ex;min-height:10ex;}\
QTabBar::tab:hover{background:rgb(255, 255, 255, 255);}\
QTabBar::tab:selected{border-color:white;background:#00BFFF;color:white;}"
tabWidget.setStyleSheet(style)
global pub, sub
pub=PublishTab()
sub=SubTab()
pub.setDisabled(True)
sub.setDisabled(True)
tabWidget.addTab(pub, "Publish")
tabWidget.addTab(sub, "Subcribe")
mainLayout = QtGui.QGridLayout()
mainLayout.addWidget(tabWidget,5,1)
mainLayout.setMargin(1)
mainLayout.setSpacing(6)
self.setLayout(mainLayout)
class PublishTab(QtGui.QWidget):
def __init__(self, parent=None):
super(PublishTab, self).__init__(parent)
publishGroup = QtGui.QGroupBox("Publish Message")
self.PubLabel = QtGui.QLabel("PubTopic:")
self.Playload = QtGui.QLabel("Message :")
self.pubEdit = QtGui.QLineEdit()
self.PlayloadEdit = QtGui.QLineEdit()
self.PlayloadEdit.setStyleSheet(" height: 37px;")
self.PushButton = QtGui.QPushButton(self.tr("Publish"))
self.PushButton.setStyleSheet(" height: 50px;background:#D3D3D3")
global pubbrowser
pubbrowser = QtGui.QTextBrowser()
pubbrowser.setFrameStyle(QtGui.QFrame.Panel|QtGui.QFrame.Sunken)
# style = "color: rgb(127, 0, 63);\
# background-image: url(:img/image/3.jpg);"
style = "color:#7CFC00;background:#4D4D4D"
pubbrowser.setStyleSheet(style)
self.QosLabel = QtGui.QLabel("Qos")
self.QosComboBox = QtGui.QComboBox()
self.QosComboBox.addItem("0")
self.QosComboBox.addItem("1")
self.QosComboBox.addItem("2")
self.formatLabel = QtGui.QLabel("Send Format")
self.formatComboBox = QtGui.QComboBox()
self.formatComboBox.addItem("HEX")
self.formatComboBox.addItem("Plain")
self.Retained = QtGui.QCheckBox("Retained")
self.pubLayout = QtGui.QGridLayout()
self.pubLayout.addWidget(self.PubLabel,0,0)
self.pubLayout.addWidget(self.pubEdit,0,1)
self.pubLayout.addWidget(self.QosLabel,0,2)
self.pubLayout.addWidget(self.QosComboBox,0,3)
self.pubLayout.addWidget(self.Retained,0,4)
self.pubLayout.addWidget(self.Playload,1,0)
self.pubLayout.addWidget(self.PlayloadEdit,1,1)
self.pubLayout.addWidget(self.formatLabel,1,2)
self.pubLayout.addWidget(self.formatComboBox,1,3,1,2)
self.pubLayout.setSpacing(10)
self.Vlineframe = QtGui.QFrame()
self.Vlineframe.setFrameStyle(QtGui.QFrame.VLine|QtGui.QFrame.Sunken)
saveButton = QtGui.QPushButton(self.tr("保存"))
saveButton.setFlat(True)
saveButton.setIcon(QtGui.QIcon(":img/image/pdf.png"))
delButton = QtGui.QPushButton(self.tr("清空"))
delButton.setFlat(True)
delButton.setIcon(QtGui.QIcon(":img/image/recycle.png"))
self.buttonLayout1 = QtGui.QGridLayout()
self.buttonLayout1.addWidget(saveButton,0,0)
self.buttonLayout1.addWidget(delButton,0,2)
'''槽函数'''
self.PushButton.clicked.connect(self.push)
saveButton.clicked.connect(self.save)
delButton.clicked.connect(self.clear)
''''''
clientLayout = QtGui.QGridLayout()
clientLayout.addLayout(self.pubLayout, 0, 0)
clientLayout.addWidget(self.Vlineframe, 0, 1)
clientLayout.addWidget(self.PushButton, 0, 2)
publishGroup.setLayout(clientLayout)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(publishGroup)
mainLayout.addWidget(pubbrowser)
mainLayout.addLayout(self.buttonLayout1)
mainLayout.addSpacing(2)
self.setLayout(mainLayout)
def push(self):
x = time.asctime( time.localtime(time.time()) )
self.pubtopic = self.pubEdit.text()
self.pubtopic = unicode(QtCore.QString(self.pubtopic).toUtf8(),'utf8','ignore')
self.pubmessage = self.PlayloadEdit.text()
self.pubmessage = unicode(self.pubmessage)
pubbrowser.append('[Pubtopic]:---' + self.pubtopic + '---[' + x + ']')
pubbrowser.append('[Message]:---' + self.pubmessage + '---[' + x + ']')
if self.formatComboBox.currentIndex() == 0:
# self.pubmessage = unicode(self.pubmessage)
self.pubmessage = bytearray().fromhex(self.pubmessage)
if self.QosComboBox.currentText() == QtCore.QString('0'):
self.qos = 0
elif self.QosComboBox.currentText() == QtCore.QString('1'):
self.qos = 1
if self.QosComboBox.currentText() == QtCore.QString('2'):
self.qos = 2
self.Retain = self.Retained.checkState()
# print self.pubtopic, self.pubmessage, self.qos, self.Retain
client.publish(self.pubtopic, self.pubmessage)
def save(self):
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
dlg = QtGui.QPrintDialog(printer, self)
dlg.setWindowTitle("Print Document")
if dlg.exec_() == QtGui.QDialog.Accepted:
pubbrowser.print_(printer)
del dlg
def clear(self):
pubbrowser.clear()
class SubTab(QtGui.QWidget):
def __init__(self, parent=None):
super(SubTab, self).__init__(parent)
SublishGroup = QtGui.QGroupBox("Subscribe")
self.SubLabel = QtGui.QLabel("SubTopic:")
self.SubEdit = QtGui.QLineEdit()
self.SubEdit.setText('$SYS/broker/bytes/received')
self.SubButton = QtGui.QPushButton(self.tr("Subscribe"))
self.SubButton.setStyleSheet(" height: 50px;background:#D3D3D3")
global browser
browser = QtGui.QTextBrowser()
browser.setFrameStyle(QtGui.QFrame.Panel|QtGui.QFrame.Sunken)
browser.ensureCursorVisible()#滚动条自动
# style = "color: rgb(127, 0, 63);\
# background-image: url(:img/image/3.jpg);"
style = "color:#ffffff;background:#000000"
browser.setStyleSheet(style)
self.QosLabel = QtGui.QLabel("Qos")
self.QosComboBox = QtGui.QComboBox()
self.QosComboBox.addItem("0")
self.QosComboBox.addItem("1")
self.QosComboBox.addItem("2")
self.pubLayout = QtGui.QGridLayout()
self.pubLayout.addWidget(self.SubLabel,0,0)
self.pubLayout.addWidget(self.SubEdit,0,1)
self.pubLayout.addWidget(self.QosLabel,0,2)
self.pubLayout.addWidget(self.QosComboBox,0,3)
self.pubLayout.setSpacing(10)
self.Vlineframe = QtGui.QFrame()
self.Vlineframe.setFrameStyle(QtGui.QFrame.VLine|QtGui.QFrame.Sunken)
saveButton = QtGui.QPushButton(self.tr("保存"))
saveButton.setFlat(True)
saveButton.setIcon(QtGui.QIcon(":img/image/pdf.png"))
delButton = QtGui.QPushButton(self.tr("清空"))
delButton.setFlat(True)
delButton.setIcon(QtGui.QIcon(":img/image/recycle.png"))
self.buttonLayout1 = QtGui.QGridLayout()
self.buttonLayout1.addWidget(saveButton,0,0)
self.buttonLayout1.addWidget(delButton,0,2)
'''槽函数'''
self.SubButton.clicked.connect(self.sub)
saveButton.clicked.connect(self.save)
delButton.clicked.connect(self.clear)
''''''
clientLayout = QtGui.QGridLayout()
clientLayout.addLayout(self.pubLayout, 0, 0)
clientLayout.addWidget(self.Vlineframe, 0, 1)
clientLayout.addWidget(self.SubButton, 0, 2)
# clientLayout.addWidget(self.browser, 1, 0, 1, 3)
# self.pubLayout.setSpacing(2)
SublishGroup.setLayout(clientLayout)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(SublishGroup)
mainLayout.addWidget(browser)
mainLayout.addLayout(self.buttonLayout1)
mainLayout.addSpacing(2)
self.setLayout(mainLayout)
def sub(self):
x = time.asctime( time.localtime(time.time()) )
self.subtopic = self.SubEdit.text()
self.subtopic = str(self.subtopic)#类型转换很重要
browser.append('[Subtopic]:---' + self.subtopic +'---[' + x + ']')
if self.QosComboBox.currentText() == QtCore.QString('0'):
self.qos = 0
elif self.QosComboBox.currentText() == QtCore.QString('1'):
self.qos = 1
if self.QosComboBox.currentText() == QtCore.QString('2'):
self.qos = 2
client.subscribe(self.subtopic,self.qos)
def save(self):
printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
dlg = QtGui.QPrintDialog(printer, self)
dlg.setWindowTitle("Print Document")
if dlg.exec_() == QtGui.QDialog.Accepted:
browser.print_(printer)
del dlg
def clear(self):
browser.clear()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
splash = QtGui.QSplashScreen(QtGui.QPixmap(":img/image/mqtt.GIF"))
splash.show()
app.processEvents()
mainWin = MainWindow()
mainWin.show()
splash.finish(mainWin)
sys.exit(app.exec_())
附上地址:github
目前只是一个手工测试工具,还不能实现自动测试,对PYQT感兴趣的同学可以互相探讨一下