How to resolve Qobject::connect: Cannot Queue Arguments of type 'Qvector<int>' error in Pyqt5 using threading to update Gui interface

Asked

Viewed 50 times

0

Good night,

I’m a beginner in the python area, and I’m having a hard time threading along with a Gui interface, created in QT Desegner. Talking to some friends showed me this forum, because maybe they could help me/clarify what the problem is. It turns out that I do not understand much of this area, I started a few months, and I’m trying to learn alone based on examples / videos from the internet. made the following example code:

from PyQt5 import  uic,QtWidgets
import time
import threading

def atualiza_dados():
    a = 0
    while 1:
        time.sleep(2)
        tela.label_6.setText(str(a))
        tela.tabela1.setItem(0, 0, QtWidgets.QTableWidgetItem('Valor de A: '))
        tela.tabela1.setItem(0, 1, QtWidgets.QTableWidgetItem(str(a)))
        a += 1

app=QtWidgets.QApplication([])
tela=uic.loadUi("tela_monitor.ui")
tela.tabela1.setRowCount(1)
threading.Thread(target=atualiza_dados,daemon=True).start()
tela.show()
app.exec()

The above code increments the variable "a" and adds the value within a label, and within a row that in turn is within a table. however I am using a threading to perform the infinite loop and not freeze the main window. but running the program I can update only the label value, only update the table value when I click on it. another problem is that the following messages appear in cmd when running the program:

QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)

If I leave only the label, it does not give the above errors, however when I get the error table.

I inserted two screen images also to try to illustrate better what is happening.

Could you help me solve this problem? Thank you very much.

Nesta imagem aparece a atualização somente da label

Nesta imagem aparece a atualização da tabela e da label, porem depois que cliquei na janela conforme mencionei acima.

@Edit follows the ui file code as I forgot to add it..

    <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>508</width>
    <height>252</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="styleSheet">
   <string notr="true">background-color: rgb(170, 255, 255);</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>10</y>
      <width>201</width>
      <height>61</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>18</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">color: rgb(85, 85, 255);
background-color: rgb(170, 255, 255);</string>
    </property>
    <property name="text">
     <string>Monitoramento</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>50</x>
      <y>80</y>
      <width>181</width>
      <height>51</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>18</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">background-color: rgb(170, 255, 255);</string>
    </property>
    <property name="text">
     <string>Valor de A:</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_6">
    <property name="geometry">
     <rect>
      <x>20</x>
      <y>130</y>
      <width>141</width>
      <height>111</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>46</pointsize>
     </font>
    </property>
    <property name="styleSheet">
     <string notr="true">color: rgb(85, 0, 0);
background-color: rgb(170, 255, 255);</string>
    </property>
    <property name="text">
     <string/>
    </property>
   </widget>
   <widget class="QTableWidget" name="tabela1">
    <property name="geometry">
     <rect>
      <x>240</x>
      <y>80</y>
      <width>251</width>
      <height>101</height>
     </rect>
    </property>
    <column>
     <property name="text">
      <string>Nome</string>
     </property>
    </column>
    <column>
     <property name="text">
      <string>Valor</string>
     </property>
    </column>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>508</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

1 answer

0


I don’t know exactly what the nature of the error you see, but I believe it is because of some incompatibility between the Qt and Python threading system. Ideally, when using Pyqt, you use the threading system provided by them. There are several tutorials out there showing the different shapes and modules of Pyqt that you can use to run a function on a separate thread from the interface - for example, here and here (links in English).

Below is a minimal example showing a similar interface to yours, which updates the displayed counter every 2 seconds (I tried to create something similar since I don’t have access to your file. ui):

import sys

from PyQt5 import QtWidgets as qtw, QtCore as qtc


class MyApp(qtw.QWidget):
    def __init__(self):
        super().__init__()
        
        # Contador que atualiza ao chamar self.update
        self.a = 0  # valor inicial
        
        # Layout do meu app
        layout = qtw.QGridLayout()
        self.setLayout(layout)
        
        # Label estático "Monitoramento"
        self.monitoramento_label = qtw.QLabel("Monitoramento")
        layout.addWidget(self.monitoramento_label, 0, 0, 1, 2)
        
        # Label estático "Valor de A"
        self.valor_a_label = qtw.QLabel("Valor de A")
        layout.addWidget(self.valor_a_label, 1, 0, 1, 1)
        
        # Tabela
        self.table = qtw.QTableWidget(rowCount=1, columnCount=2)
        self.table.setHorizontalHeaderLabels(["Nome", "Valor"])
        self.table.setItem(0, 0, qtw.QTableWidgetItem("Valor de A"))
        self.table.setItem(0, 1, qtw.QTableWidgetItem(str(self.a)))
        layout.addWidget(self.table, 1, 1, 2, 1)
        
        # Label dinâmico - exibe o valor de self.a
        self.a_label = qtw.QLabel(str(self.a))
        layout.addWidget(self.a_label, 2, 0, 1, 1)
        
        # Timer - responsável por chamar o método self.update
        # a cada 2000 milissegundos (2 segundos)
        self.timer = qtc.QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(2000)

    def update(self):
        """Incrementa self.a em um e atualiza a interface em seguida."""
        self.a += 1
        self.a_label.setText(str(self.a))
        self.table.setItem(0, 1, qtw.QTableWidgetItem(str(self.a)))
    

if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    gui = MyApp()
    gui.show()
    sys.exit(app.exec_())

Result (if you run the code, you will see the counter being incremented): inserir a descrição da imagem aqui

The secret here is in the object QTimer, on the lines:

self.timer = qtc.QTimer()
self.timer.timeout.connect(self.update)
self.timer.start(2000)

Here, we create the object, connect it to the method self.update and we ask him to call this method every 2000 milliseconds (2 seconds).

Note that the code I wrote involves defining a class MyApp and its methods __init__ and update - If you are not familiar with these things, I recommend studying more about object-oriented programming. It will help you a lot to understand better about Pyqt and Python in general.

Note also that I wrote the interface elements (the Labels, the table etc) directly into the code. That way, you don’t need to use Qt Designer to build the interface (this is a little personal preference, but I prefer to write all the interface code because it’s easier to locate myself when the interface starts getting more complex).

  • 1

    first iramene would like to thank you for having responded, so thank you very much. I will read the two links you left at the beginning of the topic, thank you. Really your example does exactly what I wanted, my ui file is pretty simple similar to what you did, I really didn’t understand the concept of the Myapp class and its methods init and update am not familiar with them, in case I would have to write my code within the class? as for the elements directly in the code I found very interesting the method you did. I will look for more on object oriented programming.

  • 1

    Sorry to duplicate the comment, but no more characters, I tried to pass the part of qtc.Qtimer() to my code but the window got stuck. that means it doesn’t work without creating the right class?

  • Hi Gabriel, good that my answer was helpful :) you’re right, basically the entire Pyqt library will only work within classes. Pyqt is nothing more than a "translation" from the Qt library (written in C++) to Python, and as this library functions within an object-oriented paradigm, Python code must also be written that way, with widgets represented by classes and objects. Maybe there is even some way to make the code work without using classes, but it should involve some unofficially supported gambiarra.

  • 1

    Got it, you’re right then, thank you so much for answering. I will study more. I will try to learn this concept of classes etc. thanks for the help.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.