Вы также можете использовать head
и tail
:
In [29]: pd.concat([df.head(1), df.tail(1)])
Out[29]:
a b
0 1 a
3 4 d
, но проблема в том, что я не могу достичь ana-> ui-> horizontalLayout_4-> addWidget (label);
blockquote>Поместите изменения своего пользовательского интерфейса в слот в вашем в главном окне и подключить сигнал потока к этому слоту, скорее всего, он будет работать. Я думаю, что только основной поток имеет доступ к пользовательскому интерфейсу в 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()
.
Прежде всего, «вы делаете это неправильно» . Обычно вы хотите создать класс, полученный из объекта QObject, и перенести этот класс на новый объект потока вместо того, чтобы получать свой класс из Qthread
. Теперь, чтобы понять специфику вашего вопроса, вы не можете для непосредственного изменения элементов ui вашего основного потока GUI из отдельного потока. Вы должны connect
a signal
от вашего 2-го потока до slot
в своем основном потоке. Вы можете передавать любые данные, которые вам нужны через это соединение с сигналом / слотом, но вы не можете напрямую модифицировать элемент ui (что, честно говоря, вы, вероятно, не хотите, если вы намерены оставить интерфейс вашего приложения отдельно от бэкэнд ). Оформить Qt-сигнал и слот документации для получения дополнительной информации
как я могу это сделать?
У вас уже есть ответы на то, что вы должны делать, но не почему, поэтому я собираюсь добавить почему.
Причина, по которой вы не изменяете элементы GUI из другого потока, состоит в том, что элементы GUI обычно не являются потокобезопасными . Это означает, что если ваш основной поток GUI и рабочий поток обновляют пользовательский интерфейс, вы не можете быть уверены в том, что произошло, когда.
Для чтения данных, как правило, это иногда может быть точным (например, проверка состояния), но обычно вы не хотите, чтобы это было случайным.
Еще один ответ был отмечен на хороших принципах дизайна - это не только ограничивает вашу логику GUI одним потоком, но и тем, стреляющие сигналы, чтобы поговорить с ним, избавляются от ваших проблем с состоянием гонки, но это также заставляет вас красиво делиться своим кодом. Презентационная логика (бит дисплея) и логика обработки данных могут быть затем отделены четко, что упрощает сохранение этих двух параметров.
На этом этапе вы можете подумать: черт возьми, этот бизнес потоков farrrrrr слишком много работы! Я просто избегу этого. Чтобы понять, почему это плохая идея, реализуйте программу копирования файлов в одном потоке с простым индикатором выполнения, сообщающим вам, насколько далеко находится копия. Запустите его в большом файле. В Windows через некоторое время приложение «пойдет белым» (или на XP, я думаю, оно станет серым) и будет «не отвечать». Это очень буквально то, что происходит.
Приложения GUI внутренне в основном работают над изменением «одной большой петли» обработки и отправки сообщений. Например, Windows измеряет время отклика на эти сообщения. Если сообщение занимает слишком много времени, чтобы получить ответ, Windows решает, что он мертв, и берет верх. Это описано в GetMessage () .
Таким образом, хотя это может показаться довольно немного работы, Signals / Slots (модель, управляемая событиями) - это, в основном, способ пойти - другой способ думать об этом заключается в том, что он полностью приемлем для вашего потоки для генерации «событий» для пользовательского интерфейса - например, обновления хода и т. д.
this
в качестве родителя. – Jens Munk 2 November 2016 в 03:58