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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: "Светодиод" из QSvgRenderer и QBrush  (Прочитано 8015 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Май 27, 2015, 17:05 »

Нужен унаследованный от QWidget "светодиод" с изменяемой формой и цветом, причем желательно с возможностью менять цвета плавно. Скачал Qled 0.6.2, посмотрел. Идея тривиальная - грузится шейп в QSvgRenderer и потом рисуется QPainter-ом. Шейпы разные, это нормально. Но для каждого цвета у них отдельный векторный рисунок, то есть никакого плавного переключения, никаких промежуточных цветов, только дискретный выбор из 7-и цветов, жестко заданных в рисунках. Соответственно 6 шейпов на 7 цветов = 48 файлов векторных картинок. И всё это засунуто в ресурсы, то есть, добавить шейпы в динамике никак. Убожество, в общем.

Первая мысль - сделать по-другому, задать по 1-ой векторной картинке на шейп, и все картинки сделать с градациями серого. А рендеринг SVG выполнять с помощью QPainter, у которого QBrush задана требуемым цветом. Соответственно, цвет можно плавно менять. Ожидаемый результат - шейп окрашивается требуемым цветом, с заданными серой картинкой яркостями. С QSvgRenderer практики у меня еще не было, поэтому вопрос к тем, кто с ним работал - это получится именно так? Просьба отвечать только тем, кто имеет опыт работы с QSvgRenderer.

Если известно, что это не будет работать, то просьба кинуть идею, как сделать, чтобы работало, но форма и градиенты задавались с помощью векторного рисунка.
Записан

2^7-1 == 127, задумайтесь...
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #1 : Май 27, 2015, 17:22 »

Как насчёт отрисовки программным способом? Я себе светодиод представляю как кружок с градиентом. В QWidget::paint написать всё...
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #2 : Май 27, 2015, 17:24 »

Я же просил отвечать по существу вопроса... Не надо уводить  в сторону оффтопиками.
Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #3 : Май 27, 2015, 21:26 »

Влоб, как хотелось, не работает. Установка цвета кисти не окрашивает картинку. Надо что-то придумывать, типа полупрозрачного цветного слоя или искать способ окрашивать сам SVG.

Никто это не делал?
Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #4 : Май 28, 2015, 17:18 »

В общем, пока сделал деревянно - пересчетом яркости цветовых компонент, и заменой каждого пиксела в QImage. Если кому понадобится - код рабочий, но выложу кусками, потому что в моём много того, что не имеет отношения к "светодиоду" (в частности, у меня на него текст накладывается).

SVG рисуются любой формы, например в бесплатном Inkscape. Важно создавать "светодиод" черно-белым. Градиенты прекрасно работают. Невидимая часть должна быть сделана прозрачной, с альфа-каналом. Файлы SVG я загрузил в ресурсы, как в Qled, но вкуснее потом сделать загрузку из внешних файлов, чтобы юзеры могли по желанию формы индикаторов менять.

Где-то в заголовочном файле класса, который наследует от QWidget (в частности, у меня он наследует от QLabel).
Код:
    QColor color;
    QImage *image;
    QSvgRenderer* svg;
Соответственно цвет надо где-то задавать таким, как хочется, годится любое допустимое значение QColor.

Где-то в конструкторе должно быть

Код:
    svg = new QSvgRenderer();
    image = 0;
Где-то в настройках, где нужно задать форму:

Код:
    svg->load( shapefilename ); // где (QString) shapefilename - имя файла с полным маршрутом в ресурсах

Отдельный метод, который надо вызывать каждый раз, когда задан новый шейп, изменен его размер или цвет. Так и эффективнее, и не будет проблемы при сборке в minGW.
Код:
void MyLED::paintLED()
{
    if( image )
        delete image;
    QImage* image = new QImage(size(), QImage::Format_ARGB32_Premultiplied);
    image->fill(0);
    QPainter p( image );
    p.setRenderHint(QPainter::Antialiasing, true);
    svg->render( &p );
    int i, j, w = image->width(), h = image->height();
    for( i = 0; i < w; i++ )
        for( j = 0; j < h; j++ )
        {
            float percent = (float)qBlue(image->pixel(i,j)) / 255; // все каналы одинаковые, но синий самый дешевый
            int r = color.red() * percent,
                g = color.green() * percent,
                b = color.blue() * percent;
            image->setPixel(i,j, qRgba(r,g,b,qAlpha(image->pixel(i,j))) );
        }
    update();
}

И код для paintEvent() этого класса
Код:
void MyLED::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.drawImage(0,0,*image);
}

