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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Рисование поверх дочерних виджетов  (Прочитано 8955 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Май 28, 2016, 19:11 »

Добрый день

Есть виджет, в нем layout в котором чайлд виджеты соединенные "проводами". И вот эти провода надо рисовать поверх чайлдов, иначе возникают непонятки. Делать провода тоже виджетами - дороговато и бестолково. Ладно, ознакомился здесь. Все ясно, наверное и работать будет - но ведь это все-таки неграмотно повторять и повторять рисование парента для каждого чайлда которых сотни.

Ну а как грамотно?

Спасибо
Записан
Bepec
Гость
« Ответ #1 : Май 28, 2016, 23:26 »

Мы это уже проходили. Виджет стекло, на котором вы будете рисовать линии, не заморачиваясь "а где" "а что" "а когда".
Данные об детях есть, координаты начала-конца линий есть, рисуй не хочу.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #2 : Май 29, 2016, 00:42 »

Я бы делал через QGraphicsScene.
В статье какой-то хак описан, не факт, что будет везде работать...
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Май 29, 2016, 07:15 »

Мы это уже проходили. Виджет стекло, на котором вы будете рисовать линии, не заморачиваясь "а где" "а что" "а когда".
Данные об детях есть, координаты начала-конца линий есть, рисуй не хочу.
Смотрел вчера. Точнее открыл хедер - и быстренько закрыл
Цитата: cpp
#ifndef SBGLASS_H
#define SBGLASS_H

/*
****************************************
[5/22/2013 Bepec]Специально для prog.org.ru
Часть кода взята из статьи "Qt. Накрываем виджеты стеклом" (http://www.quizful.net/post/glass-qt-component)
****************************************
*/

#include <QObject>
#include <QLabel>
#include <QMovie>
#include <QEvent>
#include <QBrush>
#include <QDebug>
#include <QGraphicsOpacityEffect>


class SBGlass : public QObject
{
   Q_OBJECT

public:
   SBGlass(QObject *parent = 0);
   ~SBGlass();
   virtual void install(QWidget* w);
   virtual void remove();

   void enableColor(const QColor& color = QColor(111, 111, 100));
   void disableColor();

   void enableOpacity(qreal opacity = 0.5);
   void disableOpacity();

   void enableInfoBlock(QMovie* movie = 0, const QString& text = QString::null);
   void disableInfoBlock();

   void enableAnimationBlock(QMovie* movie = 0);
   void disableAnimationBlock();

   void enableInfoTextBlock(const QString& text = QString::null);
   void disableInfoTextBlock();
   QLabel& getInfoTextBlock();
   void setMovie(QMovie* movie);

protected:
   bool eventFilter(QObject* object, QEvent* event);

private:
   void showInfoTextBlock(const QString& text = QString::null);
   void showAnimationBlock(QMovie* movie = 0);
   void infoBlockPositioning();

private:
   QLabel* wGlass_;
   QLabel* wAnimationContainer_;
   QLabel* wInfoTextContaiter_;
   QMovie* movie_;
   QMovie* defaultMovie_;
   QColor glassColor_;

   bool flagInfoTextBlockEnabled_;
   bool flagAnimationBlockEnabled_;
};

#endif // SBGLASS_H
Что-то явно "не то"
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Май 29, 2016, 07:20 »

Я бы делал через QGraphicsScene.
Эти классы всегда казались мне воплощением тупости (возможно я не объективен)

В статье какой-то хак описан, не факт, что будет везде работать...
Рисование "foreground" - нормальная вещь/практика, должно делаться просто и естественно, без всяких хаков.

Ладно, разберусь - отпишусь.
Записан
Bepec
Гость
« Ответ #5 : Май 29, 2016, 09:58 »

Не нравится - не пользуйтесь, однако функцию свою он выполняет.
По поводу тупости - покажите мне, непрофессионалу, как надо сделать такой класс. Мне будет очень интересно.

PS почему "не то"? Вы уж если критикуйте, то с аргументами. А то на пустозвона похожи, да и какой вы тогда профессионал, если не наставляете молодых да ранних Улыбающийся
« Последнее редактирование: Май 29, 2016, 10:26 от Bepec » Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #6 : Май 29, 2016, 11:33 »

Верес, честно говоря, по интерфейсу класса не понятно, как с его помощью можно выполнять кастомное рисование?
Там можно только показать текст и видео проиграть, но нигде нет доступа к паинтеру.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Май 29, 2016, 11:51 »

PS почему "не то"? Вы уж если критикуйте, то с аргументами.
Вот вверху Ваш хедер - какие-то QMovie, infoBlock и др. Разбираться где в этой куче "рациональное зерно" - нафиг нужно. 

..мне, непрофессионалу,
"Профессионал" - совсем не значит "крутой" (как часто думают). Насколько мне известно, Вы зарабатываете на жизнь программированием - стало быть, Вы профессионал. А вот какой: хороший или хреновый - это уже др вопрос Улыбающийся

.. если не наставляете молодых да ранних  Улыбающийся
Так это запросто (аттач)
Записан
Bepec
Гость
« Ответ #8 : Май 30, 2016, 20:07 »

Видимой мудрости в исходнике не вижу. А я надеялся Улыбающийся

И да, критика проекта "закрывает виджет и отображает текстовый блок и гифку" по теме "он не рисует поверх виджета", это ммм... это несколько несуразно, не находите? Показает язык
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #9 : Май 30, 2016, 21:33 »

И да, критика проекта "закрывает виджет и отображает текстовый блок и гифку" по теме "он не рисует поверх виджета", это ммм... это несколько несуразно, не находите? Показает язык

Это не критика скорее, а вопрос, как данное решение соответствует требованию рисования поверх виджета?

Вот смотрим публичный интерфейс:

Код:
   SBGlass(QObject *parent = 0);
   ~SBGlass();
   virtual void install(QWidget* w);
   virtual void remove();

   void enableColor(const QColor& color = QColor(111, 111, 100));
   void disableColor();

   void enableOpacity(qreal opacity = 0.5);
   void disableOpacity();

   void enableInfoBlock(QMovie* movie = 0, const QString& text = QString::null);
   void disableInfoBlock();

   void enableAnimationBlock(QMovie* movie = 0);
   void disableAnimationBlock();

   void enableInfoTextBlock(const QString& text = QString::null);
   void disableInfoTextBlock();
   QLabel& getInfoTextBlock();
   void setMovie(QMovie* movie);

ЧТО здесь должен вызвать пользователь, чтобы нарисовать несколько линий?
или хотя бы получить доступ к виджету-"закрывашке"?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Bepec
Гость
« Ответ #10 : Май 31, 2016, 08:18 »

Igors, Racheengel - будьте внимательнее пожалуйста Улыбающийся
Ни разу я не говорил о виджете, который был выложен мной на форуме. Его задача в другом - затемнять и показывать индикатор загрузки с текстом. Точка.

Виджет стекло я упоминал как концепцию, а не готовое решение. Вы уж не придумывайте того, чего нет Веселый

PS а по поводу того, что проходили - в одной из тем Igors уже задавался этим вопросом. И вот в той далекой теме с каким то названием лежит класс для рисования поверх ) с той же концепцией виджет стекло Улыбающийся
« Последнее редактирование: Май 31, 2016, 08:58 от Bepec » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Май 31, 2016, 13:04 »

PS а по поводу того, что проходили - в одной из тем Igors уже задавался этим вопросом. И вот в той далекой теме с каким то названием лежит класс для рисования поверх ) с той же концепцией виджет стекло Улыбающийся
Там речь была совсем о другом - рисовать "синхронно".

Видимой мудрости в исходнике не вижу. А я надеялся Улыбающийся
В чем же по-Вашему "мудрость"?  Улыбающийся Ну или "что Вы ожидали увидеть?"

Возвращаясь к теме: а ведь все не так уж просто как может показаться, тут есть о чем поговорить. Я реализовал простую конструкцию

Парент (здесь viewport)
  - чайлд 1 "содержимое" (то что накрываем), часто имеет много своих чайлдов
  - чайлд 2 "верхний слой" (стекло) имеет WA_TranslucentBackground

Осталоcь только обеспечить чтобы стекло покрывало все что нужно - и "voila". Ведь виджеты рисуются в нужном порядке. Но не тут-то было Улыбающийся Оказывается такое стекло можно разбить:

- в примере уберите вызов update и запустите
- тыкните 1 раз в скролл бар - левая часть стекла исчезает (Qt 5.4.2)

После неск часов изучения исходников мне так и не удалось понять почему так. Может просто буги-вуги? Ладно, залатал
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #12 : Май 31, 2016, 15:06 »

