import sys
import coding # coding就是通过.ui文件生成的.py文件,.ui文件的名字是什么就import什么
from PyQt5 import QtCore, QtGui, QtWidgets
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = coding.Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
关于这个程序的理解:
sys模块提供访问由解释器使用或维护的变量的接口,并提供了一些函数和解释器进行交互,操控python运行时的环境
sys.argv:
sys.exit:
QtWidgets模块包含了构建界面的一系列UI元素组件
QApplication:对于任一使用Qt的GUI应用,只能有一个QApplication对象
QMainWindow:QMainWindow是Qt的顶层窗口,使用它代表创建窗体对象
Ui_MainWindow就是.ui文件转换为.py文件生成的类,setupUi就是对对象进行初始化设置
MainWindow.show()用于显示窗体
PyQt5窗口设计基础
PyQt5的窗口就是向用户展示信息的可视化界面,是GUI程序的基本单元
PyQt5窗口创建完成后,可以通过属性对窗口进行设置,这些属性可以在属性编辑器中进行设置,也可以直接通过代码来实现,其常用的属性如下:
窗口的对象名称,相当于窗口的标识,是唯一的,在编写代码时,对窗口的任何设置和使用都是通过该名称进行操作的,默认名称是MainWindow,可通过objectName来进行修改
如果需要使用python代码进行设置的话,需要使用一个函数:MainWindow.setObjectName("MainWindow")
窗口的标题栏名称通过windowTitle设置,也可以直接用python中的函数:MainWindow.setWindowTitle("标题栏")
窗口的大小通过geometry属性设置,也可以直接用python中的函数:MainWindow.resize(252,100)
窗口的样式可以使用setWindowFlags()函数设置:setWindowFlags(Qt.WindowFlags)
,其中Qt.WindowFlags参数表示要设置的窗口样式
对窗口样式的设置要在初始化窗体后才会起作用,即要在setupUi()函数后执行
信号(signal)与槽(slot)是Qt的核心机制,也是进行PyQt5编程时对象之间通信的基础,在PyQt5中,每一个QObject对象(包括各种窗口和控件)都支持信号与槽机制,通过信号与槽的关联就可以实现对象之间的通信,当信号发射时,连接的槽函数(方法)将会自动执行,在PyQt5中,信号与槽是通过对象的signal.connect()方法进行连接
PyQt5的窗口控件中有很多内置的信号与槽,PyQt5中使用信号与槽的主要特点如下:
一个信号可以连接多个槽
一个槽可以监听多个信号
信号与信号之间可以互连
信号与槽的连接可以跨线程
信号与槽的连接方式可以是同步,也可以是异步
信号的参数可以是任何的python类型
接下来用一个简例通过信号与槽实现一个单击按钮关闭主窗口的效果:
首先添加一个PushButton,并设置按钮的text属性为"关闭"
在菜单栏中选择"编辑信号/槽",然后选中关闭按钮,按住鼠标左键拖动至窗口的空白区域
松开鼠标后,会自动弹出配置连接,选中"显示从QWidget继承的信号和槽"复选框,然后在上方的信号与槽列表分别选中"clicked()"和"close()",完成信号与槽的关联
使用PyUIC工具将.ui文件转换为.py文件,然后编写python显示窗口并测试
PyQt5的常用控件
控件是用户可以用来输入或操作数据的对象,在PyQt5中控件的基类是QFrame类,而QFrame类继承自QWidget类,QWidget类是所有用户界面对象的基类
Qt Designer中默认对控件进行了分组:
文本类控件主要用来显示或者编辑文本信息
Label:标签控件
主要用于显示用户不能编辑的文本,标识窗体上的对象,对应PyQt5中的QLabel类(QLabel类属于QtWidgets),Label控件本质上是QLabel类的一个对象
设置标签文本:在Qt Designer中的属性编辑器中设置text属性/用QLabel类的setText()方法
设置标签文本的对齐方式:在Qt Designer中的属性编辑器中设置alignment属性中的Horizontal和Vertical/用QLabel类的setAlignment()方法
Horizontal用于设置标签文本的水平对齐方式
AlignLeft:左对齐
AlignHCenter:水平居中对齐
AlignRight:右对齐
Vertical用于设置标签文本的垂直对齐方式
AlignTop:顶部对齐
AlignVCenter:垂直居中对齐
AlignBottom:底部对齐
设置文本换行显示:在标签宽度不足的情况下,系统会默认只显示部分文字,可以设置标签中的文本换行显示,在Qt Designer中的属性编辑器中将wordWrap属性后面的复选框选中/用QLabel类的setWordWrap方法
获取标签文本:用QLabel类的text()方法
LineEdit:单行文本框
LineEdit是单行文本框,该控件只能输入单行字符串,对应PyQt5中的QLineEdit类,该类的常用方法如下:
setText():设置文本框内容
text():获取文本框内容
setPlaceholderText():设置文本框浮现文字
setMaxLength():设置允许文本框内输入字符的最大长度
setAlignment():设置文本对齐方式
setReadOnly():设置文本框只读
setEchoMode():设置文本框显示字符的模式
QLineEdit.Normal:正常显示输入的字符,默认设置
QLineEdit.NoEcho:不显示任何输入的字符,适用于即使符合密码长度也需要保密的密码
QLineEdit.Password:显示与平台相关的密码掩码字符,而不是实际输入的字符
setValidator():设置文本框验证器
QIntValidator:限制输入整数
QDoubleValidator:限制输入小数
QRegExpValidator:检查输入是否符合设置的正则表达式
clear():清除文本框内容
QLineEdit类的常用信号:
textChanged:当更改文本框中的内容时发射该信号
editingFinished:当文本框中的内容编辑结束后发射该信号,以按下enter键为编辑结束标志
TextEdit:多行文本框
TextEdit是多行文本框控件,主要用来显示多行的文本内容,当文本内容超出控件的显示范围时,该控件将显示垂直滚动条,该类的常用方法如下:
setPlainText():设置文本内容
toPlainText():获取文本内容
setTextColor():设置文本颜色
setWordWrapMode():设置自动换行
clear():清除所有内容
按钮类控件
按钮类控件主要用来执行一些命令操作
PushButton允许用户通过单击来执行操作,既可以显示文本,也可以显示图像,当该控件被单击时,它看起来的状态像是被按下,然后被释放,对应PyQt5中的QPushButton类,该类的常用方法如下:
setText():设置按钮显示的文本
text():获取按钮显示的文本
setIcon():设置按钮上的图标,可以将参数设置为QtGui.QIcon('图标路径')
setIconSize():设置按钮图标的大小,参数可以设置为Qtcore.Qsize(int width, int height)
setEnabled():设置按钮是否可用,参数设置为False时,按钮为不可用状态
setShortcut():设置按钮的快捷键,参数可设置为键盘中的按键或组合键
PushButton按钮中最常用的信号是clicked,当按钮被单击时,会发射该信号执行相应的操作
实例:信息论与编码课程设计
课程设计要求
利用编程语言实现霍夫曼、费诺、香农编码
霍夫曼编码:实现任意Q符号的N重序列信源的最优R进制编码(8≤Q≤15;2≤R≤5;1≤N≤3)
费诺、香农编码:实现任意Q符号的二进制编码(Q≥10)
编写的程序应具备在windows下的可视化操作界面,不同的编码类型用不同的菜单加以分割
对于霍夫曼编码应该具备Q、N、R的能力,而费诺、香农编码能输入Q
不同编码类型应当展现编码的结果,平均码长、信息熵等性能指标
首先要在Qt designer中创建几个窗口,然后要将各个按键对应显示窗口的函数,然后根据几个编码过程编写代码然后在相应的控件上显示即可,这里给出三个编码的核心代码:
霍夫曼编码:
def Hoffman_Coding(self):
Q,N,R,sp = self.Read_Input()
if Q == 0 and N == 0 and R == 0 and sp == 0:
self.ui_error.show()
return 0
all_sym = self.Get_All_Symbol(Q,N,R,sp) # all nodes
if R == 2:
hoffman_tree = self.Hoffman_Tree_Generate_2(Q,N,sp,all_sym)
hoffman_code = self.Coding_2(all_sym,hoffman_tree)
outcome = ''
for i in range(len(all_sym)):
outcome = outcome + str(round(all_sym[i].P,6)) + ' ' + hoffman_code[i] + ' ' +'\n'
# print(outcome)
self.textEdit_2.setPlainText(outcome)
self.Calculate_Performance_Index(N,R,sp,all_sym,hoffman_code)
elif R == 3:
hoffman_tree = self.Hoffman_Tree_Generate_3(Q,N,sp,all_sym)
hoffman_code = self.Coding_3(all_sym, hoffman_tree)
outcome = ''
for i in range(len(all_sym)):
outcome = outcome + str(round(all_sym[i].P, 6)) + ' ' + hoffman_code[i] + ' ' + '\n'
self.textEdit_2.setPlainText(outcome)
self.Calculate_Performance_Index(N, R, sp, all_sym, hoffman_code)
elif R == 4:
hoffman_tree = self.Hoffman_Tree_Generate_4(Q,N,sp,all_sym)
hoffman_code = self.Coding_4(all_sym, hoffman_tree)
outcome = ''
for i in range(len(all_sym)):
outcome = outcome + str(round(all_sym[i].P, 6)) + ' ' + hoffman_code[i] + ' ' + '\n'
self.textEdit_2.setPlainText(outcome)
self.Calculate_Performance_Index(N, R, sp, all_sym, hoffman_code)
elif R == 5:
hoffman_tree = self.Hoffman_Tree_Generate_5(Q,N,sp,all_sym)
hoffman_code = self.Coding_5(all_sym, hoffman_tree)
outcome = ''
for i in range(len(all_sym)):
outcome = outcome + str(round(all_sym[i].P, 6)) + ' ' + hoffman_code[i] + ' ' + '\n'
self.textEdit_2.setPlainText(outcome)
self.Calculate_Performance_Index(N, R, sp, all_sym, hoffman_code)
def Hoffman_Tree_Generate_2(self,Q,N,sp,all_sym):
queue = all_sym[:]
while len(queue) > 1:
queue.sort(key=lambda item:item.P)
node_child1 = queue.pop(0)
node_child2 = queue.pop(0)
node_father = Node_2(node_child1.P + node_child2.P)
node_father.child1 = node_child1
node_father.child2 = node_child2
node_child1.father = node_father
node_child2.father = node_father
queue.append(node_father)
queue[0].father = None
return queue[0]
def Hoffman_Tree_Generate_3(self,Q,N,sp,all_sym):
queue = all_sym[:]
while len(queue) > 1:
queue.sort(key=lambda item:item.P)
node_child1 = queue.pop(0)
node_child2 = queue.pop(0)
node_child3 = queue.pop(0)
node_father = Node_3(node_child1.P + node_child2.P + node_child3.P)
node_father.child1 = node_child1
node_father.child2 = node_child2
node_father.child3 = node_child3
node_child1.father = node_father
node_child2.father = node_father
node_child3.father = node_father
queue.append(node_father)
queue[0].father = None
return queue[0]
def Hoffman_Tree_Generate_4(self,Q,N,sp,all_sym):
queue = all_sym[:]
while len(queue) > 1:
queue.sort(key=lambda item:item.P)
node_child1 = queue.pop(0)
node_child2 = queue.pop(0)
node_child3 = queue.pop(0)
node_child4 = queue.pop(0)
node_father = Node_4(node_child1.P + node_child2.P + node_child3.P + node_child4.P)
node_father.child1 = node_child1
node_father.child2 = node_child2
node_father.child3 = node_child3
node_father.child4 = node_child4
node_child1.father = node_father
node_child2.father = node_father
node_child3.father = node_father
node_child4.father = node_father
queue.append(node_father)
queue[0].father = None
return queue[0]
def Hoffman_Tree_Generate_5(self,Q,N,sp,all_sym):
queue = all_sym[:]
while len(queue) > 1:
queue.sort(key=lambda item:item.P)
node_child1 = queue.pop(0)
node_child2 = queue.pop(0)
node_child3 = queue.pop(0)
node_child4 = queue.pop(0)
node_child5 = queue.pop(0)
node_father = Node_5(node_child1.P + node_child2.P + node_child3.P + node_child4.P + node_child5.P)
node_father.child1 = node_child1
node_father.child2 = node_child2
node_father.child3 = node_child3
node_father.child4 = node_child4
node_father.child5 = node_child5
node_child1.father = node_father
node_child2.father = node_father
node_child3.father = node_father
node_child4.father = node_father
node_child5.father = node_father
queue.append(node_father)
queue[0].father = None
return queue[0]
def Coding_2(self,all_sym,root):
codes = ['']*len(all_sym)
for i in range(len(all_sym)):
node_tem = all_sym[i]
while node_tem != root:
if node_tem.check_num_of_child() == 1:
codes[i] = '0' + codes[i]
else:
codes[i] = '1' + codes[i]
node_tem = node_tem.father
print(codes)
return codes
def Coding_3(self, all_sym, root):
codes = ['']*len(all_sym)
for i in range(len(all_sym)):
node_tem = all_sym[i]
while node_tem != root:
if node_tem.check_num_of_child() == 1:
codes[i] = '0' + codes[i]
elif node_tem.check_num_of_child() == 2:
codes[i] = '1' + codes[i]
else:
codes[i] = '2' + codes[i]
node_tem = node_tem.father
print(codes)
return codes
def Coding_4(self, all_sym, root):
codes = ['']*len(all_sym)
for i in range(len(all_sym)):
node_tem = all_sym[i]
while node_tem != root:
if node_tem.check_num_of_child() == 1:
codes[i] = '0' + codes[i]
elif node_tem.check_num_of_child() == 2:
codes[i] = '1' + codes[i]
elif node_tem.check_num_of_child() == 3:
codes[i] = '2' + codes[i]
else:
codes[i] = '3' + codes[i]
node_tem = node_tem.father
print(codes)
return codes
def Coding_5(self, all_sym, root):
codes = ['']*len(all_sym)
for i in range(len(all_sym)):
node_tem = all_sym[i]
while node_tem != root:
if node_tem.check_num_of_child() == 1:
codes[i] = '0' + codes[i]
elif node_tem.check_num_of_child() == 2:
codes[i] = '1' + codes[i]
elif node_tem.check_num_of_child() == 3:
codes[i] = '2' + codes[i]
elif node_tem.check_num_of_child() == 4:
codes[i] = '3' + codes[i]
else:
codes[i] = '4' + codes[i]
node_tem = node_tem.father
print(codes)
return codes
def Get_All_Symbol(self,Q,N,R,sp):
all_sym = []
symbol_sequence = []
nodes = []
for i in range(N):
symbol_sequence.append(0)
for i in range(pow(Q,N)):
j = N-1
P = sp[symbol_sequence[0]]
for k in range(N):
if k != 0:
P *= sp[symbol_sequence[k]]
if R == 2:
all_sym.append(Node_2(P))
elif R == 3:
all_sym.append(Node_3(P))
elif R == 4:
all_sym.append(Node_4(P))
elif R == 5:
all_sym.append(Node_5(P))
while symbol_sequence[j] == Q-1:
symbol_sequence[j] = 0
j -= 1
if j == -1:
# print(len(all_sym))
if( int((Q - R)/(R - 1))!=(Q - R)/(R - 1) ):
Q_expand = int((Q - R)/(R - 1)+1)*(R - 1)+R
for i in range(Q_expand - Q):
if R == 2:
all_sym.append(Node_2(0))
elif R == 3:
all_sym.append(Node_3(0))
elif R == 4:
all_sym.append(Node_4(0))
elif R == 5:
all_sym.append(Node_5(0))
return all_sym
symbol_sequence[j] += 1
def Read_Input(self):
Q = int(self.lineEdit_5.text()) # num of symbol
N = int(self.lineEdit_6.text()) # num of sequence
R = int(self.lineEdit_7.text()) # num of radix
text = self.textEdit.toPlainText()
sp = self.Get_Symbol_Probability(text) # symbol probability
if Q<8 or Q>15 or N<1 or N>3 or R<2 or R>5 or len(sp)!=Q or sum(sp)<0.99999:
# self.ui_error.show()
# print(sum(sp))
return 0,0,0,0
else:
# print(Q,N,R,sp)
return Q,N,R,sp
def Str_Find_HH(self,str): # HH:huan hang '\n'
n = len(str)
pos = list()
for i in range(n):
if str[i] == '\n':
pos.append(i)
# print(pos)
return pos
def Get_Symbol_Probability(self,str):
n = len(str)
pos = self.Str_Find_HH(str)
sp = list()
n_pos = len(pos)
for i in range(n_pos):
if i == 0:
sp.append(float(str[0:pos[i]]))
else:
sp.append(float(str[pos[i - 1] + 1:pos[i]]))
# print(sp)
return sp
def Calculate_Performance_Index(self,N,R,sp,all_sym,codes):
HU = 0
l_avr = 0
for i in range(len(sp)):
HU += -sp[i]*math.log2(sp[i])
for i in range(len(all_sym)):
l_avr += all_sym[i].P*len(codes[i])
effi = HU*N/l_avr/math.log2(R)
self.lineEdit_2.setText(str(round(HU,5)))
self.lineEdit_3.setText(str(round(l_avr,2)))
self.lineEdit_4.setText(str(round(effi*100,4))+'%')
费诺编码:
def Feno_Coding(self):
Q,sp = self.Read_Input()
if Q == 0 and sp == 0:
self.ui_error.show()
return
sp_node = []
self.feno_code = ['']*len(sp)
sp.sort(reverse=True)
for i in range(len(sp)):
sp_node.append(Node(sp[i],i))
self.Coding(sp_node)
# print(self.feno_code)
outcome = ''
for i in range(len(sp)):
outcome = outcome + str(sp[i]) + ' ' + self.feno_code[i] + ' ' + '\n'
self.textEdit_2.setPlainText(outcome)
self.Calculate_Performance_Index(sp,self.feno_code)
def Coding(self,sp_node):
if len(sp_node) == 1:
return
findPos = 0
diff_c = 1
sum1 = 0
sum2 = 0
left_flag = 0 # 0 means left bigger than right
for i in range(len(sp_node)-1):
for j in range(i+1):
sum1 += sp_node[j].P
for k in range(i+1,len(sp_node)):
sum2 += sp_node[k].P
if abs(sum1-sum2) < diff_c:
diff_c = abs(sum1-sum2)
if sum1 < sum2:
left_flag = 1
else:
left_flag = 0
findPos = i
sum1 = 0
sum2 = 0
for i in range(len(sp_node)):
if left_flag:
if i <= findPos:
self.feno_code[sp_node[i].pos] += '1'
else:
self.feno_code[sp_node[i].pos] += '0'
else:
if i <= findPos:
self.feno_code[sp_node[i].pos] += '0'
else:
self.feno_code[sp_node[i].pos] += '1'
left = []
right = []
for i in range(findPos+1):
left.append(sp_node[i])
for i in range(findPos+1,len(sp_node)):
right.append(sp_node[i])
self.Coding(left)
self.Coding(right)
def Read_Input(self):
Q = int(self.lineEdit.text()) # num of symbol
text = self.textEdit.toPlainText()
sp = self.Get_Symbol_Probability(text) # symbol probability
if Q<10 or len(sp)!=Q or sum(sp)<0.99999:
# self.ui_error.show()
# print(sum(sp))
return 0,0,0,0
else:
# print(Q,N,R,sp)
return Q,sp
def Str_Find_HH(self,str): # HH:huan hang '\n'
n = len(str)
pos = list()
for i in range(n):
if str[i] == '\n':
pos.append(i)
# print(pos)
return pos
def Get_Symbol_Probability(self,str):
n = len(str)
pos = self.Str_Find_HH(str)
sp = list()
n_pos = len(pos)
for i in range(n_pos):
if i == 0:
sp.append(float(str[0:pos[i]]))
else:
sp.append(float(str[pos[i - 1] + 1:pos[i]]))
# print(sp)
return sp
def Calculate_Performance_Index(self,sp,codes):
HU = 0
l_avr = 0
for i in range(len(sp)):
HU += -sp[i]*math.log2(sp[i])
for i in range(len(sp)):
l_avr += sp[i]*len(codes[i])
effi = HU/l_avr/math.log2(2)
self.lineEdit_2.setText(str(round(HU,5)))
self.lineEdit_3.setText(str(round(l_avr,2)))
self.lineEdit_4.setText(str(round(effi*100,4))+'%')
香农编码:
def Shannon_Coding(self):
Q,sp = self.Read_Input()
if Q == 0 and sp == 0:
self.ui_error.show()
return
shannon_code = ['']*len(sp)
sp.sort(reverse=True)
for i in range(len(sp)):
P_acc = 0
code = ''
l = int(-math.log2(sp[i])+1)
for j in range(i):
P_acc += sp[j]
while True:
P_acc *= 2
if P_acc >= 1:
code += '1'
else:
code += '0'
if len(code) == l:
break
P_acc -= int(P_acc)
if P_acc == 0:
if(len(code)<l):
code += '0'*(l-len(code))
break
shannon_code[i] = code[:l]
# print(shannon_code)
outcome = ''
for i in range(len(sp)):
outcome = outcome + str(sp[i]) + ' ' + shannon_code[i] + ' ' + '\n'
self.textEdit_2.setPlainText(outcome)
self.Calculate_Performance_Index(sp,shannon_code)
def Read_Input(self):
Q = int(self.lineEdit.text()) # num of symbol
text = self.textEdit.toPlainText()
sp = self.Get_Symbol_Probability(text) # symbol probability
if Q<10 or len(sp)!=Q or sum(sp)<0.99999:
# self.ui_error.show()
# print(sum(sp))
return 0,0,0,0
else:
# print(Q,N,R,sp)
return Q,sp
def Str_Find_HH(self,str): # HH:huan hang '\n'
n = len(str)
pos = list()
for i in range(n):
if str[i] == '\n':
pos.append(i)
# print(pos)
return pos
def Get_Symbol_Probability(self,str):
n = len(str)
pos = self.Str_Find_HH(str)
sp = list()
n_pos = len(pos)
for i in range(n_pos):
if i == 0:
sp.append(float(str[0:pos[i]]))
else:
sp.append(float(str[pos[i - 1] + 1:pos[i]]))
# print(sp)
return sp
def Calculate_Performance_Index(self,sp,codes):
HU = 0
l_avr = 0
for i in range(len(sp)):
HU += -sp[i]*math.log2(sp[i])
for i in range(len(sp)):
l_avr += sp[i]*len(codes[i])
effi = HU/l_avr/math.log2(2)
self.lineEdit_2.setText(str(round(HU,5)))
self.lineEdit_3.setText(str(round(l_avr,2)))
self.lineEdit_4.setText(str(round(effi*100,4))+'%')
程序的入口:
import sys
import coding
from PyQt5 import QtCore, QtGui, QtWidgets
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = coding.Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
这里还附上完整的课程设计报告可供参考: