如何在 QGridLayout PyQt5 上获取索引或单击元素的位置?
How can I obtain the index or the position of a clicked element on QGridLayout PyQt5?
我需要获取在 pyqt5 中动态创建的按钮的索引或位置,我有这段代码,但目前当我单击 [-] 按钮时,我得到了最后添加的按钮的位置。
import sys
from PyQt5.QtWidgets import (QLineEdit, QLabel, QGridLayout, QWidget,
QPushButton, QApplication, QSpinBox)
class Window(QWidget):
def __init__(self):
super().__init__()
#Creating grid
self.grid = QGridLayout()
self.setLayout(self.grid)
#Creating elements
self.spn_amount = QSpinBox(self)
self.txt_registercode = QLineEdit(self)
self.txt_description = QLineEdit(self)
self.txt_cost = QLineEdit(self)
self.txt_total = QLineEdit(self)
self.btn_add = QPushButton("+",self) #Button that add rows
#adding functionality to [+] button
self.btn_add.clicked.connect(self.getrow_add)
#Adding elements to grid
self.grid.addWidget(self.spn_amount, 0, 0)
self.grid.addWidget(self.txt_registercode, 0, 1)
self.grid.addWidget(self.txt_description, 0, 2)
self.grid.addWidget(self.txt_cost, 0, 3)
self.grid.addWidget(self.txt_total, 0, 4)
self.grid.addWidget(self.btn_add, 0, 5)
self.row = 0
self.column = 0
def getrow_add(self): #Function that get a the actual row of the button to create a new row after
self.row = self.grid.rowCount() #Obtener el número de filas actuales en el grid
self.column = self.grid.columnCount() #Obtiene el número de columnas actuales en el grid
self.addtextbox()
def getrow_del(self):
index = self.grid.indexOf(self.btn_del_din)
position = self.grid.getItemPosition(index)
self.row = position[0] #Obtengo la posición de la fila
self.column = self.grid.columnCount() #Obtiene el número de columnas actuales en el grid
print(self.row)
def addtextbox(self):
self.lineEdits = []
#Creation of dynamicall elements
self.spn_amount_din = QSpinBox(self)
self.txt_registercode_din = QLineEdit(self)
self.txt_description_din = QLineEdit(self)
self.txt_cost_din = QLineEdit(self)
self.txt_total_din = QLineEdit(self)
self.btn_del_din = QPushButton("-",self) #Button that delete rows
#Adding functionality to the [-] button
self.btn_del_din.clicked.connect(self.getrow_del)
#Dynamically adding elements to grid
self.grid.addWidget(self.spn_amount_din, self.row, 0)
self.grid.addWidget(self.txt_registercode_din, self.row, 1)
self.grid.addWidget(self.txt_description_din, self.row, 2)
self.grid.addWidget(self.txt_cost_din, self.row, 3)
self.grid.addWidget(self.txt_total_din, self.row, 4)
self.grid.addWidget(self.btn_del_din, self.row, 5)
self.lineEdits.append('')
def deltextbox(self):
for i in range (1, self.column):
self.grid.itemAtPosition(self.row, i).widget().deleteLater()
if __name__ == "__main__":
application = QApplication(sys.argv)
window = Window()
window.setWindowTitle('Dynamically add elements')
window.show()
sys.exit(application.exec_())
当我点击 [-] 按钮时,我需要获取该小部件的具体位置。
Here is my GUI
例如这里我有 6 行和 6 列,如果我点击第一个按钮 [-] 我希望得到行的值为 1,列的值为 5,但是我不是从第一个按钮 [-] 而是从最后添加的第 5 行和第 5 列获得的值。
在我的代码中,我通过函数获得了它:
def getrow_del(self):
index = self.grid.indexOf(self.btn_del_din)
position = self.grid.getItemPosition(index)
self.row = position[0] #Obtengo la posición de la fila
self.column = self.grid.columnCount() #Obtiene el número de columnas actuales en el grid
print(self.row)
您的代码的主要问题是每次创建新行时您都在不断地覆盖实例属性。
使用动态创建对象的函数时,永远不要为这些对象创建实例属性除非您特别想保留对last 个元素已创建(这不是你的情况)。
为了正确保留对这些元素的引用,必须将它们添加到作为实例属性的持久对象容器(例如列表)中。
class Window(QWidget):
def __init__(self):
super().__init__()
self.grid = QGridLayout(self)
self.items = []
self.addRow()
def addRow(self):
spn_amount_din = QSpinBox()
txt_registercode_din = QLineEdit()
txt_description_din = QLineEdit()
txt_cost_din = QLineEdit()
txt_total_din = QLineEdit()
row = len(self.items)
if row == 0:
button = QPushButton('+')
button.clicked.connect(self.addRow)
else:
button = QPushButton('-')
button.clicked.connect(lambda: self.removeRow())
row_items = (spn_amount_din, txt_registercode_din, txt_description_din, txt_cost_din, txt_total_din, button)
self.items.insert(row, row_items)
for column, widget in enumerate(row_items):
self.grid.addWidget(widget, row, column)
def removeRow(self, row=None):
if row is None:
button = self.sender()
for row, widgets in enumerate(self.items):
if button in widgets:
break
widgets = self.items.pop(row)
for widget in widgets:
self.grid.removeWidget(widget)
widget.deleteLater()
self.adjustSize()
请注意,虽然 QGridLayout 提供 rowCount()
和 columnCount()
,但应谨慎使用它们,因为它们主要用于内部和基本的静态目的:行数和列数是 不 删除小部件时更新;这意味着如果你想实现更高级的实现(例如 插入 行或排序项目),QGridLayout 通常不是合适的选择。
更好的解决方案是使用主 QVBoxLayout 并将每一行添加为 nested QHBoxLayout,但更好的实现实际上应该使用 class 作为容器所有小部件,这使得整个概念更易于管理,并允许使用它们的属性直接访问每个行元素:
class OrderWidget(QWidget):
def __init__(self):
super().__init__()
self.spn_amount_din = QSpinBox()
self.txt_registercode_din = QLineEdit()
self.txt_description_din = QLineEdit()
self.txt_cost_din = QLineEdit()
self.txt_total_din = QLineEdit()
self.button = QPushButton()
layout = QHBoxLayout(self)
layout.addWidget(self.spn_amount_din)
layout.addWidget(self.txt_registercode_din)
layout.addWidget(self.txt_description_din)
layout.addWidget(self.txt_cost_din)
layout.addWidget(self.txt_total_din)
layout.addWidget(self.button)
class Window(QWidget):
def __init__(self):
super().__init__()
QVBoxLayout(self) # just create the layout and set it
self.items = []
self.insertRow(0)
def insertRow(self, row=None):
if row is None:
row = len(self.items)
widget = OrderWidget()
self.layout().addWidget(widget)
self.items.insert(row, widget)
if row == 0:
widget.button.setText('+')
widget.button.clicked.connect(lambda: self.insertRow())
else:
widget.button.setText('-')
widget.button.clicked.connect(lambda: self.removeRow(widget))
def removeRow(self, row):
if isinstance(row, QWidget):
widget = row
row = self.items.index(widget)
else:
widget = self.items[row]
self.layout().removeWidget(widget)
widget.deleteLater()
del self.items[row]
self.adjustSize()
我需要获取在 pyqt5 中动态创建的按钮的索引或位置,我有这段代码,但目前当我单击 [-] 按钮时,我得到了最后添加的按钮的位置。
import sys
from PyQt5.QtWidgets import (QLineEdit, QLabel, QGridLayout, QWidget,
QPushButton, QApplication, QSpinBox)
class Window(QWidget):
def __init__(self):
super().__init__()
#Creating grid
self.grid = QGridLayout()
self.setLayout(self.grid)
#Creating elements
self.spn_amount = QSpinBox(self)
self.txt_registercode = QLineEdit(self)
self.txt_description = QLineEdit(self)
self.txt_cost = QLineEdit(self)
self.txt_total = QLineEdit(self)
self.btn_add = QPushButton("+",self) #Button that add rows
#adding functionality to [+] button
self.btn_add.clicked.connect(self.getrow_add)
#Adding elements to grid
self.grid.addWidget(self.spn_amount, 0, 0)
self.grid.addWidget(self.txt_registercode, 0, 1)
self.grid.addWidget(self.txt_description, 0, 2)
self.grid.addWidget(self.txt_cost, 0, 3)
self.grid.addWidget(self.txt_total, 0, 4)
self.grid.addWidget(self.btn_add, 0, 5)
self.row = 0
self.column = 0
def getrow_add(self): #Function that get a the actual row of the button to create a new row after
self.row = self.grid.rowCount() #Obtener el número de filas actuales en el grid
self.column = self.grid.columnCount() #Obtiene el número de columnas actuales en el grid
self.addtextbox()
def getrow_del(self):
index = self.grid.indexOf(self.btn_del_din)
position = self.grid.getItemPosition(index)
self.row = position[0] #Obtengo la posición de la fila
self.column = self.grid.columnCount() #Obtiene el número de columnas actuales en el grid
print(self.row)
def addtextbox(self):
self.lineEdits = []
#Creation of dynamicall elements
self.spn_amount_din = QSpinBox(self)
self.txt_registercode_din = QLineEdit(self)
self.txt_description_din = QLineEdit(self)
self.txt_cost_din = QLineEdit(self)
self.txt_total_din = QLineEdit(self)
self.btn_del_din = QPushButton("-",self) #Button that delete rows
#Adding functionality to the [-] button
self.btn_del_din.clicked.connect(self.getrow_del)
#Dynamically adding elements to grid
self.grid.addWidget(self.spn_amount_din, self.row, 0)
self.grid.addWidget(self.txt_registercode_din, self.row, 1)
self.grid.addWidget(self.txt_description_din, self.row, 2)
self.grid.addWidget(self.txt_cost_din, self.row, 3)
self.grid.addWidget(self.txt_total_din, self.row, 4)
self.grid.addWidget(self.btn_del_din, self.row, 5)
self.lineEdits.append('')
def deltextbox(self):
for i in range (1, self.column):
self.grid.itemAtPosition(self.row, i).widget().deleteLater()
if __name__ == "__main__":
application = QApplication(sys.argv)
window = Window()
window.setWindowTitle('Dynamically add elements')
window.show()
sys.exit(application.exec_())
当我点击 [-] 按钮时,我需要获取该小部件的具体位置。
Here is my GUI
例如这里我有 6 行和 6 列,如果我点击第一个按钮 [-] 我希望得到行的值为 1,列的值为 5,但是我不是从第一个按钮 [-] 而是从最后添加的第 5 行和第 5 列获得的值。
在我的代码中,我通过函数获得了它:
def getrow_del(self):
index = self.grid.indexOf(self.btn_del_din)
position = self.grid.getItemPosition(index)
self.row = position[0] #Obtengo la posición de la fila
self.column = self.grid.columnCount() #Obtiene el número de columnas actuales en el grid
print(self.row)
您的代码的主要问题是每次创建新行时您都在不断地覆盖实例属性。
使用动态创建对象的函数时,永远不要为这些对象创建实例属性除非您特别想保留对last 个元素已创建(这不是你的情况)。
为了正确保留对这些元素的引用,必须将它们添加到作为实例属性的持久对象容器(例如列表)中。
class Window(QWidget):
def __init__(self):
super().__init__()
self.grid = QGridLayout(self)
self.items = []
self.addRow()
def addRow(self):
spn_amount_din = QSpinBox()
txt_registercode_din = QLineEdit()
txt_description_din = QLineEdit()
txt_cost_din = QLineEdit()
txt_total_din = QLineEdit()
row = len(self.items)
if row == 0:
button = QPushButton('+')
button.clicked.connect(self.addRow)
else:
button = QPushButton('-')
button.clicked.connect(lambda: self.removeRow())
row_items = (spn_amount_din, txt_registercode_din, txt_description_din, txt_cost_din, txt_total_din, button)
self.items.insert(row, row_items)
for column, widget in enumerate(row_items):
self.grid.addWidget(widget, row, column)
def removeRow(self, row=None):
if row is None:
button = self.sender()
for row, widgets in enumerate(self.items):
if button in widgets:
break
widgets = self.items.pop(row)
for widget in widgets:
self.grid.removeWidget(widget)
widget.deleteLater()
self.adjustSize()
请注意,虽然 QGridLayout 提供 rowCount()
和 columnCount()
,但应谨慎使用它们,因为它们主要用于内部和基本的静态目的:行数和列数是 不 删除小部件时更新;这意味着如果你想实现更高级的实现(例如 插入 行或排序项目),QGridLayout 通常不是合适的选择。
更好的解决方案是使用主 QVBoxLayout 并将每一行添加为 nested QHBoxLayout,但更好的实现实际上应该使用 class 作为容器所有小部件,这使得整个概念更易于管理,并允许使用它们的属性直接访问每个行元素:
class OrderWidget(QWidget):
def __init__(self):
super().__init__()
self.spn_amount_din = QSpinBox()
self.txt_registercode_din = QLineEdit()
self.txt_description_din = QLineEdit()
self.txt_cost_din = QLineEdit()
self.txt_total_din = QLineEdit()
self.button = QPushButton()
layout = QHBoxLayout(self)
layout.addWidget(self.spn_amount_din)
layout.addWidget(self.txt_registercode_din)
layout.addWidget(self.txt_description_din)
layout.addWidget(self.txt_cost_din)
layout.addWidget(self.txt_total_din)
layout.addWidget(self.button)
class Window(QWidget):
def __init__(self):
super().__init__()
QVBoxLayout(self) # just create the layout and set it
self.items = []
self.insertRow(0)
def insertRow(self, row=None):
if row is None:
row = len(self.items)
widget = OrderWidget()
self.layout().addWidget(widget)
self.items.insert(row, widget)
if row == 0:
widget.button.setText('+')
widget.button.clicked.connect(lambda: self.insertRow())
else:
widget.button.setText('-')
widget.button.clicked.connect(lambda: self.removeRow(widget))
def removeRow(self, row):
if isinstance(row, QWidget):
widget = row
row = self.items.index(widget)
else:
widget = self.items[row]
self.layout().removeWidget(widget)
widget.deleteLater()
del self.items[row]
self.adjustSize()