Russian Qt Forum
Ноябрь 26, 2024, 18:28 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Скрыть виджет, если кликнуть не на нем  (Прочитано 5478 раз)
devnikor
Гость
« : Январь 26, 2014, 22:38 »

Здравствуйте. Необходимо написать виджет, который бы скрывался, если пользователь кликнет в какой-либо другой области. Примером может служить область с часами в Windows. Если мы на нее нажмем, то появится календарь и часы, а если потом кликнем, например, на рабочий стол, что окошко с календарем скроется.
Частично решает проблему флаг Qt::Popup, вот только нужно сначала кликнуть на виджет, а потом на любую другую область, и тогда он скроется
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Январь 26, 2014, 23:07 »

повесь фильтр событий на окно верхнего уровня (или вообще на qApp), отлавливай там клики мыши и смотри попадают ли они в твой виджет
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Bepec
Гость
« Ответ #2 : Январь 27, 2014, 09:21 »

Фокус вам поможет.
Записан
Kurles
Бывалый
*****
Offline Offline

Сообщений: 480



Просмотр профиля
« Ответ #3 : Январь 27, 2014, 10:04 »

Фокус вам поможет.
С фокусом очень много геморроя выйдет. Гораздо проще через фильтр событий.
Записан

Код
C++ (Qt)
while(!asleep()) sheep++;
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Январь 27, 2014, 10:33 »

А просто setCapture чтобы все сделать в самом окне?
Да, и кстати - popup окно фокус не меняет (и это правильно)
Записан
Bepec
Гость
« Ответ #5 : Январь 27, 2014, 10:35 »

Почему много? Одно событие - focusOut, которое принимают все наследники QWidget.
И в нём написать hide();

Вот полный псевдокод
При появлении виджета
Код:
myWidget->setFocus(Qt::MouseFocusReason);

В коде виджета
Код:
void MyWidget::focusOutEvent ( QFocusEvent * event )
{
    hide();
}

update:
Если условие только при нажатии мышки, тогда да, проще через фильтр событий сделать.
Записан
devnikor
Гость
« Ответ #6 : Январь 27, 2014, 11:29 »

Да, мне надо, чтобы только при клике мышке убиралось окно
Насчет фильтра событий, не могли бы вы привести пример или объяснить немного поподробнее? Окно верхнего уровня это QDesktopWidget?
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #7 : Январь 27, 2014, 13:06 »

пример фильтра событий (метод eventFilter) есть в документации, в нем описывается как «съедать» клавиатурные нажатия.

окно верхнего уровня — тот виджет, который у тебя является окном, на котором размещены все остальные виджеты (наследник QMainWindow например).
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
devnikor
Гость
« Ответ #8 : Январь 27, 2014, 13:08 »

Спасибо, буду разбираться
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #9 : Январь 27, 2014, 13:32 »

накидал тестовый проект: при клике по виджету лейбл исчезает, при клике в области лейбла он появляется. проверял в 4.8.5 и 5.2 на винде.
Код
C++ (Qt)
#include <QtGui>
 
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtWidgets/QtWidgets>
#endif
 
class A : public QWidget
{
public:
   A(QWidget *parent = 0) : QWidget(parent), _hidingLabel(new QLabel("hide me", this))
   {
       _hidingLabel->setFrameShape(QFrame::Box);
       adjustSize();
 
       installEventFilter(this);
   }
 
protected:
   void showEvent(QShowEvent *e)
   {
       Q_UNUSED(e);
 
       _labelRect = _hidingLabel->frameGeometry();
   }
 
   bool eventFilter(QObject *o, QEvent *e)
   {
       if (e->type() == QEvent::MouseButtonPress)
       {
           QPoint clickedPos = static_cast<QMouseEvent *>(e)->pos();
           if (!childAt(clickedPos))
           {
               if (_labelRect.contains(clickedPos))
                   _hidingLabel->show();
               else
                   _hidingLabel->hide();
               return true;
           }
       }
       return QWidget::eventFilter(o, e);
   }
 
private:
   QLabel *_hidingLabel;
   QRect _labelRect;
};
 
int main( int argc, char** argv )
{
   QApplication app(argc, argv);
 
   A a;
   a.show();
 
   return app.exec();
}
 
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Январь 27, 2014, 14:14 »

MousePressEvent не придет если кликнуто в титул или вне окон приложения. Мой вариант

Код
C++ (Qt)
#include <QtGui>
 
class MyPopup : public QWidget {
public:
MyPopup( QWidget * parent = 0 ) : QWidget(parent, Qt::Popup)
{
setAttribute(Qt::WA_ShowWithoutActivating);
}
 
void mousePressEvent( QMouseEvent * e )
{
if (!rect().contains(e->pos()))
hide();
}
};
 
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
 
QDialog dlg;
dlg.show();
 
QPointer <MyPopup> test(new MyPopup);
test->setGeometry(50, 50, 100, 100);
test->show();
test->setMouseTracking(true);
 
return app.exec();
}
Записан
devnikor
Гость
« Ответ #11 : Январь 27, 2014, 17:21 »

Спасибо, вроде разобрался Улыбающийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.12 секунд. Запросов: 23.