Russian Qt Forum

Qt => Вопросы новичков => Тема начата: kip_one от Декабрь 23, 2012, 21:57



Название: eventFilter()
Отправлено: kip_one от Декабрь 23, 2012, 21:57
Постала такая небольшая проблема. Нужно что бы когда наводишь курсор на QLabel (он в фокусе), то QLabel скрывается , а QPushButton становится видимым.
 вот мои наброски:
code.h
Код:
...
struct strct{QLabel * a;
QPushButton * b;};
strct * one;
bool eventFilter(QObject *object, QEvent *event);
...

code.cpp
Код:
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
one = new strct;
one->a = new QLabel;
one->b = new QPushButton;
one->b->setVisible(false);
    installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *object, QEvent *event){
if(object == one->a)
    if (event->type() == QEvent::FocusIn){
     one->a->setVisible(false);
     one->b->setVisible(true);}

    return false;
}

Вообщем не работает.Прошу помощи.


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 23, 2012, 22:09
вместо installEventFilter(this); напиши one->a->installEventFilter(this);


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 23, 2012, 22:36
Уже пробовал такую схему, нет


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 23, 2012, 23:04
Событие возникает только один раз, когда форма становится активной


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 23, 2012, 23:07
событие hover, а не focus


Название: Re: eventFilter()
Отправлено: VPS от Декабрь 24, 2012, 00:22
Попробуйте вместо QEvent::FocusIn использовать два события: QEvent::Enter (когда указатель входит в область метки) и QEvent::Leave (указатель покидает область метки).
Должно работать...


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 24, 2012, 00:39
QEvent::Enter/Leave работает, спасибо


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 24, 2012, 01:02
Еще вопрос, если у меня массив таких структур можно ли узнать какой именно элемент вызвал событие

Код:
bool MainWindow::eventFilter(QObject *object, QEvent *event){
 
    if(object == usersList[i].bb)
    if (event->type() == QEvent::Enter){
        usersList[i].cc->setVisible(true);
        usersList[i].bb->setVisible(false);}
    if(object == usersList[i].cc)
    if(event->type() == QEvent::Leave){
        usersList[i].cc->setVisible(false);
        usersList[i].bb->setVisible(true);}


    return false;
}


Что бы вместо i был номер из массива


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 24, 2012, 02:19
сходу нельзя, только если свою функцию напишешь


Название: Re: eventFilter()
Отправлено: Firefox от Декабрь 24, 2012, 11:51
mouseMoveEvent()
и в нем написать
if Label->hasMouse()
{
}
тогда можно без эвент фильтра.


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 24, 2012, 22:07
Можно по-подробней про написание функции.
Может я хреново объяснил.
usersList[10] - массив структур (Qlabel-bb,QPushButton-cc)
Нужно что-бы eventFilter работал как-то именно с структурой которая вызвала событие.
Код:
bool MainWindow::eventFilter(QObject *object, QEvent *event){
 
    if(object == usersList[i].bb)
    if (event->type() == QEvent::Enter){
        usersList[i].cc->setVisible(true);
        usersList[i].bb->setVisible(false);}
    if(object == usersList[i].cc)
    if(event->type() == QEvent::Leave){
        usersList[i].cc->setVisible(false);
        usersList[i].bb->setVisible(true);}


    return false;
}


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 24, 2012, 23:20
перебираешь массив и сравниваешь object с каждым из полей структуры, при успехе возвращаешь текущий индекс (или можно сразу ссылку на саму структуру, чтобы лишний раз не обращаться к массиву)


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 24, 2012, 23:23
Циклом я уже пробовал. Без него никак?


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 24, 2012, 23:38
ну а как по-другому? даже если бы и был подобный метод у массива, он бы внутри тоже проходил по самому себе.


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 24, 2012, 23:41
Проблема в том что если событие возникает сильно часто, то загрузка ЦП более чем 10% из-за цикла который может быть от 0 до 3 так и от 0 до 75


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 25, 2012, 00:09
ну тогда попробуй так: для лейбла задай кнопку через buddy (потом так и будешь получать), а для кнопок создай хеш QHash<QPushButton *, QLabel *> hash, и получать лейбл будешь через hash[button]. Ну а в фильтре остаётся только проверить чем на самом деле является object. Красотой конечно решение не блещет, но должно работать быстро.


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 26, 2012, 02:53
А можно ли сделать событие event->type() == QEvent::Leave для QGridLayout?


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 26, 2012, 03:46
QGridLayout же не виджет, так что нельзя. но можно QGridLayout наложить на виджет-контейнер (обычный QWidget), и вот для этого виджета-контейнера и следить за событием. а зачем такая хитрость?


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 26, 2012, 12:45
Тут идея небольшая пришла , но вместо одной кнопки теперь нужно 4. Я их сделал и gridlayout засунул.
И этот  gridlayout один для всех QLabel . Когда происходит событие Enter я просто лабел скрываю а gridlayout добавляю.

