Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на 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)