Версия для печати темы
Форум на CrossPlatform.RU _ Qt GUI _ Всплывающие окна
Автор: breeve 28.2.2010, 15:00
Пытаюсь сделать всплывающее окно как в exail'е справа в углу:
http://img638.imageshack.us/i/82700588.png/
Оно появляется на секунд 10 и исчезает. Если наводишь на него то оно становится прозрачным. Если кликаешь по нему, то кликается на окошко позади этого. Т.е. оно на вид прозрачное и по сути тоже является таковым..
Как такое сделать?
Пытался сделать класс Всплывающее окошко. наследовал от виджета либо от диалога, с флагом popup. Хотел сделать его с закругленными углами, а оказалось что через style sheet нельзя редактировать внешний вид Qwidget или Qdialog'а. Только если background.
Потом пытался сделать через label. Но там тоже засада... Окошко появляется захватывает фокус и все..)) Я ничего не могу сделать. Куда мышкой не нажимаю ничего не происходит.. Ни клава не работает..
Может можно как-то попроще это все сделать? Кто что посоветует?
Автор: Litkevich Yuriy 28.2.2010, 15:17
offtop: breeve, скажи полное название версии ОСьки на скрине, пожалуйста.
Автор: breeve 28.2.2010, 15:19
Ubuntu 9.10 - Karmic Koala..
Автор: Litkevich Yuriy 28.2.2010, 15:21
Цитата(breeve @ 28.2.2010, 18:00)

Т.е. оно на вид прозрачное и по сути тоже является таковым..
См. http://www.prog.org.ru/index.php?topic=7303
Автор: Rocky 28.2.2010, 19:59
Цитата(breeve @ 28.2.2010, 15:19)

Ubuntu 9.10 - Karmic Koala..
ну да, это видно по иконке наверху слева ) А графическая оболочка гном?
Автор: DEADHUNT 28.2.2010, 20:24
Цитата(Rocky @ 28.2.2010, 19:59)

А графическая оболочка гном?
GNOME
Автор: SABROG 28.2.2010, 21:23
Цитата(Litkevich Yuriy @ 28.2.2010, 15:21)

Цитата(breeve @ 28.2.2010, 18:00)

Т.е. оно на вид прозрачное и по сути тоже является таковым..
См. http://www.prog.org.ru/index.php?topic=7303
Как-то слишком просто. Может это решение только для отношения QWidget->QWidget, а окошки операционной системы оно не затрагивает? Просто когда сам искал нашел лишь 2 решения:
- делать дырку через setMask под курсором мыши размером 1x1
- рисовать на контекст рабочего стола напрямую средствами ОС
Первый вариант плох тем, что нижнему окну постоянно приходят события Hover, LeaveHover и оно себя забавно ведет при таком раскладе, если пытается какой нибудь виджет подсвечивать. А второй вариант плох тем, что изображение быстро затирается при обновлении рабочего стола, поэтому нужно постоянно перерисовывать. И вроде как это приводит к морганию картинки (flickering).
---
Всё, я понял, не внимательно прочитал первый пост SASA. У него 2 Qt'шных виджета. Тут ничего общего с окнами, которые пытаются делать люди на WINAPI.
Автор: breeve 28.2.2010, 21:43
У меня вот такой вопрос сделал так чтобы когда наводишь на него становиться прозрачным..
Делал так, конструктор:
...
setMouseTracking(true);
...
Далее moveMouseEvent:
void Popup::mouseMoveEvent(QMouseEvent *event)
{
if(event->type() == QEvent::MouseMove)
{
this->setWindowOpacity(0.5);
}
}
А как сделать чтобы если мышь не находиться на виджете то сделать обратно полноцветный? Единственная догадка это считать положение мыши если не входит в QRect(размер виджета), то делать нормальным.
Автор: Rocky 28.2.2010, 22:03
enterEvent
leaveEvent
?
Автор: breeve 28.2.2010, 22:19
Цитата(Rocky @ 28.2.2010, 22:03)

enterEvent
leaveEvent
?
Спасибо.. Сделал вот так:
void Popup::mouseMoveEvent(QMouseEvent *event)
{
if(event->type() == QEvent::MouseMove)
{
this->setWindowOpacity(0.5);
}
}
void Popup::leaveEvent(QEvent *event)
{
if(event->type() == QEvent::Leave)
{
this->setWindowOpacity(1.0);
}
}
Еще вопрос. Задумывается приложение которое всегда сидит в трее. у него не должно быть основного окна. А у меня появляется пустое окно. Пытаюсь его скрыть а оно все равно не пропадает. Не могу понять как это сделать..
Автор: SABROG 28.2.2010, 22:44
Цитата(breeve @ 28.2.2010, 22:19)

А у меня появляется пустое окно.
Выражайтесь яснее. Речь ведь идет о панели задач, где появляется лишний пустой прямоугольник.
Автор: breeve 28.2.2010, 22:49
Цитата(SABROG @ 28.2.2010, 22:44)

Выражайтесь яснее. Речь ведь идет о панели задач, где появляется лишний пустой прямоугольник.
Запускаю приложение. Появляется здоровое пустое окно, как если бы запустить пустой проект..
Вот мой конструктор:
MyCitation::MyCitation(QWidget *parent)
: QWidget(parent)
{
this->hide(); // пытался скрыть окно
createActions();
createTrayIcon();
trayIcon->show();
}
Ну и помимо этого появляется иконка в трее все как положено..
Автор: SABROG 28.2.2010, 22:53
Не вызывай show() в main.cpp. Твой hide() выполняется в конструкторе, еще до того как ты вызовешь show() или a.exec().
Автор: breeve 1.3.2010, 19:43
Вопрос. Вот есть у меня QMenu в котором QAction - show(). Нажимаешь на show появляется не модальное диалоговое окно. Нажимаешь повторно и появляется такое же в точности поверху, и т.д. Как сделать так чтобы ограничить кол-во, чтобы как открылось первое окошко второе открыться не могло?
Автор: Litkevich Yuriy 1.3.2010, 20:03
Цитата(breeve @ 1.3.2010, 22:43)

Как сделать так чтобы ограничить кол-во, чтобы как открылось первое окошко второе открыться не могло?
можно сделать модальным, можно флажёк завести и в слоте проверять, есть уже окно или нет
Автор: breeve 1.3.2010, 20:27
Цитата(Litkevich Yuriy @ 1.3.2010, 20:03)

можно сделать модальным, можно флажёк завести и в слоте проверять, есть уже окно или нет
Модальным никак нельзя сделать.. Необходимо чтобы было не модальным. А что за шлажок?
Автор: Litkevich Yuriy 1.3.2010, 20:55
Цитата(breeve @ 1.3.2010, 23:27)

А что за шлажок?
в вести булевую переменную, и в слоте, где обрабатывается действие, проверять её, если ИСТИНА, то найти диалог и вывести его на первый план, если ЛОЖНО, то создать и показать.
На закрытие окна (acept/reject) предусмотреть слот, который будет сбрасывать флажок
Автор: BRE 1.3.2010, 21:02
Цитата(Litkevich Yuriy @ 1.3.2010, 20:55)

проверять её, если ИСТИНА, то найти диалог и вывести его на первый план, если ЛОЖНО, то создать и показать.
Наверное лучше сразу искать и выводить, а если не нашли - значит диалога нет и нужно его создать.
Тогда и флажки не понадобятся...
Цитата(Litkevich Yuriy @ 1.3.2010, 20:55)

На закрытие окна (acept/reject) предусмотреть слот, который будет сбрасывать флажок
Автор: breeve 1.3.2010, 21:17
Цитата(BRE @ 1.3.2010, 21:02)

Наверное лучше сразу искать и выводить, а если не нашли - значит диалога нет и нужно его создать.
Про флажки это достаточно просто и неинтересно я тоже над этим думал.. А вот насчет найти диалог.. Как это? Глупый вопрос конечно..
оффтоп = "тут надо создать раздел для новичков. Что-то вроде вы новичок - вам сюда.. Как раз для меня))"
Автор: BRE 1.3.2010, 22:08
Цитата(breeve @ 1.3.2010, 21:17)

