Динамическое создание виджета Python PyQt с использованием многопоточных [дубликатов]

Вы также можете использовать head и tail:

In [29]: pd.concat([df.head(1), df.tail(1)])
Out[29]:
   a  b
0  1  a
3  4  d
12
задан dtech 11 May 2013 в 21:24
поделиться

3 ответа

, но проблема в том, что я не могу достичь ana-> ui-> horizontalLayout_4-> addWidget (label);

Поместите изменения своего пользовательского интерфейса в слот в вашем в главном окне и подключить сигнал потока к этому слоту, скорее всего, он будет работать. Я думаю, что только основной поток имеет доступ к пользовательскому интерфейсу в Qt. Таким образом, если вы хотите использовать графический интерфейс, он должен быть там и может быть передан только из других потоков.

ОК, вот простой пример. Кстати, ваш сценарий действительно не требует расширения QThread - так что вам лучше не делать этого, если только вам это не нужно. Поэтому в этом примере я буду использовать обычный QThread с рабочим на основе QObject, но концепция будет такой же, если вы подклассы QThread:

Основной пользовательский интерфейс:

class MainUI : public QWidget
{
    Q_OBJECT

public:
    explicit MainUI(QWidget *parent = 0): QWidget(parent) {
        layout = new QHBoxLayout(this);
        setLayout(layout);
        QThread *thread = new QThread(this);
        GUIUpdater *updater = new GUIUpdater();
        updater->moveToThread(thread);
        connect(updater, SIGNAL(requestNewLabel(QString)), this, SLOT(createLabel(QString)));
        connect(thread, SIGNAL(destroyed()), updater, SLOT(deleteLater()));

        updater->newLabel("h:/test.png");
    }

public slots:
    void createLabel(const QString &imgSource) {
        QPixmap i1(imgSource);
        QLabel *label = new QLabel(this);
        label->setPixmap(i1);
        layout->addWidget(label);
    }

private:
    QHBoxLayout *layout;
};

... и рабочий объект:

class GUIUpdater : public QObject {
    Q_OBJECT

public:
    explicit GUIUpdater(QObject *parent = 0) : QObject(parent) {}    
    void newLabel(const QString &image) { emit requestNewLabel(image); }

signals:    
    void requestNewLabel(const QString &);
};

Рабочий объект создается и перемещается в другой поток, затем подключается к слоту, который создает метки, а затем его newLabel, который является всего лишь оберткой для испускания сигнала requestNewLabel и прохождения пути к изображению. Затем сигнал передается от рабочего объекта / потока к основному слоту пользовательского интерфейса вместе с параметром пути изображения, а новая метка добавляется в макет.

Поскольку рабочий объект создается без родителя, чтобы вы можете переместить его в другой поток, мы также подключим поток уничтоженного сигнала к рабочему слоту deleteLater().

14
ответ дан dtech 19 August 2018 в 19:49
поделиться
  • 1
    можете ли вы привести пример для подключения? Я не могу решить элементы подключения. – abby 12 May 2013 в 09:31
  • 2
    @abby - Я добавил быстрый пример того, как добиться того, что вам нужно. – dtech 12 May 2013 в 11:14
  • 3
    Я попробовал это, но вместо загрузки изображения я просто поместил несколько вычислений в newLabelText () (должен был изменить newLabel (), requestNewLabel ()), чтобы увидеть, действительно ли это устраняет общую проблему замораживания пользовательского интерфейса при использовании потоков при большом объеме фона (как предполагает автор, он хочет). И действительно, это немного замораживает (я поставил элемент управления ЖК-дисплеем и кнопку, которую я использую для подсчета и отображения результата на ЖК-дисплее, чтобы проверить, действительно ли он замерзает). Это также означает, что при загрузке очень большого изображения это может привести к блокировке пользовательского интерфейса. – rbaleksandar 25 April 2014 в 16:15
  • 4
    Я предполагаю, что ваш GUIUpdater просочился, если вы не добавите this в качестве родителя. – Jens Munk 2 November 2016 в 03:58

Прежде всего, «вы делаете это неправильно» . Обычно вы хотите создать класс, полученный из объекта QObject, и перенести этот класс на новый объект потока вместо того, чтобы получать свой класс из Qthread

. Теперь, чтобы понять специфику вашего вопроса, вы не можете для непосредственного изменения элементов ui вашего основного потока GUI из отдельного потока. Вы должны connect a signal от вашего 2-го потока до slot в своем основном потоке. Вы можете передавать любые данные, которые вам нужны через это соединение с сигналом / слотом, но вы не можете напрямую модифицировать элемент ui (что, честно говоря, вы, вероятно, не хотите, если вы намерены оставить интерфейс вашего приложения отдельно от бэкэнд ). Оформить Qt-сигнал и слот документации для получения дополнительной информации

4
ответ дан Community 19 August 2018 в 19:49
поделиться
  • 1
    есть ли способ обновить mainwindow.ui из рабочего потока? Потому что мне это действительно нужно. – abby 12 May 2013 в 09:12
  • 2
    вы должны обновить элемент ui в слоте, который был подключен к сигналу из другого потока – g19fanatic 13 May 2013 в 03:03
  • 3
    Ах, это печально известный «Ты делаешь это неправильно». Сообщение блога. Я категорически не согласен с ним. См. woboq.com/blog/qthread-you-were-not-doing-so-wrong.html – Zach Saw 26 November 2013 в 07:31
  • 4
    – Predrag Manojlovic 22 August 2018 в 21:29

как я могу это сделать?

У вас уже есть ответы на то, что вы должны делать, но не почему, поэтому я собираюсь добавить почему.

Причина, по которой вы не изменяете элементы GUI из другого потока, состоит в том, что элементы GUI обычно не являются потокобезопасными . Это означает, что если ваш основной поток GUI и рабочий поток обновляют пользовательский интерфейс, вы не можете быть уверены в том, что произошло, когда.

Для чтения данных, как правило, это иногда может быть точным (например, проверка состояния), но обычно вы не хотите, чтобы это было случайным.

Еще один ответ был отмечен на хороших принципах дизайна - это не только ограничивает вашу логику GUI одним потоком, но и тем, стреляющие сигналы, чтобы поговорить с ним, избавляются от ваших проблем с состоянием гонки, но это также заставляет вас красиво делиться своим кодом. Презентационная логика (бит дисплея) и логика обработки данных могут быть затем отделены четко, что упрощает сохранение этих двух параметров.

На этом этапе вы можете подумать: черт возьми, этот бизнес потоков farrrrrr слишком много работы! Я просто избегу этого. Чтобы понять, почему это плохая идея, реализуйте программу копирования файлов в одном потоке с простым индикатором выполнения, сообщающим вам, насколько далеко находится копия. Запустите его в большом файле. В Windows через некоторое время приложение «пойдет белым» (или на XP, я думаю, оно станет серым) и будет «не отвечать». Это очень буквально то, что происходит.

Приложения GUI внутренне в основном работают над изменением «одной большой петли» обработки и отправки сообщений. Например, Windows измеряет время отклика на эти сообщения. Если сообщение занимает слишком много времени, чтобы получить ответ, Windows решает, что он мертв, и берет верх. Это описано в GetMessage () .

Таким образом, хотя это может показаться довольно немного работы, Signals / Slots (модель, управляемая событиями) - это, в основном, способ пойти - другой способ думать об этом заключается в том, что он полностью приемлем для вашего потоки для генерации «событий» для пользовательского интерфейса - например, обновления хода и т. д.

1
ответ дан user 19 August 2018 в 19:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: