Ответы пользователя по тегу PyQt
  • Как в потоке ожидать завершение функции, вызванной сигналом, и получить значение из этой функции?

    @bbkmzzzz
    сигнал испускается в потоке
    вызывается функция, привязанная к этому сигналу
    мне нужно в потоке дождаться, пока эта функция выполнится и получить значение из нее

    Как только сигнал испущен, он попадает в очередь сигналов, и будет обработан как только, так сразу.
    QThread - обертка над потоками, которая выполняется в QApplication, так что связывать слотом ее бессмысленно.

    Все очень сильно зависит от структуры программы

    Есть несколько путей. Из простых:
    1. moveToThread(targetThread)
    Создаем поток QThread, пустой, запускаем его. Берем класс и вызываем метод moveToThread, все слоты
    этого класса будут выполняться в потоке
    2. Очереди
    Создаем очередь (например, queue.Queue), поток непрерывно слушает очередь, при возникновении там задачи, забирает ее и выполняет.
    Задача - что угодно, главное, что-бы код знал, что с этим делать
    Ответ написан
  • Как присвоить к тексту значение из spinBox?

    @bbkmzzzz
    self.label_3.text() + str(val1 / val2 * 100)
    Ответ написан
    Комментировать
  • Почему зависают всплывающие окна, вызванные в потоке?

    @bbkmzzzz
    если использовать QThred, то зависать не будет? или проблема не в этом?

    Нельзя вызывать методы виджетов из другого потока, таков путь.
    Испускаете сигнал, ловите его в основном потоке графики, реагируете показом окна.

    но если из потока threading.Thread - то всё зависает

    В Qt есть QThread и QThreadPool + QRunnable
    Ответ написан
    5 комментариев
  • Как в python и PyQt5 делать так, что бы при работе с zmq или сокетами не происходило "блокировки" окна?

    @bbkmzzzz
    Цикл событий Qt тоже должен как-то работать)
    1 - выносить сервер в отдельный QThread
    2 - Использовать Qt
    Ответ написан
    2 комментария
  • Почему не привязываются функции на кнопки на создаваемом виджете из моего класса?

    @bbkmzzzz
    class Task:
        def __init__(self, параметры):
            super().__init__()

    От чего наследован класс? Как запускается приложение?
    clicked сигнал испускается при нажатии на кнопку. Сигналы могут испускать и принимать только объекты-наследники QObject и только в основном цикле событий. Task таковым не является.

    Либо дополняем код, либо идем читать про Qt.
    Ответ написан
    23 комментария
  • Как удалить объект, связанный с удаляемой вкладкой?

    @bbkmzzzz
    Хранить где-то сопоставления вкладки и связанных данных.
    Завести менеджера вкладок, который (и только он) будет добавлять, удалять вкладки и управлять данными на этих вкладках
    Ответ написан
  • Как удалить item из QListWidget?

    @bbkmzzzz
    А где та часть кода, которая отвечает за удаление? Как она вызывается?
    takeItem(row) - takeItem удаляет итем с виджетом из списка и возвращает его

    import sys
    # import requests
    from PyQt5 import QtCore, QtWidgets, QtGui
    from PyQt5.Qt import *
    
    # Картинка для заполнения
    IMAGE = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x04\x00\x00\x00\xb5\xfa7\xea\x00\x00\x00\x02sBIT\x08\x08U\xecF\x04\x00\x00\x00\tpHYs\x00\x00\x00v\x00\x00\x00v\x01N{&\x08\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x01\x03IDAT(S}\xd1\xb1jS\x01\x14\xc6\xf1\x1fvi\xda\xc5*\x18\x93!\t\x82\x98-\x84\xd6\xe2\xe0+\xd8\xa1\x04\xbd\x08\xc1\'s0f\x11|\x02!q\xb8\xd0\xa1\xc1L\x9dj\xbaT\xe2\x94w\xf8:\xdc\xf4\xb6\x0e\x96\xb3}\xfc\xf9\xce\x9fs\xc4\xdd(\xac\xfdq\xf2O\x16\xa1\xe1\xbd\x83p\xa1\xe9\x85\xb3p\xe0\x83\xbd-`O\xe9\xbb\x95\x85Yx\xe4\xa7s\xbf}UjT\xc0[_B\xdfq];\xf02L\xbc\xa9\x80\xa6+\x9d\x08mcc\xed\x08=+\xcfn\x1d~9\x0c\xa76\xa6\xa66N\xc3\xd0"\x82w\xce\x94\xa1e\xb3\xed\xe9\xd8h\x87\xb9\xa5\x11\xd7^\xd9\t\x85i\xed05\x8e\xd0\xb5\xe6\xaff<\x04|t\xe1\xc7\x03+",\xbc\xfe\xafdxl\xa5\x1f\xa1\xa5PhE\xe8\xb9\xf4\xa4\x02\x86\xbe\x85\x8eA\xed0\xd4\x0b\x13G\x15\xb0\xab\xf4\xd9\x95\xa5Y\x84\xb9\x85K\x93\xfa\xd4a\xdf\'\xcf\xc3RW\xd72<U\xd4\xcf\xba\x1b#kk\xa3\xfb\xd9\ru"\xad\xb2\x11\xa2\xcfy\x00\x00\x00\x00IEND\xaeB`\x82'
    
    
    class Widget(QWidget):
        def __init__(self, urls):
            super().__init__()
    
            self.grid = QGridLayout(self)
    
            for i, url in enumerate(urls):
                lbl = QLabel()
                image = QImage()
                image.loadFromData(IMAGE)
    
                if i == 0:
                    lbl.setPixmap(QPixmap(image).scaled(210, 210))
                    self.grid.addWidget(lbl, i + 1, 0, 4, 1)
                else:
                    lbl.setPixmap(QPixmap(image).scaled(70, 70))
                    self.grid.addWidget(lbl, i, 1, 1, 1)
    
    
    class ListWidget(QListWidget):
        def __init__(self, *args, **kwargs):
            super(ListWidget, self).__init__(*args, **kwargs)
            self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.setEditTriggers(self.NoEditTriggers)
            self.setFlow(self.LeftToRight)
            self.setWrapping(True)
            self.setResizeMode(self.Adjust)
            self.setSpacing(10)
            # Резиновая лента (для эффекта выбора рамки)
            self._rubberPos = None
            self._rubberBand = QRubberBand(QRubberBand.Rectangle, self)
    
        def makeItem(self, lb):
            item = QtWidgets.QListWidgetItem(self)
            item.setSizeHint(QtCore.QSize(300, 300))
            self.setItemWidget(item, lb)
    
    
    class MyWindow(QtWidgets.QWidget):
        def __init__(self):
            super().__init__()
            self.setWindowTitle('ListWidget')
            self.resize(1100, 670)
            self.show()
    
            self.listWidget = ListWidget()
    
            # кнопка
            self.push_button = QPushButton('del 0 item')
    
            box = QtWidgets.QVBoxLayout(self)
    
            # добавляем кнопку
            box.addWidget(self.push_button)
    
            box.addWidget(self.listWidget)
    
            self.urls = [
                "https://img.icons8.com/ios/452/phone.png",
                "https://img.icons8.com/ios/452/phone.png",
                "http://www.google.com/favicon.ico",
                "https://www.imgonline.com.ua/examples/random-pixels-wallpaper-big.jpg",
                "https://laguna-akul.ru/upload/003/u379/f4/61/8f68d93a.jpg",
            ]
    
            num = 5
            for i in range(num):
                art = Widget(self.urls)
                self.listWidget.makeItem(art)
    
            # связываем сигнал нажатия на кнопку с методом
            self.push_button.clicked.connect(self._on_push_button_clicked)
    
        # метод-обработчик кнопки
        def _on_push_button_clicked(self):
            # takeItem удаляет итем с виджетом из списка и возвращает его
            removed = self.listWidget.takeItem(0)
            print(removed)
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        w = MyWindow()
        sys.exit(app.exec_())
    Ответ написан
    1 комментарий
  • Pyqt5 как сделать адаптивный размер виджетов внутри окна, чтобы они изменялись вместе с размером основного окна?

    @bbkmzzzz
    Компоновщики позволят автоматически регулировать размеры своих областей и виджетов.
    Но у нас такая компоновка виджетов, которую, я полагаю, очень проблематично можно будет перенести в грид. Что-то ещё видел про св-во sizePolicy, но что-то так и не разобрался.
    - элементом компоновщика может быть другой компоновщик

    Но тут у Вас по вертикали много места используется, возможно подойдет вариант с QScrollArea, это добавит прокрутку, но вся область станет достижима

    Еще из моментов, не надо наследоваться от двух классов, можно огрести)
    class Laba2(QMainWindow, laba2.Ui_Laba2):
    выносите весь сгенеренный гуй в self.ui
    class Laba2(QMainWindow):
        """Класс лабы 2, инициализирует форму и
            заполняет её элементами
        """
        def __init__(self):
            super().__init__()
            self.ui = laba2.Ui_Laba2()
            self.ui.setupUi(self)

    таким образом, все, связанное с сгенеренными формами будет в своем пространстве
    self.map_left_pos_key = QPixmap("..\\images\\laba_2\\key_left.png") -> self.ui.map_left_pos_key = QPixmap("..\\images\\laba_2\\key_left.png")
    Ответ написан
  • Как расположить QScrollBar на другом виджете?

    @bbkmzzzz
    Создаете виджет QScrollBar, а потом QTextEdit.setVerticalScrollBar(свой скролл) или setHorizontalScrollBar

    spoiler

    import sys
    
    from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout, QTextEdit, QScrollBar
    
    
    class Main(QMainWindow):
        def __init__(self):
            super(Main, self).__init__()
            centralWidget = QWidget(self)
            self.setCentralWidget(centralWidget)
    
            # добавляем компонощик
            self.h_grid = QHBoxLayout(centralWidget)
    
            self.customScroll = QScrollBar()
    
            # добаляем QtextEdit
            self.textEdit = QTextEdit()
    
            # задаем для него скролл
            self.textEdit.setHorizontalScrollBar(self.customScroll)
    
            # убираем полосу, отведенную под скролл
            self.textEdit.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
    
            self.h_grid.addWidget(self.textEdit)
            self.h_grid.addWidget(self.customScroll)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Main()
        ex.show()
        sys.exit(app.exec_())

    5fc893430cfd4584110093.jpeg
    Ответ написан
  • Как нормально настроить потоки в коде с использованием PyQt?

    @bbkmzzzz
    В таком виде, как приведено тут вообще работать не будет, в таком виде он даже не запустится.
    ̶Q̶T̶h̶r̶e̶a̶d̶ ̶н̶е̶ ̶н̶а̶с̶л̶е̶д̶н̶и̶к̶ ̶Q̶O̶b̶j̶e̶c̶t̶ ̶и̶ ̶н̶е̶ ̶м̶о̶ж̶е̶т̶ ̶и̶с̶п̶у̶с̶к̶а̶т̶ь̶ ̶с̶и̶г̶н̶а̶л̶ы̶. -> UPD: с определенной версии (в 5.15 точно) QThread наконец-то стал наследником QObject, так что он теперь может сам испускать сигналы. Костыль из класса сигналлера более не актуален

    Из соседнего потока нельзя вызывать изменения виджетов окна, только испуская и ловя сигналы.

    Не наследуйтесь от двух классов одновременно, огребете странностей.

    На тостере есть примеры, как в простом виде компоновать Qt.

    В общем виде, через QRunnable, выглядит так:
    import sys
    import time
    
    from PySide2.QtCore import QThreadPool, QRunnable, Signal, QObject
    from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget, QHBoxLayout
    
    
    class Main(QMainWindow):
        def __init__(self):
            super(Main, self).__init__()
            centralWidget = QWidget(self)
            self.setCentralWidget(centralWidget)
    
            # добавляем компонощик
            self.h_grid = QHBoxLayout(centralWidget)
    
            self.thread = QThreadPool().globalInstance()
            # добаляем кнопки
            self.button = QPushButton('Start thread')
            self.h_grid.addWidget(self.button)
    
            self.worker = Worker()
            self.worker.finished.connect(self.__on_finish)
    
            self.button.clicked.connect(self.start_worker)
    
        def start_worker(self):
            self.thread.start(self.worker)
    
        def __on_finish(self):
            print('Воркер закончил работу')
    
    
    class WorkerSignaller(QObject):
        finished = Signal()
    
    
    class Worker(QRunnable):
        def __init__(self):
            super(Worker, self).__init__()
            self.signaller = WorkerSignaller()
            self.finished = self.signaller.finished
    
        def run(self):
            print(f'Я воркер, и я запускаюсь')
            time_to_sleep = 10
            print(f'Я воркер, и я сплю {time_to_sleep} секунд')
            time.sleep(time_to_sleep)
            print(f'Я воркер, и я поспал')
            self.finished.emit()
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Main()
        ex.show()
        sys.exit(app.exec_())
    Ответ написан
    Комментировать
  • Как отслеживать для каждой кнопки её зажатие и отпускание?

    @bbkmzzzz
    Ловить события mousePressEvent(QMouseEvent *event) и mouseReleaseEvent(QMouseEvent *event) наследника QWidget, коим и является QPushButton
    Ответ написан
    4 комментария
  • Как работает модель/представление. в PyQt5?

    @bbkmzzzz
    Офф C++ доки - Все нормально расписано, язык не должен смущать, методы\сигналы такие-же
    На вики кратко описана концепция MVC
    В двух словах:
    MVC - про разделение бизнес логики и интерфейса, представление показывает данные, контроллер реагирует и обрабатывает действия пользователя, модель оперирует данными и логикой, передает данные в представление.
    В Qt представление и контроллер совмещены в одно, контроллер находится в представлении. Представление(вьюшка) обрабатывает события ввода, контроллер шлет сигналы, модель реагирует на сигналы.

    Разберитесь с работой QTableWidget, например. Это виджет, который совмещает QTableView и QAbstractTableModel. Разберетесь, как оно работает, можно переходить непосредственно на вьюшку и модель, и тыкать их
    Ответ написан
    Комментировать
  • Как располагать виджеты сверху в QGridLayout?

    @bbkmzzzz
    Добавить QSpacerItem в самый низ
    import sys
    from PySide2.QtWidgets import QApplication, QMainWindow, QGridLayout, QPushButton, QWidget, QSpacerItem, QSizePolicy
    
    
    class Main(QMainWindow):
        def __init__(self):
            super(Main, self).__init__()
            centralWidget = QWidget(self)
            self.setCentralWidget(centralWidget)
            
            # добавляем компоновщик-сетку
            self.v_grid = QGridLayout(centralWidget)
    
            # добавляем кнопки
            for i in range(5):
                self.v_grid.addWidget(QPushButton(f"Button {i}"))
            
            # Добавляем QSpacer, политики размера нужны, так как по умолчанию они Fixed
            self.v_grid.addItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding))
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Main()
        ex.show()
        sys.exit(app.exec_())

    А вообще, потыкайте Qt Designer, он идет в поставке Qt оберток
    тут поискать для Pyside2: $PyInterpreterDirectory$\Lib\site-packages\PySide2\designer.exe
    Он даст возможность поглядеть на виджеты, и накидать простенькие формы\части форм. Как это все потом использовать можно поискать тут, на тостере
    Ответ написан
    Комментировать
  • Создание динамических кнопок python и pyqt5?

    @bbkmzzzz
    QTableView\QTableWidget, в зависимости от желания разбираться с моделями, от объема, и QTableWidgetItem для кнопки в ячейку таблицы
    Ответ написан
    Комментировать
  • PyQT5 как заставить работать ProgressBar и lcdnumber в потоке?

    @bbkmzzzz
    Доступ к виджетам возможен только из основного потока, чтобы все работало из стороннего потока шлите сигнал и подписывайтесь на него в основном потоке.
    Ответ написан
    Комментировать