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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Ореол вокруг виджета  (Прочитано 6699 раз)
Serr500
Гость
« : Января 17, 2014, 20:54 »

Возникла необходимость сделать виджет, вокруг которого при попадании фокуса возникает ореол. Что-нибудь типа такого, как указано на рисунке, только поровнее, естественно...  Подмигивающий В качестве виджета может быть QWidget, QFrame, QLineEdit или что-либо ещё, поэтому будем брать самую основу и считать, что работаем с QWidget. Соответственно, вопрос: "Но, чёрт возьми, Холмс!!! Как?!!". Никогда не приходилось заниматься таким делом. Подскажите хотя бы куда копать. Может, в сторону QStyle?  Непонимающий
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Января 18, 2014, 11:56 »

Создаете виджет W, у него layout в него вставляете того что обводить. Регулируете размер рамки ореола с помощью setContentsMargin. Ну и пишите paint для виджета W (не вижу необходимости связываться с QStyle)
Записан
mitrich
Гость
« Ответ #2 : Января 18, 2014, 12:23 »

Вот самое удобное, на мой взгляд, решение. Будет работать для любого потомка QWidget (и для самого QWidget).
Код
C++ (Qt)
class HaloButton: public QPushButton
{
   Q_OBJECT
 
public:
   explicit HaloButton(QWidget *parent = 0);
 
protected:
   void enterEvent(QEvent *e);
   void leaveEvent(QEvent *e);
 
private:
   QGraphicsDropShadowEffect *halo;
};
 
HaloButton::HaloButton(QWidget *parent):
   QPushButton(parent)
{
   halo = new QGraphicsDropShadowEffect(this);
   halo->setXOffset(0);
   halo->setYOffset(0);
   halo->setBlurRadius(16.0);
   halo->setColor(QColor(255, 0, 0));
   halo->setEnabled(false);
 
   setGraphicsEffect(halo);
}
 
void HaloButton::enterEvent(QEvent *e)
{
   halo->setEnabled(true);
   QWidget::enterEvent(e);
}
 
void HaloButton::leaveEvent(QEvent *e)
{
   halo->setEnabled(false);
   QWidget::leaveEvent(e);
}
 
(либо focusInEvent/focusOutEvent() вместо enterEvent/leaveEvent())
« Последнее редактирование: Января 18, 2014, 12:34 от mitrich » Записан
Serr500
Гость
« Ответ #3 : Января 18, 2014, 16:36 »

Спасибо всем за подсказки. Попробую разные варианты.  Улыбающийся
Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #4 : Января 19, 2014, 16:46 »

Как вариант установить фильтр событий, отлавливать какой виджет получил фокус, над ним рисовать прозрачный для событий виджет, задача которого рисовать ареол. что это даст, добавление функционала к существующим формам и виджетам без наследования. это как вариант.
Записан
Serr500
Гость
« Ответ #5 : Января 21, 2014, 11:52 »

Сделал ореол на основе QGraphicsDropShadowEffect. Выглядит чуть не так, как хотелось бы (угловато), но сойдёт. Если руки дойдут, позже сделаю поаккуратней. Однако возникла другая проблема. Связана она с комбо-боксами. Если точнее, то с popup-окнами (Qt::WindowFlags == Qt::Popup). Хотелось бы нарисовать ореол и вокруг них, но простыми способами не получается. Если брать frameless window, то с помощью метода, предложенного Igors это можно сделать. Но нужно убирать флаг Qt::Popup, а без него окно ведёт себя совершенно не так (например, не исчезает при активации другого приложения). Переписывать всю функциональность popup не хотелось бы. Может, есть какой-то встроенный в Qt механизм, позволяющий нарисовать собственный фрейм вокруг окна? Или нужно использовать нативные средства ОС и рисовать в неклиентской области, отлавливая сообщение WM_NCPAINT и ему подобное?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Января 21, 2014, 12:41 »

Если точнее, то с popup-окнами (Qt::WindowFlags == Qt::Popup). Хотелось бы нарисовать ореол и вокруг них, но простыми способами не получается.
С точки зрения дизайна это, мягко говоря, "небезупречно". Во всяком случае в OSX окна сами бросают тени, поэтому еще одна (или убирать системную) легко может оказаться перебором/безвкусицей.

Ну а если "вот хочется" то надо создавать прозрачное окно и в нем рисовать (недавно создавал тему "Рисование на слое").

Edit: насколько я понял, QGraphicsEffect(s) действуют только в пределах окна (если не так - поправьте)
« Последнее редактирование: Января 21, 2014, 12:43 от Igors » Записан
Serr500
Гость
« Ответ #7 : Января 21, 2014, 13:15 »

С точки зрения дизайна это, мягко говоря, "небезупречно". Во всяком случае в OSX окна сами бросают тени, поэтому еще одна (или убирать системную) легко может оказаться перебором/безвкусицей.
Согласен, что не безупречно... Но нужно сделать именно так... Ещё одну тень не надо, надо убрать к чертям системную, т.е. заменить тень на ореол. А что касается OS X, то она даже в планах не рассматривается - всё под Win.

Ну а если "вот хочется" то надо создавать прозрачное окно и в нем рисовать (недавно создавал тему "Рисование на слое").
Вероятно, так и придётся делать.

насколько я понял, QGraphicsEffect(s) действуют только в пределах окна (если не так - поправьте)
Именно так. За границы окна приложения (а может, и виджета-родителя, не проверял) эффект не распространяется.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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