Код:
bool MainWindow::eventFilter(QObject *object, QEvent *event){


    if(object == ui->graphicsView)checkLoc=1;
    else checkLoc=0;
    for(int i=0;i<usersInYourList;i++){
        if(active==0)
    if(object == usersOnForm[i].image)
    if (event->type() == QEvent::Enter){
         active=1;
         widgetLayout->setVisible(true);
         usersOnForm[i].image->setVisible(false);
         usersOnForm[i].image->setBuddy(widgetLayout);
         usersOnForm[i].gridLayoutOne->addWidget(widgetLayout,3,0);

    }
        if(object == widgetLayout)
         if(event->type() == QEvent::Leave){
            usersOnForm[i].image->setVisible(true);
            widgetLayout->setVisible(false);
            usersOnForm[i].gridLayoutOne->removeWidget(widgetLayout);
            active=0;
    }
}
    return false;
}

Куда тут хеш засунуть?


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 26, 2012, 21:40
в этом коде я честно говоря ничего не понимаю, даже после правильного выравнивания. и я же сказал постом выше (и даже там решение предложил), что лейаут не получает никаких событий.


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 27, 2012, 00:00
Да, в чужом коде разбираться гнилая идея, согласен) Про лейоут я понял с сделал, и события он тоже получает, не ясно как сюда применить QHash что бы избежать цикла


Название: Re: eventFilter()
Отправлено: Bepec от Декабрь 27, 2012, 09:29
Какая то непонятная (для меня) тема.

Как то непонятно, как может тормозить сравнение указатель на объект аля указатель на объект для списка меньше двухсот элементов.
Про метод indexOf QList даже не упоминали.

Хотя в конце решение с хешами верное :)

PS ТС (kip_one) не выделите ли вы время и не объясните мне, как человеку только что заглянувшему что у вас на сей момент не так и чего вы достигли? :)


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 27, 2012, 14:48
Начну пожалуй с самого начала. Нужно сделать горизонтальный список пользователей, на одного пользователя приходится 2 Qlabel(1-имя, 2-картинка.). Когда наводишь курсором на картинку - она скрывается , а 4 кнопки связные QGridLayout и помещены в QWidget появляются(одни экземпляр для всех пользователей). Я с помощью данного форума сделал: создал массив структур(QLabel name,QLabel image,QGridLayout grid,QGroupBox box) пользователей, добавил весь массив пользователей в QGraphicsScene.
eventFilter:
Когда навожу на картинку в grid добавляю widget c кнопками, а картинку скрываю. Когда widget == QEvent::Leave - в grid -> deletewidget(widget),image->setVisible(true).
Все происходит методом перебора значения объекта.
for(int i=0;i<countOfUsers;i++){
    if(object == usersOnForm.image)
countOfUsers количество элементов в массиве.Может быть как и 1 так и 100

Нужно избавиться от цикла , потому что если курсором провести по 3-5 картинкам - загрузка ЦП ~10%


Название: Re: eventFilter()
Отправлено: Bepec от Декабрь 27, 2012, 14:59
Можете выложить мини проектик? (мне просто охота посмотреть на код полностью, некоторые моменты неясны. Согласен даже на куцую куцую версию ;) )

