python3确实不错,连.py挡都不用加 #coding注释了。
自定义了一个信号,结果报错:
AttributeError: 'FindAndReplaceDlg' object has no attribute 'not_fount'
原来,又给忘了,使用Signal定义信号,要把它放在__init__外面,放在构造器里,就会报错。
在构造器外面定义的变量,给叫做类属性,所有的实例都共享相同的值。
但是Signal却不是。
A signal (specifically an unbound signal) is an attribute of a class that is a sub-class of QObject. When a signal is referenced as an attribute of an instance of the class then PyQt4 automatically binds the instance to the signal in order to create a bound signal. This is the same mechanism that Python itself uses to create bound methods from class functions.
信号(特别是未绑定信号)是类的属性,类是QObject的子类。当以类实例的属性身份引用一个信号时,PyQt4就自动地把实例和此信号绑在一起,从而生成一个绑定信号。
Python本身从类函数生成绑定函数也是同样的机制。
因此,此Signal不会被多个实例分享。
import re
import sys
import ui_fr
from PySide.QtCore import *
from PySide.QtGui import *
class FindAndReplaceDlg(QDialog, ui_fr.Ui_Dialog):
#使用Signal宏定义两个信号
#必须在__init__之前
found = Signal(str)
not_found = Signal()
#class attribute
index = 0
def __init__(self, text, parent=None):
super(FindAndReplaceDlg, self).__init__(parent)
self.setupUi(self)
self.__text = text
found = Signal(str)
not_found = Signal()
#编辑框findEdit文本编辑 槽
@Slot()
def on_findEdit_textEdited(self):
self.text = self.findEdit.text()
#查找按钮 槽
@Slot()
def on_btnFind_clicked(self):
pattern = self.makeRegex()
match = pattern.search(self.__text)
if match:
#print(match.group())
self.found.emit(match.group())
#测试类变量
FindAndReplaceDlg.index += 10
print(self.index)
else:
self.not_found.emit()
#替换按钮 槽
@Slot()
def on_btnReplace_clicked(self):
pattern = self.makeRegex()
self.__text = pattern.sub(self.replaceEdit.text(), self.__text, 1)
print(self.__text)
#替换所有的按钮 槽
@Slot()
def on_btnReplaceAll_clicked(self):
pattern = self.makeRegex()
self.__text = pattern.sub(self.replaceEdit.text(), self.__text)
print(self.__text)
def makeRegex(self):
#re表达式
find_text = self.findEdit.text()
#print('大家好', self.comboBox.currentText())
if self.comboBox.currentText() == 'Literal text':
find_text = re.escape(find_text)
flag = re.MULTILINE | re.DOTALL | re.UNICODE
if not self.caseCheck.isChecked():
flag |= re.IGNORECASE
if self.wholeCheck.isChecked():
find_text = r'\b%s\b' % find_text
return re.compile(find_text, flag)
if __name__ == '__main__':
#不使用Slot修饰符
def find(str):
print('find %s' % str)
def not_find():
print('not find')
def find_2(str):
print('i am g, find %s' % str)
app = QApplication(sys.argv)
text = """
a brown fox jump quicly from the lazy dog, and wind is biger and beiger
There are signs of unease about the tone of these laws
...
Quoted from Henry Porter, The Observer, December 31, 2006.
"""
f = FindAndReplaceDlg(text)
#f.connect(f, SIGNAL('find'), find)
#f.connect(f, SIGNAL('notfind'),not_find)
#连接信号和槽
f.found.connect(find)
f.not_found.connect(not_find)
#显示对话框
f.show()
#信号是否分享?
text_1 = 'Good moring, every boy and girls!'
g = FindAndReplaceDlg(text_1)
g.found.connect(find_2)
g.show()
app.exec_()
这里,还创建了一个类属性,index,但是结果对它修改无效。
而且可以实验到,实例f和实例g之间不会发生信号共享的情况。
而使用其他方式定义类,则类属性(经常被叫做类变量),可以修改:
class Dog:
tricks = [] # mistaken use of a class variable
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)
d = Dog('Fido')
e = Dog('Buddy')
d.add_trick('roll over')
e.add_trick('play dead')
print(d.tricks) # unexpectedly shared by all dogs
Generally speaking, instance variables are for data unique to each instance and class variables are for attributes and methods shared by all instances of the class.
一般来讲,对于每个实例,实例变量是独一的;而类变量主要用于类实例共享的属性和方法。
上例子中,应该把tricks放到__init__中定义才合适。