从选定单元格移动时,Qtablewidget未记录崩溃

2024-10-01 04:44:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用QT构建了一个GUI,在这个GUI中有一个Qtablewidget,它最初由一个空行(9列)构建。当用户在第一列中输入数据时,将添加一个新行,以确保末尾始终有一个空行。此外,如果用户从第一列删除数据,则该行将被删除(始终保留一个空行)

生成表格并执行上述操作(带格式)的代码附在下面

除了在以下情况下发生持续性崩溃外,所有这些都可以正常工作: 当有多行时,用户双击第一列中的一个单元格进行编辑,然后不按回车/回车键单击第1列以外的另一个单元格

如果遵循此顺序,程序将关闭。根本没有生成任何错误消息,所以我很困惑是什么原因导致了它

期望的行为是,用户可以单击所述表中他们喜欢的任何位置,并且不会出现崩溃

我研究了许多线程和其他资源,没有发现任何类似的东西。我也尝试过重新调整编码,但没有成功

下面是一个示例代码(如果有点长,很抱歉,我不想去掉可能是原因的任何组合!):

#####################################################################
############ qtable widget test #####################################
#####################################################################
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt


############################## Define a function to add a row to the reponse table ################
def ResponsetableRows():
    rowchanged=mygui.TableResTimetable.currentItem().row() #pick up the index of the changed row
    columnchanged=mygui.TableResTimetable.currentItem().column() #pick up the index of the changed column
  
    if columnchanged==0 and len(mygui.TableResTimetable.currentItem().text())!=0: #if the name column (id=0) has changed and is not blank then rin the code to add content/ format to row
        
        #first we add the cell items to the row that we just changed
        font = QtGui.QFont()
        font.setFamily("Calibri")
        font.setPointSize(11)

        
        comboBox = QtWidgets.QComboBox()    #defining thc combobox in Col 2 
        comboBox.addItems(["1","2","3","1(T'nee)","2(T'nee)","3(T'nee)","1(Obs)","2(Obs)","3(Obs)"])
        comboBox.setFont(font)
        comboBox.setStyleSheet("border-style:none") #remove the frame
        mygui.TableResTimetable.setCellWidget(rowchanged, 1, comboBox)

        shiftBox=QtWidgets.QSpinBox()
        shiftBox.setFont(font)
        shiftBox.setMinimum(1)
        shiftBox.setButtonSymbols(2) #removes the +/- buttons form the spinbox
        shiftBox.setStyleSheet("border-style:none") #remove the frame
        shiftBox.setAlignment(QtCore.Qt.AlignCenter)
        mygui.TableResTimetable.setCellWidget(rowchanged, 2, shiftBox)   

        dateBoxStart = QtWidgets.QDateEdit()         # define the date box and add to 4th cols (index 3)
        dateBoxStart.setFont(font)
        dateBoxStart.setDateTime(QtCore.QDateTime.currentDateTime())
        dateBoxStart.setButtonSymbols(2) #removes the +/- buttons form the spinbox
        dateBoxStart.setStyleSheet("border-style:none") #remove the frame
        mygui.TableResTimetable.setCellWidget(rowchanged, 3, dateBoxStart)


        dateBoxEnd = QtWidgets.QDateEdit()         # define the date box and add to 6th cols (index 5)
        dateBoxEnd.setFont(font)
        dateBoxEnd.setDateTime(QtCore.QDateTime.currentDateTime())
        dateBoxEnd.setButtonSymbols(2) #removes the +/- buttons form the spinbox
        dateBoxEnd.setStyleSheet("border-style:none") #remove the frame
        mygui.TableResTimetable.setCellWidget(rowchanged, 5, dateBoxEnd)
        

        TimeBoxStart = QtWidgets.QTimeEdit()        #define the time picker and add to 5th col (index 4)
        TimeBoxStart.setFont(font)
        TimeBoxStart.setDateTime(QtCore.QDateTime.currentDateTime())
        TimeBoxStart.setButtonSymbols(2) #removes the +/- buttons form the spinbox
        TimeBoxStart.setStyleSheet("border-style:none") #remove the frame
        mygui.TableResTimetable.setCellWidget(rowchanged, 4, TimeBoxStart)

        TimeBoxEnd = QtWidgets.QTimeEdit()        #define the time picker and add to 7th col (index 6)
        TimeBoxEnd.setFont(font)
        TimeBoxEnd.setDateTime(QtCore.QDateTime.currentDateTime())
        TimeBoxEnd.setButtonSymbols(2) #removes the +/- buttons form the spinbox
        TimeBoxEnd.setStyleSheet("border-style:none") #remove the frame
        mygui.TableResTimetable.setCellWidget(rowchanged, 6, TimeBoxEnd)

        MoneyBox = QtWidgets.QDoubleSpinBox()        #define the money picker and add to 9th col (index 6)
        MoneyBox.setMaximum(1000.00)
        MoneyBox.setPrefix("£ ")
        MoneyBox.setFont(font)
        MoneyBox.setButtonSymbols(2) #removes the +/- buttons form the spinbox
        MoneyBox.setStyleSheet("border-style:none") #remove the frame
        mygui.TableResTimetable.setCellWidget(rowchanged, 8, MoneyBox)       


        #Then we check to see if the row at the end is blank (none type or blank in 1st cell), if not then we add a new row at the end of the table this one for the next data.
        if mygui.TableResTimetable.rowCount()==0:
            mygui.TableResTimetable.insertRow(mygui.TableResTimetable.rowCount())
        elif (mygui.TableResTimetable.cellWidget(mygui.TableResTimetable.rowCount()-1,0))==None:
            pass
        elif (mygui.TableResTimetable.cellWidget(mygui.TableResTimetable.rowCount()-1,0).text())!="":
            mygui.TableResTimetable.insertRow(mygui.TableResTimetable.rowCount())    
                    
    #if the name column is changed and the length is 0 (emptied) then we clear the row
    elif columnchanged==0 and (len(mygui.TableResTimetable.currentItem().text())==0): 
        mygui.TableResTimetable.removeRow(rowchanged)

        if mygui.TableResTimetable.rowCount()==0:
            mygui.TableResTimetable.insertRow(mygui.TableResTimetable.rowCount())
        elif (mygui.TableResTimetable.cellWidget(mygui.TableResTimetable.rowCount()-1,0))==None:
            pass
        elif (mygui.TableResTimetable.cellWidget(mygui.TableResTimetable.rowCount()-1,0).text())!="":
            mygui.TableResTimetable.insertRow(mygui.TableResTimetable.rowCount())  

