gpt4 book ai didi

python - 在运行时替换 QWidget 对象

转载 作者:行者123 更新时间:2023-11-30 23:26:27 25 4
gpt4 key购买 nike

在我的应用程序中,我必须用自定义的 QLineEdit 替换所有 QLineEdit 元素。为此,有不同的解决方案:

  1. 修改从 pyuic4 生成的 py 文件,并将所有 QLineEdit 对象替换为我的一个 LineEdit。这个解决方案并不是最好的,因为每次运行 pyuic4 时,我都会丢失对生成的输出文件所做的修改。
  2. 编写一个新类,在我的窗口或对话框中递归搜索 QLineEdit 小部件类型,并将其替换为我的一个 LineEdit。这个解决方案要好得多。它允许我对其他对象执行相同的操作或根据需要扩展它,而无需关心对话框或窗口。

到目前为止,我可以编写一个模块(WidgetReplacer),它递归地搜索 QGridLayout 项目并搜索是否有 QLineEdit 子项。如果是,那就换成我的。

问题是,当我尝试访问我的 LineEdit 对象之一时,出现以下错误:

RuntimeError: wrapped C/C++ object of type QLineEdit has been deleted

如果我查看输出,我会注意到修改后的 QLineEdit 对象具有旧的 id:

old qt_obj <PyQt4.QtGui.QLineEdit object at 0x0543C930>
Replaced txt_line_1 with LineEdit
new qt_obj <LineEdit.LineEdit object at 0x0545B4B0>
----------------------------------
...
----------------------------------
<PyQt4.QtGui.QLineEdit object at 0x0543C930>

问题

为什么会出现这种情况?如何在运行时替换 QWidgets?

<小时/>

更新

这里有一些有关对象包装的其他详细信息:在模块 WidgetReplace 中,如果我转储 QEditLine 和 LineEdit 对象,我会得到:

<PyQt4.QtGui.QLineEdit object at 0x05378618>
Reference count: 7
Address of wrapped object: 051FAC40
Created by: Python
To be destroyed by: C/C++
Parent wrapper: <PyQt4.QtGui.QGridLayout object at 0x05378588>
Next sibling wrapper: NULL
Previous sibling wrapper: <PyQt4.QtGui.QLabel object at 0x05378930>
First child wrapper: NULL

<LineEdit.LineEdit object at 0x05378978>
Reference count: 3
Address of wrapped object: 051FAC40
Created by: Python
To be destroyed by: C/C++
Parent wrapper: <__main__.Dialog object at 0x0535FBB8>
Next sibling wrapper: <PyQt4.QtGui.QGridLayout object at 0x05378780>
Previous sibling wrapper: NULL
First child wrapper: NULL

相反,如果我从主窗口转储行编辑,我会得到关注,它代表已删除的 QLineEdit 对象:

<PyQt4.QtGui.QLineEdit object at 0x05378618>
Reference count: 2
Address of wrapped object: 00000000
Created by: Python
To be destroyed by: C/C++
Parent wrapper: NULL
Next sibling wrapper: NULL
Previous sibling wrapper: NULL
First child wrapper: NULL
<小时/>

这是我的代码

对话框ui 和生成文件可以从 DropBox dialog.ui and dialog.py 下载

主要

import sys
from PyQt4.QtGui import QDialog, QApplication
from dialog import Ui_Form
from WidgetReplacer import WidgetReplacer

class Dialog(QDialog, Ui_Form):

def __init__(self, parent = None):
super(Dialog, self).__init__(parent)

# Set up the user interface from Designer.
self.setupUi(self)
WidgetReplacer().replace_all_qlineedit(self)


if __name__ == "__main__":
app = QApplication(sys.argv)
window = Dialog()

window.show()

print window.txt_line_1
window.txt_line_1.setText("Hello Text 1")

sys.exit(app.exec_())

行编辑

