1
votes

i want to create QLabels dynamically at runtime, and change the Text afterwards. I did it like that:

def __init__(self, *args, **kwargs):
    QWidget.__init__(self, *args, **kwargs)
    self.counter = 0
    self.items = self.read_hosts()
    self.layout = QGridLayout()
    for item in self.items:
        self.item = QLabel(item, self)

        self.item.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.item.setAlignment(Qt.AlignCenter)
        self.item.setStyleSheet("QLabel {background-color: green;}")
        self.layout.addWidget(self.item,self.counter, 0)
        self.counter += 1
    self.setLayout(self.layout)
    self.startWorker()
    self.show()

def change_txt(self, lb, i):
     self.item.setText("{}".format(i))

It won't work. I understand why it would change just the text of the last label. I'm doing something wrong during assignment.

How can I create all labels completely variably and subsequently change the texts?

I am using:

PyQT5 on Windows 10

Thanks!

Here is my whole code:

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import os

class Worker(QObject):
    update = pyqtSignal(str,int)
    exception = pyqtSignal(str)

    def read_hosts(self):
        #try:
            file = open("hosts.ini", "r") 
            return file.readlines() 
        #except Exception as ex:
            #self.exception.emit(str(ex))

    def check_ping(self):
        #try:
            hosts = self.read_hosts()
            while True:
                for host in hosts:
                    print(host)
                    params = " -l 1000"
                    response = os.system("ping  " + host + params)
                    print("weiter")
                    self.update.emit(host, response)

        #except Exception as ex:
            #self.exception.emit(str(ex))

class Window(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)

        self.counter = 0
        self.items = self.read_hosts()
        self.layout = QGridLayout()
        for item in self.items:
            self.item = QLabel(item, self)
            self.item.setObjectName("label" + str(self.counter))
            print("label" + str(self.counter))
            self.item.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            self.item.setAlignment(Qt.AlignCenter)
            self.item.setStyleSheet("QLabel {background-color: green;}")
            self.layout.addWidget(self.item,self.counter, 0)
            self.counter += 1
        self.setLayout(self.layout)
        self.startWorker()
        self.show()

    def startWorker(self):
        self.thread = QThread() 
        self.obj = Worker()  
        self.thread = QThread() 
        self.obj.moveToThread(self.thread)
        self.obj.update.connect(self.onUpdate)
        self.obj.exception.connect(self.onException)
        self.thread.started.connect(self.obj.check_ping)
        self.thread.start()

    def read_hosts(self):
        #try:
            file = open("hosts.ini", "r") 
            return file.readlines() 
        #except Exception as ex:
            #self.exception.emit(str(ex))

    def onException(self, msg):
        QMessageBox.warning(self, "Eine Exception im Worker wurde geworfen: ", msg)

    def onUpdate(self, lb, i):
        label = lb
        self.label0.setText("{}".format(i))


app = QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())

hosts.ini:

192.168.1.1
192.168.1.2
192.168.1.30
1
Could you explain yourself better, do you want to change all the QLabels at the same time or before what action do you want to change each QLabel?eyllanesc
First I want to create a label assigning an ObjectName from a list and then I want to change the text of the label afterwards. After creation of labels a thread will emit an signal and this method should change the right one label(text).0xPYTHONIC
i've posted my whole code above...0xPYTHONIC
sorry, i have forgot to post it. There it is...0xPYTHONIC

1 Answers

1
votes

I have improved your code in the following aspects:

  • If your layout has a column it is not necessary to use QGridLayout, just QVBoxLayout.

  • Having a read_hosts() method for each class is a waste, so I've created a unique function.

  • self.item is an attribute of the class that is continually being overwritten so it is not necessary to create them.

  • The objectName should be the name of the host, that is, the IP, since that is the information that the thread has.

  • To find the label through the objectName you can use findChild().


import sys
import os

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def read_hosts():
    file = open("hosts.ini", "r") 
    return file.readlines() 

class Worker(QObject):
    update = pyqtSignal(str, int)
    exception = pyqtSignal(str)

    def check_ping(self):
        hosts = read_hosts()
        while True:
            for host in hosts:
                params = "-l 1000"
                response = os.system("ping  {} {}".format(host, params))
                print("weiter")
                self.update.emit(host, response)

class Window(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.layout = QVBoxLayout(self)

        hosts = read_hosts()
        for host in hosts:
            label = QLabel(host)
            label.setObjectName(host)
            label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            label.setAlignment(Qt.AlignCenter)
            label.setStyleSheet("QLabel {background-color: green;}")
            self.layout.addWidget(label)
        self.startWorker()

    def startWorker(self):
        self.thread = QThread() 
        self.obj = Worker()  
        self.thread = QThread() 
        self.obj.moveToThread(self.thread)
        self.obj.update.connect(self.onUpdate)
        self.obj.exception.connect(self.onException)
        self.thread.started.connect(self.obj.check_ping)
        self.thread.start()

    def onException(self, msg):
        QMessageBox.warning(self, "Eine Exception im Worker wurde geworfen: ", msg)

    def onUpdate(self, host, value):
        label = self.findChild(QLabel, host)
        label.setText("{}".format(value))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Window()
    win.show()
    sys.exit(app.exec_())