#FIXME going from a blank cell to any other causes an undocumented close!



class MyGui(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.setGeometry(0,0,1200,400)


#########################################Basic table def######################################################
        self.TableResTimetable = QtWidgets.QTableWidget(self)
        self.TableResTimetable.setGeometry(QtCore.QRect(10, 10, 1151, 351))
        font = QtGui.QFont()
        font.setFamily("Calibri")
        font.setPointSize(11)
        self.TableResTimetable.setFont(font)
        self.TableResTimetable.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.TableResTimetable.setEditTriggers(QtWidgets.QAbstractItemView.AllEditTriggers)
        self.TableResTimetable.setProperty("showDropIndicator", False)
        self.TableResTimetable.setDragDropOverwriteMode(False)
        self.TableResTimetable.setAlternatingRowColors(False)
        self.TableResTimetable.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.TableResTimetable.setGridStyle(QtCore.Qt.DashDotLine)
        self.TableResTimetable.setWordWrap(True)
        self.TableResTimetable.setCornerButtonEnabled(False)
        self.TableResTimetable.setRowCount(1)
        self.TableResTimetable.setColumnCount(9)
        self.TableResTimetable.setObjectName("TableResTimetable")
        item = QtWidgets.QTableWidgetItem()
        font = QtGui.QFont()
        font.setFamily("Calibri")
        font.setPointSize(10)
        item.setFont(font)
        self.TableResTimetable.setVerticalHeaderItem(0, item)
        self.TableResTimetable.setHorizontalHeaderItem(0, item)
        self.TableResTimetable.setHorizontalHeaderItem(1, item)
        self.TableResTimetable.setHorizontalHeaderItem(2, item)
        self.TableResTimetable.setHorizontalHeaderItem(3, item)
        self.TableResTimetable.setHorizontalHeaderItem(4, item)
        self.TableResTimetable.setHorizontalHeaderItem(5, item)
        self.TableResTimetable.setHorizontalHeaderItem(6, item)
        self.TableResTimetable.setHorizontalHeaderItem(7, item)
        self.TableResTimetable.setHorizontalHeaderItem(8, item)

#Size table for the Response Timetable
        self.TableResTimetable.setColumnWidth(0, 170) #Team member Name
        self.TableResTimetable.setColumnWidth(1, 70) #Role
        self.TableResTimetable.setColumnWidth(2, 70) #Shift
        self.TableResTimetable.setColumnWidth(3, 85) #StartDate
        self.TableResTimetable.setColumnWidth(4, 80) #Start Time
        self.TableResTimetable.setColumnWidth(5, 85) #End Date
        self.TableResTimetable.setColumnWidth(6, 80) #End Time
        self.TableResTimetable.setColumnWidth(7, 320) #Expenses Description
        self.TableResTimetable.setColumnWidth(8, 100) #Expenses Total
         
             
        self.show()



if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)   #Generate and show UI
    mygui = MyGui()
    mygui.show()

###################### Signal emit and action #########################################################################
    mygui.TableResTimetable.cellChanged.connect(ResponsetableRows) # catch signal on TableResTimetable change and connect to 

#############################    End call   ##########################################################
    sys.exit(app.exec_())

请注意,列0未分配小部件/项目,因此我认为它默认为QLineEdit

如果有人能为我提供任何帮助,或者有人能为我指出其他问题的方向,我将不胜感激


Tags: andthetoselfadditemfontqtcore
1条回答
网友
1楼 · 发布于 2024-10-01 04:44:08

谢谢大家的帮助和建议

我最终选择了在每一行添加一个按钮。 我尝试将QlineEdit小部件设置为第一列以删除任何非类型,但是,这会干扰“cellChanged”信号。虽然我确信这是可以克服的,但我还是采纳了我认为最有利的建议

以下是我更新的最低可行代码。它仍然有点重,也不是特别整洁,但它似乎起了作用。 我希望这对某人有帮助

#####################################################################
############ qtable widget test #####################################
#####################################################################
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt


############################## Define a function to add a row to the reponse table ################
def ResponsetableRows():
    rowchanged=mygui.TableResTimetable.currentItem().row() #pick up the index of the changed row
    columnchanged=mygui.TableResTimetable.currentItem().column() #pick up the index of the changed column
 
    if columnchanged==0 and len(mygui.TableResTimetable.currentItem().text())!=0: #if the name column (id=0) has changed and is not blank then run the code to add content/ format to row

        print("doing formating stuff")
        
        #NEW              add in the new delete button to final col
        deletebutton  =  QtWidgets.QPushButton("Del")
        deletebutton.clicked.connect(DELTABrow)
        mygui.TableResTimetable.setCellWidget(rowchanged, 9, deletebutton) 

        #Then we check to see if the row at the end is blank (none type or blank in 1st cell), if not then we add a new row at the end of the table this one for the next data.
        if mygui.TableResTimetable.rowCount()==0: #if reduced to 0 rows
            mygui.TableResTimetable.insertRow(mygui.TableResTimetable.rowCount())
        elif (mygui.TableResTimetable.cellWidget(mygui.TableResTimetable.rowCount()-1,0).text())!="":
            mygui.TableResTimetable.insertRow(mygui.TableResTimetable.rowCount())    

######### NEW FUNCTION -                  identify where button clicked was and delete relevent row #####                    
def DELTABrow():
    btnClick = QtWidgets.QApplication.focusWidget()
    index = mygui.TableResTimetable.indexAt(btnClick.pos())
    if index.isValid():
        mygui.TableResTimetable.removeRow(index.row())
##################################################################

class MyGui(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.setGeometry(0,0,1200,400)


#########################################Basic table def######################################################
        self.TableResTimetable = QtWidgets.QTableWidget(self)
        self.TableResTimetable.setGeometry(QtCore.QRect(10, 10, 1151, 351))
        font = QtGui.QFont()
        font.setFamily("Calibri")
        font.setPointSize(11)
        self.TableResTimetable.setFont(font)
        self.TableResTimetable.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.TableResTimetable.setEditTriggers(QtWidgets.QAbstractItemView.AllEditTriggers)
        self.TableResTimetable.setProperty("showDropIndicator", False)
        self.TableResTimetable.setDragDropOverwriteMode(False)
        self.TableResTimetable.setAlternatingRowColors(False)
        self.TableResTimetable.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.TableResTimetable.setGridStyle(QtCore.Qt.DashDotLine)
        self.TableResTimetable.setWordWrap(True)
        self.TableResTimetable.setCornerButtonEnabled(False)
        self.TableResTimetable.setRowCount(1)
        self.TableResTimetable.setColumnCount(10)                        #NEW        col count increased by 1
        self.TableResTimetable.setObjectName("TableResTimetable")



#Size table for the Response Timetable
        self.TableResTimetable.setColumnWidth(0, 170) #Team member Name
        self.TableResTimetable.setColumnWidth(1, 70) #Role
        self.TableResTimetable.setColumnWidth(2, 70) #Shift
        self.TableResTimetable.setColumnWidth(3, 85) #StartDate
        self.TableResTimetable.setColumnWidth(4, 80) #Start Time
        self.TableResTimetable.setColumnWidth(5, 85) #End Date
        self.TableResTimetable.setColumnWidth(6, 80) #End Time
        self.TableResTimetable.setColumnWidth(7, 320) #Expenses Description
        self.TableResTimetable.setColumnWidth(8, 100) #Expenses Total
        self.TableResTimetable.setColumnWidth(9, 30) # NEW              col for delete button################################################
            
        self.show()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)   #Generate and show UI
    mygui = MyGui()
    mygui.show()

###################### Signal emit and action #########################################################################
    mygui.TableResTimetable.cellChanged.connect(ResponsetableRows) # catch signal on TableResTimetable change and connect to

#############################    End call   ##########################################################
    sys.exit(app.exec_())

代码的末尾仍然保留一个空行,并允许用户删除他们选择的任何行。添加行的代码在很大程度上保持不变,但是覆盖非类型的任何逻辑语句都已删除。 我试图强调代码中新增的内容,以便清楚地了解更改的内容

虽然这对我来说是一个解决方案,但我仍然想知道自动化方法会是什么样子!如果有人有任何想法,请做后,因为我相信有更好的方法来做我所做的

相关问题 更多 >