Ну не забыть в деструкторе класса
Код:
    delete image;
    delete svg;
« Последнее редактирование: Май 29, 2015, 00:35 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Май 28, 2015, 17:39 »

Код:
void MyLED::paintLED()
{
    if( image )
        delete image;
    QImage* image = new QImage(size(), QImage::Format_ARGB32_Premultiplied);
    image->fill(0);
    QPainter p( image );
    p.setRenderHint(QPainter::Antialiasing, true);
    svg->render( &p );
    int i, j, w = image->width(), h = image->height();
    for( i = 0; i < w; i++ )
        for( j = 0; j < h; j++ )
        {
            float percent = (float)qBlue(image->pixel(i,j)) / 256;
            int r = color.red() * percent,
                g = color.green() * percent,
                b = color.blue() * percent;
            image->setPixel(i,j, qRgba(r,g,b,qAlpha(image->pixel(i,j))) );
        }
    update();
}
Вы бы это почистили, а то молодые засмеют
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #6 : Май 28, 2015, 17:49 »

Вы бы это почистили, а то молодые засмеют

во1ых, что там померещилось не так? во2ых, мне наплевать, в в3их, мне интересны только комментарии, в которых будут предложены другие варианты закраски
« Последнее редактирование: Май 28, 2015, 17:51 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


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


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

наверно, вот это не так:

Цитировать
image->setPixel

Для подобных манипуляций есть QImage::scanLine().

Кстати - а что плохого в предложении
Цитировать
Как насчёт отрисовки программным способом?

Собственно, я бы в первую очередь на это ориентировался. Или надо, чтобы лэды скины имели?  Непонимающий
Записан

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 не волк, в лес не уйдёт
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #8 : Май 29, 2015, 21:03 »

Цитировать
image->setPixel

Для подобных манипуляций есть QImage::scanLine().

Не принципиально. Раскраска делается только при изменениях. Размеры небольшие, обычно порядка 20х20, 30х30, поэтому разницы не будет совершенно никакой. Даже если будут одновременно 100 светодиодов меняться, что в реальности невероятно, разницу обнаружить не получится. А в paintEvent() рисуется только готовый QImage.

надо, чтобы лэды скины имели?  Непонимающий

да, надо

кстати, где-то в 90-х я рисовал "светодиоды" на экране, и вспомнил, что они больше похожи на светодиоды, когда в яркой части они светятся белым, поэтому вот такая модификация тела цикла раскраски:

Код:
                int gray = qBlue(image->pixel(i,j));
#define SPOT    180
                if( gray < SPOT )
                {
                    float percent = (float)gray / SPOT;
                    image->setPixel(i,j, qRgba( color.red() * percent,
                                                color.green() * percent,
                                                color.blue() * percent,
                                                qAlpha(image->pixel(i,j)) ));
                }
                else
                {
                    float percent = ((float)gray - SPOT) / (256 - SPOT);
                    image->setPixel(i,j, qRgba( color.red() + (255 - color.red()) * percent,
                                                color.green() + (255 - color.green()) * percent,
                                                color.blue() + (255 - color.blue()) * percent,
                                                qAlpha(image->pixel(i,j)) ));
                }

Без этого они выглядят, слишком пластиково, и не яркие. Так лучше.
« Последнее редактирование: Май 29, 2015, 21:18 от Гурман » Записан

2^7-1 == 127, задумайтесь...
kandrey
Гость
« Ответ #9 : Май 30, 2015, 01:30 »

а не получится фильтр с фрагментным шейдером использовать?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #10 : Май 30, 2015, 01:58 »

а не получится фильтр с фрагментным шейдером использовать?

код покажите, и что он даст, чтобы было видно зачем порождать сущности

и чтобы работало на любом железе, в т.ч. на любых поддерживаемых видео-картах и во всех поддерживаемых ОС, и желательно в не поддерживаемых ;-)
« Последнее редактирование: Май 30, 2015, 02:03 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


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


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

а не получится фильтр с фрагментным шейдером использовать?

ОМГ... Для светодиода то... Можно тогда уже сразу в Unity проект делать начать, чо там...
Записан

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 не волк, в лес не уйдёт
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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