我有一个定制的QWidget,我已经嵌入到QTableWidget中了。当我切换QCheckBoxes并修改QLineEdit小部件中的文本时,程序无法将第2行和第1行中的小部件与第0行中的小部件区分开来。如何更改程序,以便打印正在编辑的QLineEdit小部件的正确行和列或正在切换的复选框?
图1在Visual中多次选择第三个复选框后,显示了该程序的屏幕截图和输出。预期输出将重复读取“2.0”,但它将读取“0”。
图2类似地,当我将单元格2,0中的QLineEdit中的文本从“我的自定义文本”修改为“text”时,程序会打印“Handle Cell Edited 0,0,0”,尽管预计它会打印“Handle Cell Edited 2,0 cell 2,0已更改为Text”。
代码:
# Much of this code is copy pasted form user: three_pineapples post on stackoverflow:
# https://stackoverflow.com/a/26311179/18914416
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QTableWidget, \
QApplication, QTableWidgetItem, QLineEdit, QCheckBox
from PyQt5 import QtGui
class SimpleTable(QTableWidget):
def __init__(self,window):
# Call the parent constructor
QTableWidget.__init__(self)
self.window = window
class myWidget(QWidget):
#This code is adapted paritally form a post by user sebastian at:
#https://stackoverflow.com/a/29764770/18914416
def __init__(self,parent=None):
super(myWidget,self).__init__()
self.Layout1 = QHBoxLayout()
self.item = QLineEdit("My custom text")
#https://stackabuse.com/working-with-pythons-pyqt-framework/
self.Checkbox = QCheckBox()
self.Checkbox.setCheckState(Qt.CheckState.Unchecked)
self.Layout1.addWidget(self.Checkbox)
self.Layout1.addWidget(self.item)
#https://stackoverflow.com/questions/29764395/adding-multiple-widgets-to-qtablewidget-cell-in-pyqt
self.item.home(True)
#https://www.qtcentre.org/threads/58387-Left-text-alignment-for-long-text-on-QLineEdit
self.setLayout(self.Layout1)
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
layout = QHBoxLayout()
self.setLayout(layout)
self.table_widget = SimpleTable(window=self)
layout.addWidget(self.table_widget)
self.table_widget.setColumnCount(3)
self.table_widget.setHorizontalHeaderLabels(['Colour', 'Model'])
items = [('Red', 'Toyota'), ('Blue', 'RV'), ('Green', 'Beetle')]
for i in range(len(items)):
c = QTableWidgetItem(items[i][0])
m = QTableWidgetItem(items[i][1])
self.table_widget.insertRow(self.table_widget.rowCount())
self.table_widget.setItem(i, 1, c)
self.table_widget.setItem(i, 2, m)
myWidget1 = myWidget()
myWidget1.Checkbox.stateChanged.connect(self.handleButtonClicked)
myWidget1.item.editingFinished.connect(self.handle_cell_edited)
self.table_widget.setCellWidget(i,0,myWidget1)
myWidget1.Layout1.setContentsMargins(50*i+10,0,0,0)
self.show()
self.table_widget.itemChanged.connect(self.handle_cell_edited)
def handleButtonClicked(self):
#Adapted from a post by user: Andy at:
# https://stackoverflow.com/a/24149478/18914416
button = QApplication.focusWidget()
# or button = self.sender()
index = self.table_widget.indexAt(button.pos())
if index.isValid():
print(index.row(), index.column())
# I added this fuction:
def handle_cell_edited(self):
if QApplication.focusWidget() != None:
index = self.table_widget.indexAt(QApplication.focusWidget().pos())
x,y = index.column(),index.row()
if index.isValid():
print("Handle Cell Edited",index.row(), index.column())
if self.table_widget.item(y,x)!= None:
print(f"Cell {x},{y} was changed to {self.table_widget.item(y,x).text()}.")
def main():
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
main()到目前为止我尝试过的:
我了解到QT有两种类型的小部件可以嵌入到表中;QTableWigetItem可以使用setItem()(3.)插入到表中,Qwidget可以使用setCellWidget()放置到表中。(4.)通常,我知道使用QTableWigetItem one可以设置item.setFlags(Qt.ItemFlag.ItemIsUserCheckable)标志在单元格中创建复选框。(3.)然而,在使用QTableWigetItem时,我无法找到缩进复选框的方法。因为在我的程序上下文中给每个复选框赋予自己的缩进级别很重要,所以我决定在缩进很重要的少数选定单元格中使用Qwidgets而不是QTableWigetItems。我读过,通过创建一个QItemDelegate(5)(6),,您可以通过在框中设置QWidget来做更多的事情。然而,创建一个委托似乎很复杂,所以如果可能的话,我更愿意避免这种情况。如果没有其他方法使程序注册正在编辑的单元格的正确单元号,则创建委托将是我接下来要研究的事情。
对于任何想要在这个应用程序中使用QTableWigetItems的人来说,这里有一个类似的程序,它使用QTableWigetItems而不是QWidgets,但不允许对列0中的文本字段进行单独的缩进或编辑。由于这两个原因之一,QTableWigetItem似乎不能用于列0中的复选框。
使用QTableWidgetItem:的不太成功的尝试
#Much of this code is copy pasted form user: three_pineapples post on stackoverflow:
# https://stackoverflow.com/a/26311179/18914416
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QTableWidget, \
QApplication, QTableWidgetItem, QLineEdit, QCheckBox
from PyQt5 import QtGui
class SimpleTable(QTableWidget):
def __init__(self,window):
QTableWidget.__init__(self)
self.window = window
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
layout = QHBoxLayout()
self.setLayout(layout)
self.table_widget = SimpleTable(window=self)
layout.addWidget(self.table_widget)
self.table_widget.setColumnCount(3)
self.table_widget.setHorizontalHeaderLabels(['Colour', 'Model'])
items = [('Red', 'Toyota'), ('Blue', 'RV'), ('Green', 'Beetle')]
for i in range(len(items)):
c = QTableWidgetItem(items[i][0])
m = QTableWidgetItem(items[i][1])
self.table_widget.insertRow(self.table_widget.rowCount())
self.table_widget.setItem(i, 1, c)
self.table_widget.setItem(i, 2, m)
item = QTableWidgetItem("My Custom Text")
item.setFlags(Qt.ItemFlag.ItemIsUserCheckable| Qt.ItemFlag.ItemIsEnabled)
item.setCheckState(Qt.CheckState.Unchecked)
self.table_widget.setItem(i,0,item)
#https://youtu.be/DM8Ryoot7MI?t=251
self.show()
#I added this line:
self.table_widget.itemChanged.connect(self.handle_cell_edited)
def handleButtonClicked(self):
#Adapted from a post by user: Andy at:
# https://stackoverflow.com/a/24149478/18914416
button = QApplication.focusWidget()
# or button = self.sender()
index = self.table_widget.indexAt(button.pos())
if index.isValid():
print(index.row(), index.column())
# I added this fuction:
def handle_cell_edited(self):
if QApplication.focusWidget() != None:
index = self.table_widget.indexAt(QApplication.focusWidget().pos())
x,y = index.column(),index.row()
if index.isValid():
print("Handle Cell Edited",index.row(), index.column())
if self.table_widget.item(y,x)!= None:
print(f"Cell {x},{y} was changed to {self.table_widget.item(y,x).text()}.")
def main():
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
main()书目:
1.https://i.stack.imgur.com/FudE3.png
2.https://i.stack.imgur.com/C2ypp.png
3.https://youtu.be/DM8Ryoot7MI?t=251
5.为QWidgets,https://stackoverflow.com/a/35418141/18914416创建一个https://stackoverflow.com/a/35418141/18914416
6.需要创建一个QItemDelegate来向QTableWidgetItem:https://forum.qt.io/topic/13124/solved-qtablewidgetitem-set-stylesheet添加样式表
发布于 2022-06-13 17:21:04
小部件的几何形状总是相对于它的父部件。
在第一个示例中,问题是小部件返回的pos()相对于myWidget容器,而且由于垂直位置总是在父级顶部以下几个像素(布局边距),所以总是得到相同的值。
第二个例子有另一个概念上的问题: checkable的复选框不是实际的小部件,所以您得到的小部件就是表本身。
def handle_cell_edited(self):
# this will print True
print(isinstance(QApplication.focusWidget(), QTableWidget))正如上面所解释的,几何总是相对于父的,所以您实际上将得到表相对于窗口的位置。
第一种情况的解决办法很简单,只要你了解坐标系的相对性。请注意,您不应该依赖focusWidget() (小部件可能不接受焦点),而是实际获取sender(),它是发出信号的对象:
def handleButtonClicked(self):
sender = self.sender()
if not self.table_widget.isAncestorOf(sender):
return
# the widget coordinates must *always* be mapped to the viewport
# of the table, as the headers add margins
pos = sender.mapTo(self.table_widget.viewport(), QPoint())
index = self.table_widget.indexAt(pos)
if index.isValid():
print(index.row(), index.column())实际上,这可能并不是必要的,因为如果缩进是惟一的要求,那么项委托就足够了:解决方案是在initStyleOption()中正确地设置initStyleOption()并为缩进使用自定义角色:
IndentRole = Qt.UserRole + 1
class IndentDelegate(QStyledItemDelegate):
def initStyleOption(self, opt, index):
super().initStyleOption(opt, index)
indent = index.data(IndentRole)
if indent is not None:
left = min(opt.rect.right(),
opt.rect.x() + indent)
opt.rect.setLeft(left)
class SimpleTable(QTableWidget):
def __init__(self,window):
QTableWidget.__init__(self)
self.window = window
self.setItemDelegateForColumn(0, IndentDelegate(self))
class Window(QWidget):
def __init__(self):
# ...
for i in range(len(items)):
# ...
item.setData(IndentRole, 20 * i)https://stackoverflow.com/questions/72606180
复制相似问题