Как отобразить сообщение в Qlabel от внешне вызванной функции Python - PullRequest
1 голос
/ 25 марта 2020

У меня на самом деле есть 3 вопроса.

  1. У меня есть кнопка, которая вызывает внешнюю функцию (пример кода приведен ниже). когда я нажимаю кнопку Run, и функция выполняется. Я хочу отобразить сообщение от этой функции на мой Qlabel в окне. до сих пор я получаю это сообщение, когда функция полностью выполняется и возвращается к основной функции. но я хочу видеть, что пока выполняется функция. Есть ли способ исправить это?

  2. Во-вторых, My GUI переходит в режим «не отвечает» при выполнении каких-либо внешних функций. в чем может быть причина и способ ее исправить?

  3. Я хочу динамически регулировать размер всех виджетов при открытии GUI в любом другом разрешении (ScreenSize). прямо сейчас размер QTablewidget фиксирован в любом случае. Как я могу получить это? это может быть достигнуто через какие-либо настройки в QTDesigner?

enter image description here

enter image description here

Код, сгенерированный дизайнером пользовательского интерфейса:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1150, 905)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(290, 820, 161, 41))
        self.pushButton.setObjectName("pushButton")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(10, 10, 1131, 791))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(580, 820, 191, 41))
        self.label.setText("")
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Run"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Основной сценарий:

from PyQt5 import QtWidgets

from demoUI import Ui_MainWindow

from callingexternalfunction import callingexternalfunction

class DemoCode(QtWidgets.QMainWindow, Ui_MainWindow):                    
    def __init__(self):
        super(DemoCode, self).__init__()
        self.setupUi(self)

        self.pushButton.clicked.connect(self.button_clicked)

    def button_clicked(self):
        callingexternalfunction(self)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = DemoCode()    
    window.show()
    sys.exit(app.exec_())

Функция, вызывающая внешнюю функцию:

import time

def callingexternalfunction(self):
    for i in range(0,5):
        time.sleep(3)
        self.label.setText('3 Second Pause '+ str(i))

1 Ответ

1 голос
/ 25 марта 2020

Вопросы 1 и 2 связаны, поэтому я решу их вместе:

GUI зависает, потому что функция сна блокирует событие GUI l oop, поэтому логика c должна запускаться это в другой ветке. С другой стороны, GUI не может быть доступен напрямую из другого потока, так как он не является потокобезопасным, поэтому вы должны использовать сигналы.

main.py

from PyQt5 import QtCore, QtWidgets

import threading

from demoUI import Ui_MainWindow

from callingexternalfunction import callingexternalfunction


class DemoCode(QtWidgets.QMainWindow, Ui_MainWindow):
    signal = QtCore.pyqtSignal(str)

    def __init__(self):
        super(DemoCode, self).__init__()
        self.setupUi(self)

        self.pushButton.clicked.connect(self.button_clicked)
        self.signal.connect(self.label.setText)

    def button_clicked(self):
        threading.Thread(
            target=callingexternalfunction, args=(self.signal,), daemon=True
        ).start()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    window = DemoCode()
    window.show()
    sys.exit(app.exec_())

callexternalfunction.py

import time

def callingexternalfunction(signal):
    for i in range(0,5):
        time.sleep(3)
        signal.emit('3 Second Pause '+ str(i))

Для изменения размера виджетов необходимо использовать макеты ( Здесь является официальным руководством, в котором они поясняются), в этом В случае, если вы можете использовать QGridLayout плюс другие модификации:

<?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>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
    <item row="0" column="0" colspan="2">
     <widget class="QTableWidget" name="tableWidget"/>
    </item>
    <item row="1" column="0">
     <widget class="QPushButton" name="pushButton">
      <property name="minimumSize">
       <size>
        <width>160</width>
        <height>40</height>
       </size>
      </property>
      <property name="baseSize">
       <size>
        <width>0</width>
        <height>0</height>
       </size>
      </property>
      <property name="text">
       <string>Run</string>
      </property>
     </widget>
    </item>
    <item row="1" column="1">
     <widget class="QLabel" name="label">
      <property name="text">
       <string/>
      </property>
      <property name="margin">
       <number>0</number>
      </property>
      <property name="indent">
       <number>40</number>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>26</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>
...