我在QT设计器中构建了一个ui,然后使用pyside-uic将其转换为python文件,然后编写了一些代码以编程方式对其进行编辑。换句话说,我有一个按钮Add Row,当单击它时,它会将自己重命名为Remove1,并创建另一个按钮名为Add Row,并将其添加到布局中。
单击Add Row时,更改名称和信号/插槽:
self.pb_Row[-1].setText('Remove'+str(self.nRows))
self.pb_Row[-1].clicked.disconnect( self.addRow )
self.pb_Row[-1].clicked.connect( self.removeRow )单击Remove时,删除所选按钮:
iRow = int(self.sender().objectName().split('_')[-1])-1
ind = self.PropertyLayout.indexOf(self.pb_Row[iRow])
t = self.PropertyLayout.takeAt(ind)
t.widget().deleteLater()
# self.pb_Row[iRow].hide()
# self.pb_Row[iRow].deleteLater()
self.pb_Row.pop(iRow)这是很好的工作,直到你添加了至少一个,然后删除它,下一次在它周围混乱。基本上,当我有两个按钮并删除一个按钮,然后尝试添加一个按钮时,它就会出错。我的意思是,新按钮在旧按钮的顶部结束,有时它出现在下面而不是上面。
此外,对于当前的行,如果我使用.hide()函数,它不会真正地重新组织网格布局中的东西。我不太确定我该用哪一种。
谢谢!
下面是一个产生不良结果的序列:
新开始

单击Add后

单击“删除”(到目前为止都很好),然后单击“添加”(没有可见的差异)。

单击后再添加第二次

单击Remove2后,Remove1从它下面出现

代码的“工作”示例
import numpy as np
import sys
from PySide import QtCore, QtGui
import matplotlib.pyplot as plt
from ModesInFiber import Ui_fiberModesMainWindow
class Ui_fiberModesMainWindow(object):
def setupUi(self, fiberModesMainWindow):
fiberModesMainWindow.setObjectName("fiberModesMainWindow")
fiberModesMainWindow.resize(653, 597)
self.centralwidget = QtGui.QWidget(fiberModesMainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout_2 = QtGui.QHBoxLayout(self.centralwidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.MainLayout = QtGui.QGridLayout()
self.MainLayout.setObjectName("MainLayout")
self.PropertyLayout = QtGui.QGridLayout()
self.PropertyLayout.setObjectName("PropertyLayout")
self.lbl_Name = QtGui.QLabel(self.centralwidget)
self.lbl_Name.setObjectName("lbl_Name")
self.PropertyLayout.addWidget(self.lbl_Name, 0, 1, 1, 1)
self.pb_addRow_1 = QtGui.QPushButton(self.centralwidget)
self.pb_addRow_1.setObjectName("pb_addRow_1")
self.PropertyLayout.addWidget(self.pb_addRow_1, 1, 5, 1, 1)
self.ledit_Name_1 = QtGui.QLineEdit(self.centralwidget)
self.ledit_Name_1.setObjectName("ledit_Name_1")
self.PropertyLayout.addWidget(self.ledit_Name_1, 1, 1, 1, 1)
self.MainLayout.addLayout(self.PropertyLayout, 0, 0, 1, 1)
spacerItem2 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.MainLayout.addItem(spacerItem2, 1, 0, 1, 1)
self.horizontalLayout_2.addLayout(self.MainLayout)
fiberModesMainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(fiberModesMainWindow)
QtCore.QMetaObject.connectSlotsByName(fiberModesMainWindow)
# fiberModesMainWindow.setTabOrder(self.ledit_Name_1, self.ledit_Width_1)
# fiberModesMainWindow.setTabOrder(self.ledit_Width_1, self.cmb_RIType_1)
# fiberModesMainWindow.setTabOrder(self.cmb_RIType_1, self.ledit_RIParam_1)
# fiberModesMainWindow.setTabOrder(self.ledit_RIParam_1, self.pb_addRow_1)
def retranslateUi(self, fiberModesMainWindow):
fiberModesMainWindow.setWindowTitle(QtGui.QApplication.translate("fiberModesMainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.lbl_Name.setText(QtGui.QApplication.translate("fiberModesMainWindow", "Name", None, QtGui.QApplication.UnicodeUTF8))
self.pb_addRow_1.setText(QtGui.QApplication.translate("fiberModesMainWindow", "Add Row", None, QtGui.QApplication.UnicodeUTF8))
class DesignerMainWindow(QtGui.QMainWindow, Ui_fiberModesMainWindow):
def __init__(self, parent = None):
super(DesignerMainWindow, self).__init__(parent)
self.setupUi(self)
self.pb_addRow_1.clicked.connect( self.addRow )
self.ledit_Name = [ self.ledit_Name_1 ]
self.pb_Row = [ self.pb_addRow_1 ]
# number of rows
self.nRows = 1
def addRow( self ):
self.ledit_Name[-1].setEnabled(False)
self.pb_Row[-1].setText('Remove'+str(self.nRows))
self.pb_Row[-1].clicked.disconnect( self.addRow )
self.pb_Row[-1].clicked.connect( self.removeRow )
self.nRows += 1
self.ledit_Name.append( QtGui.QLineEdit(self.centralwidget) )
self.ledit_Name[-1].setObjectName('ledit_Name_'+str(self.nRows))
self.PropertyLayout.addWidget( self.ledit_Name[-1], self.nRows, 1, 1, 1)
self.pb_Row.append( QtGui.QPushButton(self.centralwidget) )
self.pb_Row[-1].setObjectName( 'pb_addRow_'+str(self.nRows) )
self.pb_Row[-1].setText('Add Row')
self.pb_Row[-1].clicked.connect( self.addRow )
self.PropertyLayout.addWidget( self.pb_Row[-1], self.nRows, 5, 1, 1)
def removeRow( self ):
iRow = int(self.sender().objectName().split('_')[-1])-1
self.nRows -= 1
ind = self.PropertyLayout.indexOf(self.ledit_Name[iRow])
t = self.PropertyLayout.takeAt(ind)
t.widget().setParent(None)
# t.widget().deleteLater()
# self.ledit_Name[iRow].hide()
# self.ledit_Name[iRow].deleteLater()
# self.ledit_Name[iRow].setParent(None)
self.ledit_Name.pop(iRow)
ind = self.PropertyLayout.indexOf(self.pb_Row[iRow])
t = self.PropertyLayout.takeAt(ind)
t.widget().setParent(None)
# t.widget().deleteLater()
# self.pb_Row[iRow].hide()
# self.pb_Row[iRow].deleteLater()
# self.pb_Row[iRow].setParent(None)
self.pb_Row.pop(iRow)
for iAfterRow in range(iRow, self.nRows):
self.ledit_Name[iAfterRow].setObjectName( 'ledit_Name_' + str(iAfterRow+1) )
self.pb_Row[iAfterRow].setObjectName( 'ledit_Name_' + str(iAfterRow+1) )
print 'Remove row', iRow
if __name__ == '__main__':
app = QtGui.QApplication( sys.argv )
dmw = DesignerMainWindow()
dmw.show()
sys.exit( app.exec_() )发布于 2014-01-19 21:20:28
这里的问题是由QGridLayout的实现细节引起的。
每当从QGridLayout中删除项时,逻辑行和列的数量将永远不会减少,即使可视行或列的数量可能会减少。因此,应该始终使用QGridLayout中的项目直接使用getItemPosition和itemAtPosition等方法。
下面是使用这种方法从示例中重写DesignerMainWindow类。显然,它可能需要稍加调整才能与您的实际应用程序一起工作。
class DesignerMainWindow(QtGui.QMainWindow, Ui_fiberModesMainWindow):
def __init__(self, parent = None):
super(DesignerMainWindow, self).__init__(parent)
self.setupUi(self)
self.pb_addRow_1.clicked.connect( self.addRow )
def addRow( self ):
rows = self.PropertyLayout.rowCount()
columns = self.PropertyLayout.columnCount()
for column in range(columns):
layout = self.PropertyLayout.itemAtPosition(rows - 1, column)
if layout is not None:
widget = layout.widget()
if isinstance(widget, QtGui.QPushButton):
widget.setText('Remove %d' % (rows - 1))
widget.clicked.disconnect(self.addRow)
widget.clicked.connect(self.removeRow)
else:
widget.setEnabled(False)
widget = QtGui.QLineEdit(self.centralwidget)
self.PropertyLayout.addWidget(widget, rows, 1, 1, 1)
widget = QtGui.QPushButton(self.centralwidget)
widget.setText('Add Row')
widget.clicked.connect(self.addRow)
self.PropertyLayout.addWidget(widget, rows, columns - 1, 1, 1)
def removeRow(self):
index = self.PropertyLayout.indexOf(self.sender())
row = self.PropertyLayout.getItemPosition(index)[0]
for column in range(self.PropertyLayout.columnCount()):
layout = self.PropertyLayout.itemAtPosition(row, column)
if layout is not None:
layout.widget().deleteLater()
self.PropertyLayout.removeItem(layout)发布于 2014-01-19 07:26:06
编辑:这不能解决问题,我还找到了我的知识来源:有什么方法可以删除QWidget中的QGridLayout吗?
-出于某种原因,从布局中删除小部件很困难。我花了很长时间去寻找答案,但我不记得我在哪里找到的,但我离题了.
你需要做的是以下几点。首先,找到要删除的项。您可以使用layout.itemAt()或layout.itemAtPosition获取对它的引用。
现在,要从布局中删除该项,只需调用item.widget().setParent(None)。这将产生从布局中移除项目的效果!
注意:如果您已经有了对小部件的引用,那么您可能只需在它上调用setParent,而不必从布局中找到它。不过,我还没试过(但不明白为什么不行)。
发布于 2014-01-19 13:59:01
看起来,您没有为想要删除的所有单元格调用QGridLayout::removeWidget()。然后,由于PySide,布局将继续引用这些小部件,并且当您调用setParent(None)时,它们并没有被真正删除/删除。
同样,当您在没有QLayout::removeWidget()的单元格中尝试小部件的deleteLater()时,该单元格将不会被移除,而是保持活动(单元格中将保留QLayoutItem )。
https://stackoverflow.com/questions/21213853
复制相似问题