Вот работающий, правда с некоторыми хинтами, вариант
Код
C++ (Qt)
#include <QWidget>
#include <QBackingStore>
#include <QPainter>
#include <QGridLayout>
 
class GridManager : public QWidget
{
bool in_paint_ = false;
public:
GridManager( QWidget* parent = nullptr ) : QWidget( parent )
{
setLayout( new QGridLayout() );
}
void addWidget( QWidget* w, int row, int column )
{
qobject_cast< QGridLayout* >( layout() )->addWidget( w, row, column );
}
 
protected:
bool event( QEvent* e )
{
if( e->type() == QEvent::ChildAdded )
static_cast< QChildEvent* >( e )->child()->installEventFilter( this );
}
bool eventFilter( QObject* o, QEvent* e )
{
if( e->type() == QEvent::Paint )
{
if( !in_paint_ )
{
drawChild( qobject_cast< QWidget* >( o ) );
return true;
}
}
return QWidget::eventFilter( o, e );
}
void drawChild( QWidget* w )
{
w->setAttribute( Qt::WA_WState_InPaintEvent, false );
auto bs = window()->backingStore();
auto r = w->rect().translated( - w->mapFrom( w->window(), QPoint( 0, 0 ) ) );
bs->beginPaint( QRegion( r ) );
QPainter p( bs->paintDevice() );
p.translate( r.topLeft() );
in_paint_ = true;
w->render( &p );
in_paint_ = false;
drawOverChild( &p, w );
bs->endPaint();
}
virtual void drawOverChild( QPainter* p, QWidget* w )
{
p->setBrush( QColor( 0xff, 0xff, 0xff, 200 ) );
p->drawRect( w->rect() );
}
};
 

Перегрузите GridManager::drawOverChild() и уже поверх чайлда рисуйте всё что хотите.
« Последнее редактирование: Май 31, 2016, 15:09 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Июнь 01, 2016, 08:19 »

Вот работающий, правда с некоторыми хинтами, вариант
Это близко к приводимой статье, по существу эффект тот же как унаследоваться от чайлда и перекрыть его paintEvent. Предложу еще один способ
Код
C++ (Qt)
class Dummy : public QWidget {
public:
using QWidget::paintEvent;
};
 
bool eventFilter( QObject* o, QEvent* e )
{
if (e->type() == QEvent::Paint) {
Dummy * w = static_cast<Dummy*> (o);
w->paintEvent(static_cast<QPaintEvent *> (e));
QPainter painter(w);
drawOverChild(&painter, w);
return true;
}
return QWidget::eventFilter( o, e );
}
Но это решает проблему с одним чайлдом, мне же хотелось бы создать "слой" и рисовать его один раз, не заботясь сколько чего "под ним"
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #14 : Июнь 01, 2016, 10:55 »

Это близко к приводимой статье, по существу эффект тот же как унаследоваться от чайлда и перекрыть его paintEvent. Предложу еще один способ
Сей способ в отличие от моего не решает такой запрос:
 - чайлд 1 "содержимое" (то что накрываем), часто имеет много своих чайлдов

Но это решает проблему с одним чайлдом, мне же хотелось бы создать "слой" и рисовать его один раз, не заботясь сколько чего "под ним"
И придётся много заморачиваться с доставкой событий чайлдам, если они интерактивные.
« Последнее редактирование: Июнь 01, 2016, 10:59 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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