Найти - Пользователи
Полная версия: В QListWidget не появляется новых элементов
Начало » GUI » В QListWidget не появляется новых элементов
1
AlekseyPython
В Qt Designer я создал форму, на которую поместил QlistWidget для отображения хода обработки:

 from PyQt5 import QtWidgets, uic
from Database import Manager
from MyLib import Events, GUI
import Forms, General
 
class Form(QtWidgets.QWidget):
 
    def __init__(self, parent: QtWidgets.QMainWindow):
        QtWidgets.QWidget.__init__(self)
         
        ClassForm, _ = uic.loadUiType(Forms.Directory + 'CreateDatabase.ui')    
        self.ui = ClassForm()
        self.ui.setupUi(self)
        self.parent = parent
         
        #name of form
        self.setWindowTitle('Form for creating database')
        self.widget = QtWidgets.QWidget(self)
          
        layoutV = QtWidgets.QVBoxLayout()
        layoutV.addWidget(self.ui.label)
        layoutV.addWidget(self.ui.ButtonCreateDatabase)
        layoutV.addWidget(self.ui.MessageList)
         
        self.widget.setLayout(layoutV)
        self.setLayout(layoutV)
            
        self.ui.ButtonCreateDatabase.clicked.connect(self.CreateDatabase)
   
    ...
         
    def event(self, current_event: Events.EventForMessageList) -> bool:
        if current_event.type() !=  General.type_event:
            return False
        self.ui.MessageList.addItem(current_event.message)
        #alive gui
        q_app = QtWidgets.QApplication.instance()
        q_app.processEvents();
        return True

Форма отлично создается, во время хода выполнения ей прибывают события нужного типа с непустыми значениями в поле message, они без ошибок обрабатываются, но в QListWidget новых строк не появляется. Это поле всегда остается полностью пустым.

Причем такой код дает верный результат (в отладчике я вижу текст, который должен отображаться в QListWidget):
 quantity = self.ui.MessageList.count()
self.ui.MessageList.item(quantity-1).text()
self.ui.MessageList.item(quantity-2).text()

Почему?
AlekseyPython
Оказалось, что если форму изменить в размерах, то элементы появляются! Но ведь я “оживляю” форму с помощью:
 q_app = QtWidgets.QApplication.instance()
q_app.processEvents();

Неужели мое “оживление” не работает и надо создавать второй процесс и в нем запускать выполнение обработки?
vic57
попробуй QListWidget().repaint()/update()
AlekseyPython
vic57
QListWidget().repaint()/update()
Спасибо, но и то, и другое не работает: опять пока я не меняю размер окна данные не появляются.

При поиске ошибки произвел две модификации:
1. Решил уйти от QtDesigner и форму создал чисто с помощью кода.
2. Выполнение задачи запустил в отдельном потоке

 class Form(QtWidgets.QWidget):
    def __init__(self, parent):
        QtWidgets.QWidget.__init__(self)
         
        #name of form
        self.setWindowTitle('Form for creating database')
        
        self.label = QtWidgets.QLabel('Обработка создания базы данных')
        self.ButtonCreateDatabase = QtWidgets.QPushButton("Создать")
        self.MessageList = QtWidgets.QListWidget()
          
        self.layoutV = QtWidgets.QVBoxLayout()
        self.layoutV.addWidget(self.label)
        self.layoutV.addWidget(self.ButtonCreateDatabase)
        self.layoutV.addWidget(self.MessageList)
         
        self.setLayout(self.layoutV)
            
        self.ButtonCreateDatabase.clicked.connect(self.CreateDatabase)
   
    def do(self):
        for i in range(10):
            Events.message_error(str(i) + " Hop, Hey! La-la-ley!")
             
            q_app = QtWidgets.QApplication.instance()
            q_app.processEvents();
     
            time.sleep(1)
         
    def CreateDatabase(self) -> None:
        threading.Thread(target=self.do).start()
         
    def event(self, current_event: Events.EventForMessageList) -> bool:
        if current_event.type() !=  General.type_event:
            return False
          
        self.MessageList.addItem(current_event.message)
        self.ButtonCreateDatabase.setText(current_event.message)
         
        q_app = QtWidgets.QApplication.instance()
        q_app.processEvents();
         
        return True

Результат точно такой же как и раньше: список и кнопка не обновляются пока я не начинаю менять размеры окна….
vic57
если ты Qt используешь то лучше QThread
где то в примерах видел такое
https://github.com/baoboa/pyqt5/tree/master/examples/threads
ЕМНИП если ты event перехватывашь - event.assert() надо делать
http://doc.crossplatform.ru/qt/4.6.x/eventsandfilters.html
vic57
вот пример
метод QObject::event(QEvent *event) должен возвращать true на все случаи event`ов, которые были обработаны в методе, в противном случае должен вызываться метод базового класса. То есть правильнее будет делать так:

bool MainWindow::event(QEvent *event)
{
if(event->type() == QEvent::WinIdChange)
{
g_id = winId();
qDebug() << “WinIdChange”;
return true;
}
return QMainWindow::event(event);
}
AlekseyPython
vic57, спасибо, но я наконец- то нашел решение.
Для будущих поколений оставлю его здесь (основная мысль- перехватывать в виджете которому нужно отображать, а не в форме):

 class MyThread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)
        
    def run(self):
        for i in range(1, 11):
            self.sleep(1)
            
            # Передача данных из потока через событие
            Events.message_error(str(i) + " Hop, Hey! La-la-ley!")
class MyList(QtWidgets.QListWidget):
    def __init__(self, parent=None):
        QtWidgets.QListWidget.__init__(self, parent)
    def customEvent(self, current_event: Events.EventForMessageList):
        if current_event.type() != General.type_event:
            return False
        
        self.addItem(current_event.message)
                            
class Form(QtWidgets.QWidget):
    def __init__(self, parent):
        QtWidgets.QWidget.__init__(self)
         
        #name of form
        self.setWindowTitle('Form for creating database')
        
        self.label = QtWidgets.QLabel('Обработка создания базы данных')
        self.ButtonCreateDatabase = QtWidgets.QPushButton("Создать")
        self.MessageList = MyList()
          
        self.layoutV = QtWidgets.QVBoxLayout()
        self.layoutV.addWidget(self.label)
        self.layoutV.addWidget(self.ButtonCreateDatabase)
        self.layoutV.addWidget(self.MessageList)
          
        self.setLayout(self.layoutV)
            
        self.thread = MyThread()
        
        self.ButtonCreateDatabase.clicked.connect(self.on_clicked)
    def on_clicked(self):
        General.generate_type_event()
        General.event_receiver = self.MessageList
        
        self.thread.start()
vic57
а нужен ли перехват событий?
в кьюте есть сигналы/слоты
 from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel
class Window(QMainWindow):
    Signal  = pyqtSignal(str)     
    def __init__(self):
        super().__init__()
        
    def mousePressEvent(self, event):
        pos = event.pos()
        self.Signal.emit('sended from: ' + repr(pos))
    
if __name__ == '__main__':
    app = QApplication([])
    l = QLabel()
    l.resize(300,50)
    l.move(100,100)
    w = Window()
    w.Signal.connect(l.setText)
    l.show()
    w.show()
    app.exec_()
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB