pyqt5插槽参数在第一次致电后未更新

发布于 2025-02-13 10:43:31 字数 8932 浏览 0 评论 0原文

我有一个信号,该信号连接到我用来更改matplotlib图上X范围跨度的插槽。当用户更改显示所有跨度的表中的启动X值时,我正在尝试更新跨度。但是,在第一个跨度编辑之后,程序编辑所有内容都好像它们正在编辑相同的跨度,而不是新选择的跨度。运行代码时:

@QtCore.pyqtSlot()
    def xStartChanged(xStart, rowVal):
        if self.inCounter == 0:
            print( "row in start changed: ", rowVal)
            print("xStart in start changed: ", xStart)
            print(type(xStart))
            tagName = self.highlights[xStart].tag
            xEnd = self.highlights[xStart].xEnd
            xStartNew = int(self.taggingTable.item(rowVal, 1).text())
            self.highlights[xStart].highlightObj.remove() #remove old from the plot
            del self.highlights[xStart]                   #remove old from directory
            highlightObj = self.Axes.axvspan(xStartNew, xEnd, color = 'blue', alpha = 0.5) #add new to plot
            
            self.highlights[xStartNew] = highlight(tagName, xStartNew, xEnd, highlightObj) #add new to directory
            self.taggingTable.clearSelection() #deselect value from table
            self.draw_idle()#update plot
        self.inCounter = self.inCounter + 1

     def onCellSelect():
            index = self.taggingTable.selectedIndexes()
            if len(index) != 0:
                rowVal = index[0].row()
                #get the starting adn ending indices so they can be edited. 
                ##deal with empty cell click
                if not (self.taggingTable.item(rowVal, 1) is None):
                    xStart = int(self.taggingTable.item(rowVal, 1).text())
                    print("row in cell select: ", rowVal)
                    print("xStart in cell select: ", xStart)
                    xEnd = int(self.taggingTable.item(rowVal, 2).text())
                    self.inCounter = 0
                    #self.taggingTable.itemChanged.connect(lambda state, item = None, xStartVal = xStart, rowValFxn = rowVal: xStartChanged(xStartVal, rowValFxn))
                    print(type(xStart))
                    self.taggingTable.itemChanged.connect(lambda item = None, xStart = xStart: xStartChanged(xStart, rowVal))
                    self.draw_idle()
                    #self.taggingTable.itemChanged.connect(xEndChanged)
                
    #self.taggingTable.cellDoubleClicked.connect(onCellSelect)
    self.taggingTable.selectionModel().selectionChanged.connect(onCellSelect)
    self.draw_idle()