А вот насчет найти диалог.. Как это? Глупый вопрос конечно..
А диалог это обычный виджет.
Если у него установлен parent, то можно воспользоваться функцией:
QList<T> QObject::findChildren ( const QString & name = QString() ) const
Если это диалоги верхнего уровня, то:
QWidgetList QApplication::topLevelWidgets () [static]
Автор: Litkevich Yuriy 1.3.2010, 22:34
Цитата(BRE @ 2.3.2010, 1:08)

QList<T> QObject::findChildren ( const QString & name = QString() ) const
можно сократить расходы на поиск:
QList<QDialog *> dialogs = this->findChildren<QDialog *>();Т.е. искать сразу нужный класс. Получается быстрее
Автор: SABROG 1.3.2010, 23:34
Проблема может только появится, если диалогов может быть несколько и они скрыты например. Зато если задать уникальное имя объекту, то промахов быть не должно:
T QObject::findChild ( const QString & name = QString() ) const
Но я не пойму как мы вообще до такого докатились? Диалоги сам по себе редко когда создаются, а это значит, что в большинстве случаев у нас есть указатель на него, который можно поместить в private секцию класса. А проверка делается легко QWidget::isVisible().
Автор: BRE 1.3.2010, 23:34
Цитата(Litkevich Yuriy @ 1.3.2010, 22:34)

можно сократить расходы на поиск:
QList<QDialog *> dialogs = this->findChildren<QDialog *>();
Т.е. искать сразу нужный класс. Получается быстрее
Ну так я про это же.
Указание имени так же повысит скорость:
QList<QDialog *> dialogs = this->findChildren<QDialog *>( "NameDialog" );QList<MainDialog *> dialogs = this->findChildren<MainDialog *>();QList<MainDialog *> dialogs = this->findChildren<MainDialog *>( "MainDialog" );
Автор: Litkevich Yuriy 2.3.2010, 0:21
Цитата(SABROG @ 2.3.2010, 2:34)

Но я не пойму как мы вообще до такого докатились?
Автор: refixs 20.3.2010, 22:47
Доброго времени суток.
Есть всплывающие окно, нужно его закрыть по правому клику мыши, при этом не активируя приложения.
Сделал так:
void NotifyWindow::mousePressEvent(QMouseEvent *event) {
if(event->button() == Qt::RightButton) {
event->ignore(); // тут пробовал по всякому
showTimer.stop();
hide();
} else if(event->button() == Qt::LeftButton) {
event->accept();
showTimer.stop();
hide();
}
}
Идея в том чтоб левым щелчком активировать основное окно, а правым убирать всплывающее не изменяя текущего активного окна. Пробовал с event->ignore(); пробовал играться с атрибутами WA_NoMousePropagation и WA_NoMouseReplay. Что-то ничего не получается.
Как не пробовал после щелчка мышью на всплывающем окне активным становится всплывающее, а когда оно закрывается активируется основное окно приложения.
Автор: Litkevich Yuriy 21.3.2010, 0:14
refixs,
Цитата(refixs @ 21.3.2010, 1:47)

а правым убирать всплывающее не изменяя текущего активного окна.
можно в основном окне поставить фильтр событий на всплывающее. Если в обработчике фильтра событие не игнорировать, т.е. функция
bool MyWindow::eventFilter ( QObject * watched, QEvent * event ) [virtual]
вернёт
true то, событие не дойдёт до всплывающего окна, следовательно оно не получит фокус ввода (я так думаю).
Автор: refixs 21.3.2010, 2:19
Что-то у меня до eventFilter вообще ничего не доходит не в основном окне не в NotifyWindow.
ЗЫ. С 6000ым сообщением 
Еще такой момент, всплывающее сообщение подкрепляется периодическими вызовами activateWindow у основного окна. activateWindow вызывается раз в 1 секунду заставляя основное окошко мигать оранжевым на панели задач. В итоге получается как-то так:
- Появляется всплывающее окно
- Щелкаем по нему, оно получает фокус ввода
- Срабатывает activateWindow, фокус ввода получает MainWindow
Автор: Litkevich Yuriy 21.3.2010, 2:20
Цитата(refixs @ 21.3.2010, 5:12)

