Нужен совет (QWidget в отдельном QThread)
Хочу спросить совета по следующему вопросу
У меня есть приложение, которое работает в трее
У него должно быть меню настроек
Оно будет вызываться по нажатию на элемент контекстного меню иконки
Вот код конструктора основного класса
//заголовок окна настроек
setWindowTitle("System tray");
//таймер на 3 секунды
startTimer(3000);
QAction* pactShowHide = new QAction(tr("Settings"), this);
connect(pactShowHide, SIGNAL(triggered()),
this, SLOT(slotShowHide())
);
QAction* pactQuit = new QAction(tr("Quit"), this);
connect(pactQuit, SIGNAL(triggered()), qApp, SLOT(quit()));
m_ptrayIconMenu = new QMenu(this);
m_ptrayIconMenu->addAction(pactShowHide);
m_ptrayIconMenu->addAction(pactQuit);
m_ptrayIcon = new QSystemTrayIcon(this);
m_ptrayIcon->setContextMenu(m_ptrayIconMenu);
m_ptrayIcon->setToolTip(tr("Update Scanner"));
m_ptrayIcon->setIcon(QPixmap("img1.bmp"));
m_ptrayIcon->show();
}
Пока, как видите, я наследуюсь от QLabel, то есть, при нажатии на Settings появляется окошко с меткой
Думаю сделать так, чтобы по нажатию на Settings появлялось полноценное окно QWidget с опциями настройки
Создавал новый класс формы, наследовался от него
Всё норм, правда вызов окна настроек сильно тормозит (видимо, за счёт того, что я каждые 3 секунды выполняю определённые действия)
Очевидно, работать с окном настроек надо в отдельном потоке
Почитал в книжках про потоки, примерно понял, что к чему, но знаний пока не хватает
Насколько реально это сделать, и как бы вы решали данную проблему?
Очевидно, работать с окном настроек надо в отдельном потоке
Неа. Очевидно что всю работу нужно делать в отдельном потоке.
Да в Qt предельно просто с потоками работать: в .pro добавляем CONFIG += thread. наследуемся от QThread переопределяем run(), добавляем своих членов, в конструкторе вызываем moveToThread(this) . Для членов в конструкторе указываем parent'a this или вызываем сначала moveToThread(this) потом setParent(this). Связь с другими объектами ведём только через сигналы, слоты.
run() можно сделать двумя способами (Для твоего примера чтото делать каждых 3 секунды)1. если поток будет делать чтото всё время то run() примерно такой конструкции:
{
while(true)
{
//Чтото делаем
sleep(3);//отдыхаем 3 сек
}
}
2. если поток должен чтото делать по сигналу (в твоём примере у потока член QTimer, приконнекчен к onTimer())
{
exec();
}
И стартуем поток из приложения start()
Выход из потока - exit(int).
Ну и чтиво для досуга: http://doc.qt.nokia.com/latest/qthread.html
Вот смотри, у меня main.cpp
{
QApplication app(argc, argv);
SystemTray st;
QApplication::setQuitOnLastWindowClosed(false);
return app.exec();
}
Файл SystemTray.cpp (приведу только актуальное)
//таймер на 3 секунды
startTimer(3000);
QAction* pactShowHide = new QAction(tr("Settings"), this);
connect(pactShowHide, SIGNAL(triggered()),
this, SLOT(slotShowHide())
);
}
void SystemTray::slotShowHide() {
//setVisible(!isVisible());
//вот сюда то и нужно, как я думал, впихнуть вызов, допустим, SettingsForm в отдельном потоке
}
Вот, надеюсь, понятно описал суть происходящего
Так то действие у меня такое есть
{
//здесь выполняется событие по таймеру
}
Ты его имеешь в виду?
Событие по таймеру, то бишь
Просто верхний пост твой ток недавно заметил)
Кстати, как можно сделать работу с ГУИ в моём случае
У меня то так - как нажали на настройки, появляется окно, нажали ещё раз - оно делается невидимым, то есть появление окна определеяется лишь видимостью
Собственно, этот код:
setVisible(!isVisible());
}
Я, к сожалению, только такой вариант знаю
Смысл CONFIG += и операций (moveToThread и SetParent), не очень понял, можешь объяснить вкратце, зачем они нужны?
Я, вобщем, как попробовал
main.cpp
{
QApplication app(argc, argv);
//поток работы трея
TrayThread thread;
//запускаем
thread.start();
QApplication::setQuitOnLastWindowClosed(false);
return app.exec();
}
TrayThread.h
Q_OBJECT
private:
SystemTray st;
public:
void run();
};
TrayThread.cpp
while(true) {
//Что-то делаем
st.Run();
sleep(3);//отдыхаем 3 сек
}
}
SystemTray.h
//вот тут я что-то и делаю
}
То есть теперь ВЕСЬ трей выполняется в отдельном потоке
Я правильно понял твою идею?
К сожалению, теперь, если я захочу вызвать окно настроек
(а у меня, допустим, будет форма
{
Q_OBJECT
public:
explicit Menu(QWidget *parent = 0);
~Menu();
private:
Ui::Menu *ui;
};
)
и сам трей будет унаследован от этой формы
То получится, что и ГУИ тоже будет вызываться в том же потоке, что и действие на run (потому что поток повешен на работу ВСЕГО Systemtray, как я понимаю)
Вот ты мне можешь подсказать, как бы сделать так, чтобы форма вызывалась как-то вне потока трея?
Надеюсь, я понятно выражаюсь)))
Хотел спросить, если ты знаешь, вот moveToThread - перенаправляет весь цикл обработки событий объекта в отдельный поток?
То есть...Допустим, у меня у SystemTray есть тот же метод Run, и я, допустим, напишу ещё 10 методов (Run1, Run2, ..., Run10)
и если вызову moveThThread и SetParent, то эти методы Run будут выполняться в отдельном потоке?
Я правильно понял?
У меня событие вызова ГУИ -
setVisible(!isVisible());
}
Если я все события в ОДИН поток перенаправлю - у меня снова окажется так, что и Run, и вызов ГУИ будут в одном потоке, и опять будут тормоза
ВСЕ события нельзя в 1 поток перенаправлять...
А можно только определённое событие в поток направить?
Нужно из класса трея вообще всю работу вынести в поток, а трей пусть только за ГУИ отвечает, и тогда не будет проблем!
Нужно из класса трея вообще всю работу вынести в поток, а трей пусть только за ГУИ отвечает, и тогда не будет проблем!
5+
Пример QThread: [ATTACH]5296[/ATTACH]
Статейка (правда ещё по Qt3 но общую инфу почерпнуть можна)