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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Рисование карандаша, прерывистые линии  (Прочитано 12691 раз)
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« : Ноябрь 20, 2012, 18:43 »

Нужно в программе, дать пользователю возможность рисовать "карандашем" ну к примеру как в pain или photoshop . На первый взгляд все выглядет просто, пользователь зажал кнопку, дергает мышкой, а мы получаем координаты и соединяем их линией. Все клево, за счет одного переодичность прихода координат, если у пользователя паркинсон, то мышь дергается очень быстро и координаты приходят реже, получаются ломанные линии. Под виндой еще куда не шло, но под маком сильно заметно. Собственно вопрос, как можно либо увеличить кол-во координат, либо как то сгладить линии. Пример того что получается в аттаче
Записан
Bepec
Гость
« Ответ #1 : Ноябрь 20, 2012, 18:55 »

Кхм.

Проще выражаясь - линия получается ломанной вместо плавной? Или я не допонял вас.
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #2 : Ноябрь 20, 2012, 19:31 »

Все верно понял. И собственно она такой получается из за того что mouseMoveEvent() достаточно редко приходит.
Записан
vregess
Гость
« Ответ #3 : Ноябрь 20, 2012, 19:53 »

А что если использовать таймер?
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #4 : Ноябрь 20, 2012, 19:55 »

Не думал об этом, но на первый взгляд кажется костылем Улыбающийся хотя по идее должно сработать, может есть еще какие то варианты ?
Записан
Bepec
Гость
« Ответ #5 : Ноябрь 20, 2012, 20:06 »

Я согласен с ck.

Таймер, QCursor::pos() и количество точек у тебя вырастет в разы. Причём, насколько я пробовал, это совсем не грузит систему и программу Улыбающийся
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #6 : Ноябрь 20, 2012, 20:10 »

Я за ооп беспокоюсь ))) Просто в софте есть несколько инструментов и все принимают координаты именно через mouseMoveEvent наследуясь при этом от одного родителя, а если карандаш будет через таймер работать, это несколько поломает картину. Ну да ладно, оставлю таймер на крайний случай, подумаю пока как еще можно сделать. Где то слышал что можно попробовать рисовать не линию ,а кривую базье, мол это должно "сгладить углы", но пока не представляю как это можно сделать.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Ноябрь 20, 2012, 20:20 »

Где то слышал что можно попробовать рисовать не линию ,а кривую базье, мол это должно "сгладить углы", но пока не представляю как это можно сделать.
Ну только "Безье" Улыбающийся Этот вариант не равен "карандашу" (в его бытовом понимании). Хотя с др стороны - толку с того карандаша - кот наплакал. Вот был бы планшет или др устройство - тогда да, а просто с мышей доводит юзверя до нервного срыва  Улыбающийся
Записан
V1KT0P
Гость
« Ответ #8 : Ноябрь 20, 2012, 21:28 »

Нужно в программе, дать пользователю возможность рисовать "карандашем" ну к примеру как в pain или photoshop . На первый взгляд все выглядет просто, пользователь зажал кнопку, дергает мышкой, а мы получаем координаты и соединяем их линией. Все клево, за счет одного переодичность прихода координат, если у пользователя паркинсон, то мышь дергается очень быстро и координаты приходят реже, получаются ломанные линии.
Во первых Qt возможно может пропускать часть событий мыши(именно движения). Насколько мне известно например при ресайзе формы часть событий пропускается дабы сдвиг на пиксель не преводил к ресайзу если сразу за ним последует еще несколько, а подождет немного ).
Во вторых я бы делал примерно так(вроде так и сделано в нормальных редакторах):
1) Находим способ определять координаты мыши( посмотреть флаги кьюта, отдельный поток которых фиксирует координаты и т.д. ).
2) При движении эти координаты кладем в контейнер.
3) Отдельный поток достает из этого контейнера координаты и в фоне рисует.
В результате если пользователь проведет красивую линию мышкой, но комп не справится то получится нормальное изображение хоть и с задержкой. Пользователей это намного больше устроит чем подвисание мыши.
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #9 : Ноябрь 20, 2012, 22:00 »

а вот это интересная идея, попробую сделать.
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #10 : Ноябрь 21, 2012, 10:48 »

Сделал как советовал V1KT0P, работает хорошо, на нажатие мыши запускаю поток, который в буфер собирает точки, на отпускание завершаю поток, на движение из буфера рисую по точкам.
Записан
panAlexey
Гипер активный житель
*****
Offline Offline

Сообщений: 864

Акцио ЗАРПЛАТА!!!!! :(


Просмотр профиля
« Ответ #11 : Ноябрь 21, 2012, 13:45 »

Сделал как советовал V1KT0P, работает хорошо, на нажатие мыши запускаю поток, который в буфер собирает точки, на отпускание завершаю поток, на движение из буфера рисую по точкам.
Интересно код посмотреть.
Записан

Win Xp SP-2, Qt4.3.4/MinGW. http://trdm.1gb.ru/
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #12 : Ноябрь 21, 2012, 14:17 »

Из проекта вырывать не охото, щас объясню как сделал если будет не понятно то накидаю пример простой

есть некий класс(буду писать примерно)

описание

Код:
class PenGraphItem : public AbstractGraphItem
{
  blablabla

  private:
     QList<QPoint> *m_lstBuff;  // создается в конструкторе
     bool *m_stopThreadBuff; // создается в конструкторе
};

реализация

Код:
void pCreateBufferPoint(QList<QPoint> *lstPoint, bool *stop)
{
    while(!(*stop)) {
        lstPoint->append(QCursor::pos());

        QEventLoop loop;
        QTimer::singleShot(10,&loop,SLOT(quit()));
        loop.exec();
    }
}

void PenGraphItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    (*m_stopThreadBuff) = false;
    m_bufferPoint->clear();
    QtConcurrent::run(pCreateBufferPoint,m_bufferPoint,m_stopThreadBuff);
}

void PenGraphItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
        for (int i = 0; i < m_bufferPoint->count(); ++i) {
            paint(m_bufferPoint->at(i));
        }
     
        paint(event->pos());
        m_bufferPoint->clear();
}

void PenGraphItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
       (*m_stopThreadBuff) = true;
}

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

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Ноябрь 21, 2012, 14:50 »

Код:
void PenGraphItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
...
        m_bufferPoint->clear();
}
Не вижу каким образом это "потокобезопасно". Ведь в этот момент др нитка может писать в  m_bufferPoint. Или я чего-то не понял?
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #14 : Ноябрь 21, 2012, 15:02 »

Да, вы правы, поправил таким образом

Код:
void pCreateBufferPoint(QList<QPoint> *lstPoint, bool *stop)
{
    QMutex mutex;

    while(!(*stop)) {

        mutex.lock();
        if (lstPoint->count() > 0) {
            if (lstPoint->last() != QCursor::pos())
                lstPoint->append(QCursor::pos());
        }else
            lstPoint->append(QCursor::pos());
        mutex.unlock();

        QEventLoop loop;
        QTimer::singleShot(10,&loop,SLOT(quit()));
        loop.exec();
    }
}

заодно впилил проверку на то что бы одинаковые точки в конец не добавлялись, если юзверь просто так зажал кнопку. Так вроде все кошерно.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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