Access a label from main
-
Hello everybody!
I am completely new to python and also to QT.
Below is part of my code. I would like to set the label (marked by an arrow) to the value returned by the function executed in the main class. my code returns AttributeError: type object 'MainTab' has no attribute 'label'.Could somebody please help me out on this?
Any help appreciated!
Thank you!
class App(QMainWindow): def __init__(self): super().__init__() self.setMinimumSize(800, 500) self.tab_widget = TabWidget(self) self.setCentralWidget(self.tab_widget) self.show() class TabWidget(QWidget): def __init__(self, parent): super(QWidget, self).__init__(parent) self.layout = QVBoxLayout(self) self.tabs = QTabWidget() self.tabs.addTab(MainTab(), "Main") self.tabs.resize(500, 200) # Add tabs to widget self.layout.addWidget(self.tabs) self.setLayout(self.layout) class MainTab(QDialog): def __init__(self, parent=None): super().__init__() self.originalPalette = QApplication.palette() self.mainLayout = QHBoxLayout() self.buttonLayout = QVBoxLayout() buttonMsg = QPushButton("test button") self.buttonLayout.addWidget(buttonMsg) self.mainLayout.addLayout(self.buttonLayout) self.label = QLabel(self) # <-------------------------------------------- # pixmap = QPixmap('test.jpg') # self.label.setPixmap(pixmap) self.label.setStyleSheet("border: 1px solid black;") self.label.setAlignment(Qt.AlignCenter) self.mainLayout.addWidget(self.label) self.setLayout(self.mainLayout) def main(): check_requirements(exclude=('tensorboard', 'thop')) im0 = yoloRun.run() height, width, channel = im0.shape bytesPerLine = 3 * width qImg = QImage(im0.data, width, height, bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap(qImg) MainTab.label.setPixmap(pixmap) # <--------- FROM HERE I WOULD LIKE TO PUT PIXMAP AS BACKGROUND if __name__ == '__main__': t1 = threading.Thread(target=main) t1.start() app = QApplication([]) app.setStyle('Fusion') app.setApplicationName('KiTest') ex = App() app.exec()
-
@Igor86 said in Access a label from main:
MainTab.label.setPixmap(pixmap)
How should this work? MainTab is a class, you need an instance of it to set the label.
Your main() function (strange name for a function by the way) should rather return the pixmap and not set anything. Then call this method in MainTab constructor and set the pixmap it returns in the label. -
Thank you, not sure I understood completely what you mean.
the idea was this: "main" is the main program thread that runs on its own thread, and awaits for a external trigger. the trigger starts a image aquisition that is returned by yoloRun.run() and stored into im0. this will then all be inside a whie loop to start again. the task should not end, it should always be waiting for some images...
so if my main() function is not going to return as long as the software runs, is there a workaround?
THANK YOU!
-
@jsulm said in Access a label from main:
@Igor86 said in Access a label from main:
MainTab.label.setPixmap(pixmap)
How should this work? MainTab is a class, you need an instance of it to set the label.
You do need to understand what @jsulm said! You need to understand the difference between a class and an instance in Python to achieve anything. (Google it if you don't.)
You do not create any instance of your class
MainTab
, so there is no dialog created to do anything on or show.t1 = threading.Thread(target=main) t1.start()
I have no idea what you are intending to do or why. Threading is the very last thing you should be trying to use. Also in Qt you cannot access any UI elements from anything but the main thread (where you create your
QApplication
here). I would doubt you could any of what you have to work as it is even if you sort out e.g. your dialog issue. You will not be able to do at least these lines in your thread:pixmap = QPixmap(qImg) MainTab.label.setPixmap(pixmap) # <--------- FROM HERE I WOULD LIKE TO PUT PIXMAP AS BACKGROUND
At best you could perhaps get your
QImage
in a thread; you would then need to send that as a parameter in a signal from the thread which the main UI/application thread receives in a slot and does theQPixmap
manipulation and display there. -
Thank you JonB, will google it right away and try to understand this.
I used threads because run() starts a camera aquisition, and then waits for a hardware trigger. without threads the whole app freezes until the trigger arrives. (sometimes it takes a few ms, sometimes 30 minutes.. its a external signal going to the camera not controlled by me..) the IDEA (looks like my idea is not the best.. :D ) would be that this second thread works in background and does nothing but waitig for a trigger and sending the image back. once sent back it restarts and waits for the next trigger. the base thread would do all the rest such as the UI, the TCP comunication etc..
-
@Igor86
Yes, I understand you may indeed need to use a background thread for your camera acquisition here. I just drew attention to the fact that using threads in Qt UIs is one of the hardest things to get right.You will indeed need to do some reading about "Qt and threads"; there are various approaches to designing them.
What remains true, however, is that they cannot access UI elements. That would include your dialog or label, when you get those sorted out. They can access/use
QImage
s, because those are not UI-dependent, but notQPixmap
s, which are UI-dependent. The usual technique is for a thread to emit a signal with whatever necessary as a parameter, with the UI thread reacting that by doing whatever needs to be done with it on the UI side. -
Hello! It works now! :) i replaced the Thread with QtThread and implemented the signals to pass the iamge and some values to a function that sets everything on the UI.
The only problem I am facing now, is that I cannot set a label's text. I have 2 labels, one contains a text and a float (managed to do this one by converting the float to string) and the second has a text + a str variable.
The second one is not working. the program crashes as soon as it arrives there. I tried to print str and it has the correct value in it. What am I doing wrong here?
def setImage(self, img, classname = str, score = float): height, width, channel = img.shape bytesPerLine = 3 * width qImg = QImage(img.data, width, height, bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap(qImg) self.labeledPic.setPixmap(pixmap) self.scoreText.setText("Score: " + f'{score:0.2f}') print(classname) self.modeltext.setText("Model: " + classname) <---- crash also tried: self.modeltext.setText(classname) <---- crash
-