Что-то у меня до eventFilter
покажи как настраиваешь перехват событий
Автор: refixs 21.3.2010, 2:30
Точка остановки стоит в самом начале метода. Запускаю в режиме отладки (в QtCreator) и не останавливается ни при каких обстоятельствах.
Наверно все таки вся загвоздка в этом activateWindow, если без него то окна нормально исчезают.
void NotifyWindow::mousePressEvent(QMouseEvent *event) {
event->accept();
hide();
if(event->button() == Qt::LeftButton) {
MainWindow::get()->activateWindow();
}
}
Если убрать "мигание" на панели задач, то вот так работает. А мигание я наверно сделаю при условии что всплывающие окна скрыты.
Автор: Litkevich Yuriy 21.3.2010, 2:49
Цитата(refixs @ 21.3.2010, 5:19)

Что-то у меня до eventFilter вообще ничего не доходит
и тот код, что ты привел, как бы не согласуются.
Ты понимаешь что есть такие вещи как
Фильтры событий?
(eventFilter, installEventFilter)
Автор: refixs 21.3.2010, 3:20
Там два сообщения, отдельно добавить не получилось. В первом я сказал, что eventFilter не срабатывает, отладчик не останавливается в начале функции. Во втором сообщении я рассказал о том как решил решить свою проблему.
Вот один из вариантов использования eventFilter:
bool NotifyWindow::eventFilter(QObject *obj, QEvent *event) {
if(event->type() == QEvent::MouseButtonPress) {
return true;
} else {
QWidget::eventFilter(obj, event);
}
}
но какая разница какой код если отладчик не останавливается в начале функции?
Автор: Litkevich Yuriy 21.3.2010, 3:38
NotifyWindow - это всплывающее окно?
Цитата(refixs @ 21.3.2010, 6:20)

но какая разница какой код если отладчик не останавливается в начале функции?
не знаю ничего про отладчик, у меня один отладчик:
qDebug() << "Название функции"
Автор: refixs 21.3.2010, 12:02
Цитата(Litkevich Yuriy @ 21.3.2010, 3:38)

NotifyWindow - это всплывающее окно?
Да, а MainWindow это основное. Фильтр я пробовал и туда и туда ставить.
Цитата(Litkevich Yuriy @ 21.3.2010, 3:38)

не знаю ничего про отладчик, у меня один отладчик:
qDebug() << "Название функции"
bool NotifyWindow::eventFilter(QObject *obj, QEvent *event) {
qDebug() << "NotifyWindow::eventFilter";
return QWidget::eventFilter(obj, event);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
qDebug() << "MainWindow::eventFilter";
return QMainWindow::eventFilter(obj, event);
}
Вывод приложения:Lowest section in C:\WINDOWS\system32\xpsp2res.dll is .rsrc at 00011000
Добавил еще в конструкторы на всякий случай (чтоб проверить или qDebug() вообще срабатывает), получил такой вот вывод:
Цитата
MainWindow::MainWindow
Lowest section in C:\WINDOWS\system32\xpsp2res.dll is .rsrc at 00011000
NotifyWindow::NotifyWindow
NotifyWindow::NotifyWindow
Автор: Litkevich Yuriy 21.3.2010, 12:26
Цитата(refixs @ 21.3.2010, 15:02)

Да, а MainWindow это основное. Фильтр я пробовал и туда и туда ставить.
отсюда вывод - ты не понимаешь, что такое "фильтр событий", К стати говоря я так и не увидел кода, который устанавливает фильтр событий.
Ты должен в MainWindow установить фильтр событий на интересующий тебя экземпляр класса NotifyWindow
Читай асистент
bool QObject::eventFilter ( QObject * watched, QEvent * event ) [virtual]там очень простой и понятный пример
Автор: refixs 22.3.2010, 3:04
Да, я понял свою ошибку. Я не сделал привязку фильтра через installEventFilter. Отпишусь как вернусь к задаче. Пока меня устраивает решение описанное выше.
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)