А так - метод indexOf() в структуре QList вас чем не устраивает?  (К тому же вы вроде с хешами делали, али не доделали?)

Эммм... Ну походу у вас получается весёлая хрень аля "вызовем цикл по 100 элементов с проверкой и какими то действиями."

Хотя по моему разумению, тормозить всё равно не должно. Не тот масштаб - меньше 300 картинок и 10% загрузки.

PS если оперативно выложите, я вечером (18-19 по МСК) посмотрю.


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 27, 2012, 15:26
https://skydrive.live.com/redir?resid=EF37E6F8B7097AAC!2160


Название: Re: eventFilter()
Отправлено: Bepec от Декабрь 27, 2012, 15:39
Конечно эээ... Оригинальное форматирование.

Глянул перед уездом домой - проблемка понятна. Ориентировочно к 19.00 представлю свою версию :)

А так пока вам пища для размышлений.

У вас есть картинки для каждого пользователя (правильно). (100 пользователей = 100 картинок)
У вас есть 4 слота реакции на нажатия кнопочулочек (превосходно). (100 пользователей = 4 слота)
У вас есть на каждого пользователя свой виджет с кнопками. (100 пользователей = 400 кнопок+виджет+лейаут)

Последний пункт вас не смущает? Или у вас есть какие то задумки на этот счёт?


Название: Re: eventFilter()
Отправлено: kambala от Декабрь 27, 2012, 16:06
Цитировать
А так - метод indexOf() в структуре QList вас чем не устраивает?
Мне интересно как ты его собираешься применить в данном контексте, где в списке хранятся структуры вида лейбл-кнопка, а событие получает лишь один из виджетов (кнопка и лейбл же никак не связаны между собой)


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 27, 2012, 16:45
Bepec, вы наверно не заметили, но там 4 кнопки для всех пользователей, просто они с каждым событием они меняют владельца
Кнопки были созданы только один раз


Название: Re: eventFilter()
Отправлено: Bepec от Декабрь 27, 2012, 17:07
Ненадо на меня сразу кидаться :) Убегая с работы, я многое мог не заметить :) Приношу извинения ;)

PS счас сяду, да как возьмусь, да как соберусь.



Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 27, 2012, 17:24
Угрозы ни к чему  :)


Название: Re: eventFilter()
Отправлено: Bepec от Декабрь 27, 2012, 17:29
Я не вас пугаю, а ваш проект  ;D


Название: Re: eventFilter()
Отправлено: Bepec от Декабрь 27, 2012, 19:24
Итак новости.

1) GraphicsView при интенсивном движении(и только при нём) жрёт от 5 до 12 % цп.

Это нормально. Все кутешные примеры и другие программы жрут аналогично.

Потому разницы вообще никакой нет, это не тормоза программы, это потребность QGraphicsView. (на мой неискушённый взгляд)

2) Мой пример, без цикла, с разделением по классам. Возможно кому то такой подход не нравится :/ Практически то же, что сделали и вы, за исключением чтения из файла. Возможности для расширения есть.

https://dl.dropbox.com/u/62712483/tempFun.zip

3) Приятно поработать с QGraphicsView. Давно не занимался.


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 28, 2012, 16:44
Очень интересный пример :) Могли бы вы его исправить таким образом что кнопки появляются по нажатию на картинку?

Пока времени не было что бы посмотреть подробно код.Спасибо 


Название: Re: eventFilter()
Отправлено: Bepec от Декабрь 28, 2012, 17:55
Функцию "enterEvent ( QEvent * event )" замените на "mousePressEvent ( QMouseEvent * event )".
Это в классе эмм... SBUserFace насколько я помню.

PS перепишите по подобию под себя - навык повысите :) А SB в названии классов в своём проекте прошу не использовать :) Эт мой уникальный идентификатор считайте  ;D


Название: Re: eventFilter()
Отправлено: kip_one от Декабрь 28, 2012, 22:59
Посмотреть и правда есть на что :) Спасибо за помощь