2016-02-02 23 views
1

Я пытаюсь использовать QWebPage в общей библиотеке, что означает, что у меня должно быть QApplication, чтобы получить контекст графического интерфейса для его запуска. чтобы получить это на месте, однако, как только я запустил qApp->exec(), Event Loop полностью блокирует и предотвращает выполнение чего-либо другого. Это связано с тем, что общая библиотека запускается в OS X, но я еще не пытаюсь использовать другие платформы.QApplication в общих проблемах цикла событий библиотеки

Я попытался добавить QTimer, чтобы запускать каждые 100 мсек, но который никогда не вызван, я бы предположил, что блокирование цикла событий. Я добавил свой установочный код QApplication. Я бы предположил, что мне нужно либо запустить его в потоке, либо я пропустил что-то тривиальное, но я совершенно не уверен, что.

web_lib.cpp

WebLib::WebLib(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv, false); 
    connect(&m_eventTimer, SIGNAL(timeout()), this, SLOT(handleEvents())); 
    m_eventTimer.start(100); 

    a.exec(); 
} 
void WebLib::renderFile(QString file 
{ 
    ...some connection code that's boring here 
    m_page = new QWebPage; 
    m_page->mainFrame()->load(file); 
} 
void WebLib::handleEvents() 
{ 
    qApp->processEvents() 
} 

web_lib.h

class WEBLIBSHARED_EXPORT WebLib: public QObject 
{ 
    Q_OBJECT 
public: 
    WebLib(); 
    WebLib(int argc, char *argv[]); 
    void renderFile(QString fileName); 

private slots: 
    void handleEvents(); 

private: 
    QWebPage *m_page; 

    QTimer m_eventTimer; 
}; 

main.cpp

int main(int argc, char *argv[]) 
{ 
    WebLib *webLib = new webLib(argc, argv); 
    svgLib->renderFileFromName("somePath"); 

    return 0; 
} 
+0

Что такое '' 'в вашем коде? Является ли это классом с переменной 'QTimer' как переменной-членом? – Tarod

+1

Если вам нужно запустить приложение в OS X, вы не сможете переместить 'QApplication' в новый поток, насколько я знаю. Однако он мог работать и на других ОС. Вы всегда можете отменить его, запустить GUI-библиотеку с помощью 'QApplication' в основном потоке и переместить другой материал в новый поток. – thuga

+0

@Tarod: да, 'this' - это класс, содержащий таймер в качестве переменной-члена. –

ответ

1

Как только я запустил qApp->exec(), цикл событий полностью блокирует и предотвращает выполнение чего-либо другого.

Это правильно. После того, как вы закончите рендеринг, вы должны выйти из цикла событий.

Таймер бесполезен, так как вызов processEvents из неблокируемого слота, такого как handleEvents, просто заставляет цикл событий заново вводиться на короткое время без каких-либо причин.

+0

Таймер действительно казался бесполезным, поэтому я перешел от него. После того, как я перейду в 'qApp-> exec(), дальнейший код не будет выполнен, так как вы предлагаете мне выйти из цикла событий? –

+0

@NicholasSmith Неверно, что дальнейший код не будет выполнен! Это точка циклов событий: они будут обрабатывать обработчики событий по мере поступления событий, например. из-за сетевой активности. Если вам нечего делать дальше, вам даже не нужно начинать цикл событий. Если вы используете сетевые подключения, вы будете уведомлены, когда все, что вы пожелаете, сделаете, и добавьте это в 'QCoreApplication :: quit'. Обратите внимание, что вам не нужно использовать 'QCoreApplication :: exec', вы также можете создать явный цикл событий и выйти из этого, внутренне это то, что происходит. –

+0

@NicholasSmith Конечно, ваш вызов «render» блокирует доступ к сети таким образом, и это может быть не так, как вы хотите. Вы можете обрабатывать сетевые запросы только в цикле событий в другом потоке и предлагать другой API: один, когда пользователь инициирует запрос, а другой, где они вызываются после завершения сетевых запросов, и рендеринг может быть завершен. –

-1

exec должен быть запущен в протекторе. В качестве альтернативы вы можете периодически звонить QApplication::processEvents.

+0

Мне не удалось вызвать 'processEvents', но я попробую запустить' exec' в своем потоке. –

+0

Это плохой совет. Qt не поддерживает запуск основного цикла событий в любом потоке, отличном от основного потока. Случается, что он работает в Windows, но там бессмысленно, поскольку цикл событий Qt вращает собственный цикл событий. В OS X: 'QApplication :: exec' закрутит собственную runloop, так что вам не нужен другой поток. Кроме того, OS X не поддерживает операции с графическим интерфейсом, такие как создание окон и т. Д. Из потоков, отличных от основного потока, поэтому 'qApp-> exec()' не имеет смысла в других потоках. –

+0

@KubaOber, как основная нить не является нитью? – Velkan

1

Ваш цикл событий не имеет никакого отношения. Перед вызовом a.exec() необходимо выполнить запрос файла рендеринга, а не потом. Другими словами, вам необходимо внести следующие изменения:

В конструкторе WebLib: 1. Удалите вызов a.exec(). 2. Динамически выделяйте QApplication вместо того, чтобы помещать его в стек. 3. Удалите таймер, он вам не понадобится.

В web_lib.cpp: Добавить WebLib :: run(), который вызовет a.exec().

В main.cpp: После вызова renderFile() вызовите webLib-> run().

+0

Мне нужно попробовать это должным образом, однако мое тестирование показало, что 'a.exec()' необходимо было вызывать к концу конструктора, иначе он будет segfault при создании переменной QWebPage. –

+0

Не должно быть, можете ли вы предоставить дополнительную информацию об аварии? Если вы не можете обойти это, вы можете изменить renderFile, чтобы он размещал настраиваемое событие, которое затем вызывало вызов для создания и загрузки веб-страницы. –

+0

Sure: 'EXC_BAD_ACCESS (код = 1, адрес = 0x0) кадр # 0: 0x000000010003081f QtWebKitWidgets WebKit :: initializeWebKitWidgets() + 47' Если добавить вызов' .exec' в нем будет позволять инициализацию к , но затем блокирует цикл события. –