我将获得以下输出:(注意:我隐藏了“路径”,因为它与工作有关,对不起

row in cell select:  0
xStart in cell select:  3517
<class 'int'>
row in start changed:  0
xStart in start changed:  3517
<class 'int'>
row in cell select:  1
xStart in cell select:  2801
<class 'int'>
row in start changed:  0
xStart in start changed:  3517
<class 'int'>
Traceback (most recent call last):
  File "path", line 314, in <lambda>
    self.taggingTable.itemChanged.connect(lambda item = None, xStart = xStart: xStartChanged(xStart, rowVal))
  File "path", line 277, in xStartChanged
    tagName = self.highlights[xStart].tag
KeyError: 3517
zsh: abort      path

。在更改和编辑单元格之后,第一个插槽函数(OnCellSelect)正在读取新的单元格值和XSTART值,但是嵌套的信号插槽连接(XstartChanged)仍将保留在较旧的单元格和XSTART值上。我假设我在某种程度上打电话给它,我没有意识到

编辑

    import sys
   
    from PyQt5.QtWidgets import *
    from PyQt5 import QtCore
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    
    from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
    from matplotlib.figure import Figure
    import matplotlib.widgets as mwidgets
    
    class Window(QMainWindow):
    
        def __init__(self, parent = None):
            super(Window, self).__init__(parent)
            self.resize(1600, 800)
            self.MyUI()
            
        def MyUI(self):
    
            canvas = Canvas(self, width=14, height=12, dpi=100)
            canvas.move(0,0)
    
    class Canvas(FigureCanvas):
        def __init__(self, parent, width = 14, height = 12, dpi = 100):
            Plot = Figure(figsize=(width, height), dpi=dpi)
            self.Axes = Plot.add_subplot(111)
            self.Axes.set_position([0.05, 0.58, 0.66, 0.55])
            self.rowCount = 0
            super().__init__(Plot)
            self.setParent(parent)
    
            
            ##add all relevant lines to plot 
            self.Axes.plot([0,1,2,3,4], [3, 4, 5, 6, 7])
            self.Axes.set_xlabel('Frame', fontsize = 10) 
            self.Axes.grid()
            self.Axes.set_aspect(1)
            Plot.canvas.draw()
    
    
            #use this object in the dictionary to hold onto all the spans. 
            class highlight:
                def __init__(self, tag, xStart, xEnd, highlightObj):
                    self.tag = tag
                    self.xStart = xStart
                    self.xEnd = xEnd
                    self.highlightObj = highlightObj
    
            self.highlights = {} #empty dictionary to store all the tags.
    
            ##define a table to hold the values postselection
            self.taggingTable = QTableWidget(self)
            self.taggingTable.setColumnCount(3)
            self.taggingTable.setRowCount(100)
            self.taggingTable.setGeometry(QRect(1005,85, 330, 310))
            self.taggingTable.setHorizontalHeaderLabels(['Behavior','Start Frame', 'End Frame'])
    
            ##highlighting adds a highlight item to the directory. 
            def onHighlight(xStart, xEnd):
                tagName = "No Tag"
                self.taggingTable.setItem(self.rowCount, 0, QTableWidgetItem(tagName))
                self.taggingTable.setItem(self.rowCount, 1, QTableWidgetItem(str(int(xStart))))
                self.taggingTable.setItem(self.rowCount, 2, QTableWidgetItem(str(int(xEnd))))
                self.rowCount = self.rowCount + 1
                highlightObj = self.Axes.axvspan(xStart, xEnd, color = 'blue', alpha = 0.5)
                self.highlights[int(xStart)] = highlight(tagName, xStart, xEnd, highlightObj)
                self.draw_idle()
                    
            self.span = mwidgets.SpanSelector(self.Axes, onHighlight, "horizontal", 
                                            interactive = True, useblit=True, props=dict(alpha=0.5, facecolor="blue"),)
            self.draw_idle()
    
            ##TODO: editing spans in table is reflected in plot --- use axvspan to track spans? and spanselector to draw them?
            ##define workflow for when a cell is selected
            def xStartChanged(xStart, rowVal):
                if self.inCounter == 0:
                    print( "row in start changed: ", rowVal)
                    print("xStart in start changed: ", xStart)
                    xEnd = self.highlights[xStart].xEnd
                    xStartNew = int(self.taggingTable.item(rowVal, 1).text())
                    self.highlights[xStart].highlightObj.remove() #remove old from the plot
                    del self.highlights[xStart]                   #remove old from directory
                    highlightObj = self.Axes.axvspan(xStartNew, xEnd, color = 'blue', alpha = 0.5) #add new to plot
                    self.highlights[xStartNew] = highlight("No tagName", xStartNew, xEnd, highlightObj) #add new to directory
                    self.taggingTable.clearSelection() #deselect value from table
                    self.draw_idle()#update plot
                self.inCounter = self.inCounter + 1
    
            def onCellSelect():
                index = self.taggingTable.selectedIndexes()
                if len(index) != 0:
                    rowVal = index[0].row()
                    if not (self.taggingTable.item(rowVal, 1) is None):
                        xStart = int(self.taggingTable.item(rowVal, 1).text())
                        print("row in cell select: ", rowVal)
                        print("xStart in cell select: ", xStart)
                        self.inCounter = 0
                        self.taggingTable.itemChanged.connect(lambda: xStartChanged(xStart, rowVal))              
           
            self.taggingTable.selectionModel().selectionChanged.connect(onCellSelect)
            self.draw_idle()
    
    
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    app.exec()

    row in cell select:  0
    xStart in cell select:  2
    row in start changed:  0
    xStart in start changed:  2
    row in cell select:  1
    xStart in cell select:  1
    row in start changed:  0
    xStart in start changed:  2
    Traceback (most recent call last):
      File "path", line 103, in <lambda>
        self.taggingTable.itemChanged.connect(lambda: xStartChanged(xStart, rowVal))              
      File "path", line 84, in xStartChanged
        xEnd = self.highlights[xStart].xEnd
    KeyError: 2
    zsh: abort      "path"

I have a signal that connects to a slot that I use to change an x-range span on a matplotlib plot. I am trying to update the span when a user changes the starting x value in a table that shows all the spans. However, after the first edit of the span, the proceeding edits all act as though they are editing the same span, rather than the newly selected span. When running the code:

@QtCore.pyqtSlot()
    def xStartChanged(xStart, rowVal):
        if self.inCounter == 0:
            print( "row in start changed: ", rowVal)
            print("xStart in start changed: ", xStart)
            print(type(xStart))
            tagName = self.highlights[xStart].tag
            xEnd = self.highlights[xStart].xEnd
            xStartNew = int(self.taggingTable.item(rowVal, 1).text())
            self.highlights[xStart].highlightObj.remove() #remove old from the plot
            del self.highlights[xStart]                   #remove old from directory
            highlightObj = self.Axes.axvspan(xStartNew, xEnd, color = 'blue', alpha = 0.5) #add new to plot
            
            self.highlights[xStartNew] = highlight(tagName, xStartNew, xEnd, highlightObj) #add new to directory
            self.taggingTable.clearSelection() #deselect value from table
            self.draw_idle()#update plot
        self.inCounter = self.inCounter + 1

     def onCellSelect():
            index = self.taggingTable.selectedIndexes()
            if len(index) != 0:
                rowVal = index[0].row()
                #get the starting adn ending indices so they can be edited. 
                ##deal with empty cell click
                if not (self.taggingTable.item(rowVal, 1) is None):
                    xStart = int(self.taggingTable.item(rowVal, 1).text())
                    print("row in cell select: ", rowVal)
                    print("xStart in cell select: ", xStart)
                    xEnd = int(self.taggingTable.item(rowVal, 2).text())
                    self.inCounter = 0
                    #self.taggingTable.itemChanged.connect(lambda state, item = None, xStartVal = xStart, rowValFxn = rowVal: xStartChanged(xStartVal, rowValFxn))
                    print(type(xStart))
                    self.taggingTable.itemChanged.connect(lambda item = None, xStart = xStart: xStartChanged(xStart, rowVal))
                    self.draw_idle()
                    #self.taggingTable.itemChanged.connect(xEndChanged)
                
    #self.taggingTable.cellDoubleClicked.connect(onCellSelect)
    self.taggingTable.selectionModel().selectionChanged.connect(onCellSelect)
    self.draw_idle()

I get the following output: (NOTE: I have hidden the "path" because it is work related, sorry.

row in cell select:  0
xStart in cell select:  3517
<class 'int'>
row in start changed:  0
xStart in start changed:  3517
<class 'int'>
row in cell select:  1
xStart in cell select:  2801
<class 'int'>
row in start changed:  0
xStart in start changed:  3517
<class 'int'>
Traceback (most recent call last):
  File "path", line 314, in <lambda>
    self.taggingTable.itemChanged.connect(lambda item = None, xStart = xStart: xStartChanged(xStart, rowVal))
  File "path", line 277, in xStartChanged
    tagName = self.highlights[xStart].tag
KeyError: 3517
zsh: abort      path

I understand that for some reason, the connection sends the row value and xStart value of 0 and 3517 and after the cell is changed and edited, the first slot function (onCellSelect) is reading the new cell and xStart values, but the nested signal-slot connection (xStartChanged) is still holding onto the older cell and xStart values. I'm assuming that I am calling or initializing it wrong in some way. Is there something i'm not realizing?

EDIT: minimal reproducible example.

    import sys
   
    from PyQt5.QtWidgets import *
    from PyQt5 import QtCore
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    
    from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
    from matplotlib.figure import Figure
    import matplotlib.widgets as mwidgets
    
    class Window(QMainWindow):
    
        def __init__(self, parent = None):
            super(Window, self).__init__(parent)
            self.resize(1600, 800)
            self.MyUI()
            
        def MyUI(self):
    
            canvas = Canvas(self, width=14, height=12, dpi=100)
            canvas.move(0,0)
    
    class Canvas(FigureCanvas):
        def __init__(self, parent, width = 14, height = 12, dpi = 100):
            Plot = Figure(figsize=(width, height), dpi=dpi)
            self.Axes = Plot.add_subplot(111)
            self.Axes.set_position([0.05, 0.58, 0.66, 0.55])
            self.rowCount = 0
            super().__init__(Plot)
            self.setParent(parent)
    
            
            ##add all relevant lines to plot 
            self.Axes.plot([0,1,2,3,4], [3, 4, 5, 6, 7])
            self.Axes.set_xlabel('Frame', fontsize = 10) 
            self.Axes.grid()
            self.Axes.set_aspect(1)
            Plot.canvas.draw()
    
    
            #use this object in the dictionary to hold onto all the spans. 
            class highlight:
                def __init__(self, tag, xStart, xEnd, highlightObj):
                    self.tag = tag
                    self.xStart = xStart
                    self.xEnd = xEnd
                    self.highlightObj = highlightObj
    
            self.highlights = {} #empty dictionary to store all the tags.
    
            ##define a table to hold the values postselection
            self.taggingTable = QTableWidget(self)
            self.taggingTable.setColumnCount(3)
            self.taggingTable.setRowCount(100)
            self.taggingTable.setGeometry(QRect(1005,85, 330, 310))
            self.taggingTable.setHorizontalHeaderLabels(['Behavior','Start Frame', 'End Frame'])
    
            ##highlighting adds a highlight item to the directory. 
            def onHighlight(xStart, xEnd):
                tagName = "No Tag"
                self.taggingTable.setItem(self.rowCount, 0, QTableWidgetItem(tagName))
                self.taggingTable.setItem(self.rowCount, 1, QTableWidgetItem(str(int(xStart))))
                self.taggingTable.setItem(self.rowCount, 2, QTableWidgetItem(str(int(xEnd))))
                self.rowCount = self.rowCount + 1
                highlightObj = self.Axes.axvspan(xStart, xEnd, color = 'blue', alpha = 0.5)
                self.highlights[int(xStart)] = highlight(tagName, xStart, xEnd, highlightObj)
                self.draw_idle()
                    
            self.span = mwidgets.SpanSelector(self.Axes, onHighlight, "horizontal", 
                                            interactive = True, useblit=True, props=dict(alpha=0.5, facecolor="blue"),)
            self.draw_idle()
    
            ##TODO: editing spans in table is reflected in plot --- use axvspan to track spans? and spanselector to draw them?
            ##define workflow for when a cell is selected
            def xStartChanged(xStart, rowVal):
                if self.inCounter == 0:
                    print( "row in start changed: ", rowVal)
                    print("xStart in start changed: ", xStart)
                    xEnd = self.highlights[xStart].xEnd
                    xStartNew = int(self.taggingTable.item(rowVal, 1).text())
                    self.highlights[xStart].highlightObj.remove() #remove old from the plot
                    del self.highlights[xStart]                   #remove old from directory
                    highlightObj = self.Axes.axvspan(xStartNew, xEnd, color = 'blue', alpha = 0.5) #add new to plot
                    self.highlights[xStartNew] = highlight("No tagName", xStartNew, xEnd, highlightObj) #add new to directory
                    self.taggingTable.clearSelection() #deselect value from table
                    self.draw_idle()#update plot
                self.inCounter = self.inCounter + 1
    
            def onCellSelect():
                index = self.taggingTable.selectedIndexes()
                if len(index) != 0:
                    rowVal = index[0].row()
                    if not (self.taggingTable.item(rowVal, 1) is None):
                        xStart = int(self.taggingTable.item(rowVal, 1).text())
                        print("row in cell select: ", rowVal)
                        print("xStart in cell select: ", xStart)
                        self.inCounter = 0
                        self.taggingTable.itemChanged.connect(lambda: xStartChanged(xStart, rowVal))              
           
            self.taggingTable.selectionModel().selectionChanged.connect(onCellSelect)
            self.draw_idle()
    
    
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    app.exec()

I receive the following error:

    row in cell select:  0
    xStart in cell select:  2
    row in start changed:  0
    xStart in start changed:  2
    row in cell select:  1
    xStart in cell select:  1
    row in start changed:  0
    xStart in start changed:  2
    Traceback (most recent call last):
      File "path", line 103, in <lambda>
        self.taggingTable.itemChanged.connect(lambda: xStartChanged(xStart, rowVal))              
      File "path", line 84, in xStartChanged
        xEnd = self.highlights[xStart].xEnd
    KeyError: 2
    zsh: abort      "path"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文