from PyQt4.QtGui import QLineEdit, QValidator, QPalette
from PyQt4 import QtCore

class LineEdit(QLineEdit):

def __init__(self, parent=None):
super(LineEdit, self).__init__(parent)

self.color_red = QPalette()
self.color_red.setColor(QPalette.Text, QtCore.Qt.red)

self.color_black = QPalette()
self.color_black.setColor(QPalette.Text, QtCore.Qt.red)

# Make connections
self.textChanged.connect(self.verify_text)

def verify_text(self, text):
validator = self.validator()
is_valid = QValidator.Acceptable

if validator is not None:
is_valid = validator.validate(text, 0)

if is_valid == QValidator.Acceptable:
self.setPalette(self.color_black)
elif is_valid in [QValidator.Invalid, QValidator.Intermediate]:
self.setPalette(self.color_red)

WidgetReplacer

import sip
from LineEdit import LineEdit
from PyQt4.QtCore import QRegExp
from PyQt4 import QtGui

class WidgetReplacer():

def __init__(self):
pass

def replace_all_qlineedit(self, qt_dlg):
children = self._get_all_gridlayout(qt_dlg)

items = []
for child in children:
new_items = self._find_all_obj_in_layout(child, QtGui.QLineEdit)
items.extend(new_items)

for item in items:
layout = item[0]
row = item[1]
column = item[2]
qt_obj = item[3]
self._replace_qlineedit_from_gridlayout(qt_dlg, qt_obj,
layout, row, column)

def _get_all_gridlayout(self, qt_dlg):
return qt_dlg.findChildren(QtGui.QGridLayout, QRegExp("gridLayout_[0-9]"))

def _find_all_obj_in_layout(self, layout, qt_type):
# Output list format:
# layout, row, col, qt_obj,
objects = []
if type(layout) == QtGui.QGridLayout:
layout_cols = layout.columnCount()
layout_rows = layout.rowCount()
for i in range(layout_rows):
for j in range(layout_cols):
item = layout.itemAtPosition(i, j)
# print "item(",i, j, "):", item

if type(item) == QtGui.QWidgetItem:
if type(item.widget()) == qt_type:
new_obj = [layout, i, j, item.widget()]
objects.append(new_obj)

elif type(layout) in [QtGui.QHBoxLayout, QtGui.QVBoxLayout]:
raise SyntaxError("ERROR: Find of Qt objects in QHBoxLayout or QVBoxLayout still not supported")
# for i in range(layout.count()):
# item = layout.itemAt(i)

return objects

def _replace_qlineedit_from_gridlayout(self, parent, qt_obj, layout, row, column):
print "old qt_obj", qt_obj
obj_name = qt_obj.objectName()
layout.removeWidget(qt_obj)
sip.delete(qt_obj)
qt_obj = LineEdit(parent)
qt_obj.setObjectName(obj_name)

layout.addWidget(qt_obj, row, column)
print "Replaced", obj_name, "with LineEdit"

print "new qt_obj", qt_obj
print "----------------------------------"

最佳答案

不要在运行时替换小部件:在 Qt Designer 中升级小部件,以便在生成 GUI 模块时自动将行编辑替换为您的自定义类。

以下是如何提升小部件以使用自定义类:

在 Qt Designer 中,选择要替换的所有行编辑,然后右键单击它们并选择“升级到...”。在对话框中,将“升级的类名称”设置为“LineEdit”,并将“头文件”设置为包含此类的模块的 python 导入路径(例如 myapp.LineEdit)。然后单击“添加”和“升级”,您将在对象检查器 Pane 中看到类从“QLineEdit”更改为“LineEdit”。

现在,当您使用 pyuic 重新生成 ui 模块时,您应该看到它使用您的自定义 LineEdit 类,并且文件底部会有一个额外的行,如下所示:

    from myapp.LineEdit import LineEdit

关于python - 在运行时替换 QWidget 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22528418/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com