Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Qt/PyQt/PySide:重新实现QLineEdit子类的撤消框架时出现问题_Python_Qt_Pyqt_Pyside - Fatal编程技术网

Python Qt/PyQt/PySide:重新实现QLineEdit子类的撤消框架时出现问题

Python Qt/PyQt/PySide:重新实现QLineEdit子类的撤消框架时出现问题,python,qt,pyqt,pyside,Python,Qt,Pyqt,Pyside,我已经创建了一个自定义行编辑小部件,这样我就可以将其上的撤销/重做命令合并到我的应用程序的通用撤销堆栈中(而不是使用QLineEdit小部件附带的内置撤销/重做功能)。撤销/重做逻辑相当简单:当行编辑小部件接收到焦点时,其内容立即分配给实例变量(self.init_text);当行编辑小部件失去焦点时,如果文本内容与self.init_text中存储的内容不同,则会创建一个新的QUndoCommand对象。undo()方法将把内容重新设置为self.init_文本中的任何内容,而redo()方法

我已经创建了一个自定义行编辑小部件,这样我就可以将其上的撤销/重做命令合并到我的应用程序的通用撤销堆栈中(而不是使用QLineEdit小部件附带的内置撤销/重做功能)。撤销/重做逻辑相当简单:当行编辑小部件接收到焦点时,其内容立即分配给实例变量(self.init_text);当行编辑小部件失去焦点时,如果文本内容与self.init_text中存储的内容不同,则会创建一个新的QUndoCommand对象。undo()方法将把内容重新设置为self.init_文本中的任何内容,而redo()方法将把内容重新设置为行编辑小部件失去焦点时捕获的任何内容。(在任何一种方法中,行编辑都将再次获得焦点,以便用户能够清楚地看到撤消或重做命令实际影响了什么。)

它似乎工作得很好,但有一个例外:如果用户通过QPushButtons快速循环执行撤销或重做命令,那么框架就会崩溃。我无法更好地描述它,因为我不确定Qt引擎盖下发生了什么,但是,例如,QUndoStack的count()可能会完全改变。应用程序继续运行,终端上未报告任何错误,但它仍然是一个损坏的撤消堆栈

我创建了一个小小的QDialog应用程序,您可以尝试重新创建问题。(使用Python 2.7.3/PySide 1.2.1…如果您安装了最近的PyQt绑定,我认为您不需要替换除前两个导入语句之外的任何内容。)例如,在第一个选项卡的QLineEdit中,如果键入“hello”,然后键入tab out,然后单击back in并键入“world”,然后再次键入tab out,尝试快速单击“撤消”按钮(向下和超出撤消堆栈底部)和“重做”按钮(向上和超出撤消堆栈顶部)。对我来说,这足以打破它

#/usr/bin/python
#编码=utf-8
从PySide.QtCore导入*
从PySide.QtGui导入*
导入系统
类CustomRightClick(QObject):
customRightClicked=信号()
def uuu init uuu(self,parent=None):
QObject.\uuuuu init\uuuuu(自,父)
def事件过滤器(自身、obj、事件):
如果event.type()==QEvent.ContextMenu:
#发出信号,以便小部件可以将插槽连接到该信号
self.customRightClicked.emit()
返回真值
其他:
#标准事件处理
返回QObject.eventFilter(自、对象、事件)
类命令行编辑(QUNDO命令):
def_uuuinit_uuu(self,line_edit,init_text,tab_小部件,tab_索引,描述):
QUNDOCOMAND.\uuuuu init\uuuuuu(自我,描述)
self.\u line\u edit=line\u edit
self.\u current\u text=line\u edit.text()
self.\u init\u text=init\u text
self.\u tab\u widget=tab\u widget
self.\u tab\u index=tab\u index
def撤消(自我):
self.\u line\u edit.setText(self.\u init\u text)
self.\u tab\u widget.setCurrentIndex(self.\u tab\u index)
self.\u line\u edit.setFocus(Qt.OtherFocusReason)
def重做(自我):
self.\u line\u edit.setText(self.\u current\u text)
self.\u tab\u widget.setCurrentIndex(self.\u tab\u index)
self.\u line\u edit.setFocus(Qt.OtherFocusReason)
类CustomLineEdit(QLineEdit):
定义初始化(自、父、选项卡小部件、选项卡索引):
超级(自定义行编辑,自我)。\uuuu初始化\uuuuu(父级)
self.parent=parent
self.tab\u小部件=tab\u小部件
self.tab\u index=tab\u index
self.init_text=self.text()
self.setContextMenuPolicy(Qt.CustomContextMenu)
undoAction=QAction(“撤消”,自我)
undoAction.triggered.connect(self.parent.undo\u stack.undo)
self.customContextMenu=QMenu()
self.customContextMenu.addAction(undoAction)
自定义单击器=自定义右键单击(自身)
self.installEventFilter(自定义点击器)
self.right\u clicked=False
自定义鼠标点击器。自定义鼠标右键点击。连接(self.menuShow)
def菜单显示(自我):
self.right_clicked=True#将self.right_clicked设置为True,以便focusOutEvent不会因为右键单击而将任何内容推送到撤消堆栈
self.customContextMenu.popup(QCursor.pos())
self.right\u clicked=False
#重新实现focusInEvent(),以便它捕获focusInEvent()时文本*的当前值作为实例变量。这将用于下面的撤消堆栈命令push
def焦点事件(自身、事件):
self.init_text=self.text()
QLineEdit.FocusineEvent(自、事件)
#重新实现focusOutEvent(),使其将当前文本推送到撤消堆栈。。。。但前提是有变化!
def focusOutEvent(自身、事件):
如果self.text()!=self.init_文本而非self.right_单击:
打印“焦点输出事件。(self.text为%s,init_文本为%s)。推到撤消堆栈上。(事件原因为%s)”%(self.text(),self.init_文本,event.reason())
command=CommandLineEdit(self,self.init_text,self.tab_小部件,self.tab_索引,“编辑文本框”)
self.parent.undo_stack.push(命令)
focusOutEvent(自、事件)
def按键事件(自身,事件):
如果event.key()==Qt.key_Z:
如果event.modifiers()&Qt.ControlModifier:
self.parent.undo_stack.undo()
其他:
QLineEdit.keyPressEvent(自,事件)
elif event.key()==Qt.key\u Y:
如果event.modifiers()&Qt.ControlModifier:
self.parent.undo_stack.redo()
其他:
QLineEdit.keyPressEvent(自,事件)
其他:
QLineEdit.keyPressEvent(自,事件)
课堂形式(QDialog):
def uuu init uuu(self,parent=None):
超级(形式,自我)。\uuuu初始\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
self.undo_stack=QUndoStack()
self.tab_widget=QTabWidget()
self.line_edit1=CustomLineEdit(self,sel
def undo(self):
    self._line_edit.setText(self._init_text)
    self._line_edit.init_text = self._line_edit.text()
    self._tab_widget.setCurrentIndex(self._tab_index)
    self._line_edit.setFocus(Qt.OtherFocusReason)

def redo(self):
    self._line_edit.setText(self._current_text)
    self._line_edit.init_text = self._line_edit.text()
    self._tab_widget.setCurrentIndex(self._tab_index)
    self._line_edit.setFocus(Qt.OtherFocusReason)