crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> [Решено] Рисование во View?, Как нарисовать что-нибудь изменяющееся минуя сцену?
Obey-Kun
  опции профиля:
сообщение 26.3.2010, 22:30
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 96
Регистрация: 24.3.2010
Пользователь №: 1556

Спасибо сказали: 3 раз(а)




Репутация:   0  


Нужно создать класс, который действовал бы аналогично QRubberBand. То есть чтобы его можно было создавать во вьюпорте View и изменять его параметры (размер, позицию), не заботясь о его перерисовке (чтобы он при этом сам перерисовывался).

Можете привести пример для, например, эллписа (и чтоб описывался он, по традиции Qt, как QRect). Использовать хочется по некоторой аналогии с QRubberBand:
В хедере View делается
QPoint m_origin;
AbstractRubberBand m_rubberband;


Использовать хочу так:
 void Widget::mousePressEvent(QMouseEvent *event)
{
     m_origin = event->pos();
     if (m_rubberband == NULL) {
         m_rubberband = new (m_instrument == Ellipse ? EllipseRubberBand(this) : RectangleRubberBand(this) );
     }
     m_rubberband->setGeometry(QRect(origin, QSize()));
     m_rubberband->show();
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    if (m_rubberban != NULL) {
       m_rubberband->setGeometry(QRect(origin, event->pos()).normalized());
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_rubberban != NULL) {
     m_rubberband->hide();
     // делаем что надо с полученной фигурой и удаляем m_rubberband
    }
}


Также нужен инструмент полигональной линии — в него последовательно (сигналами или ещё как) отправляются QPointF'ы или сигналы изменения позиции одного из QPointF, потом удаляем его и получаем shape.

Итак, что наследовать, что переопределять? :)

Опечатка, в хедер хочу делать так
QPoint m_origin;
AbstractRubberBand *m_rubberband;


Сообщение отредактировал Obey-Kun - 28.3.2010, 0:57
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
2 страниц V   1 2 >  
Начать новую тему
Ответов (1 - 9)
Litkevich Yuriy
  опции профиля:
сообщение 26.3.2010, 23:57
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Obey-Kun, ты вообще имеешь представление как рисуют на виджетах?
Есть демки, например, Сглаживание траектории
Имеет смысл посмотреть её код, в ней используется система рисования Arthur, т.е. рисование QPainter'ом в обработчике события рисования (QWidget::paintEvent())
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Obey-Kun
  опции профиля:
сообщение 27.3.2010, 18:29
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 96
Регистрация: 24.3.2010
Пользователь №: 1556

Спасибо сказали: 3 раз(а)




Репутация:   0  


Если честно, демку не осилил (всё в одну кучу сброшено, лень было разбираться), но волшебного слова «paintEvent» хватило, спасибо :)
Думал, что всё гораздо сложнее. Экспериментирую.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Obey-Kun
  опции профиля:
сообщение 27.3.2010, 19:01
Сообщение #4


Студент
*

Группа: Участник
Сообщений: 96
Регистрация: 24.3.2010
Пользователь №: 1556

Спасибо сказали: 3 раз(а)




Репутация:   0  


Хедер:
#pragma once
#ifndef MYRECTANGLE_H
#define MYRECTANGLE_H

#include <QWidget>

class MyRectangle : public QWidget
{
public:
    MyRectangle(QWidget* parent = 0);
    void changeRect(QRectF inRect);

private:
    QRectF m_rect;

protected:
    void paintEvent(QPaintEvent* );
};

#endif // MYRECTANGLE_H


Реализация:
#include "myrectangle.h"

#include <QtGui/QPainter>

MyRectangle::MyRectangle(QWidget* parent): QWidget(parent),
m_rect(10,10,10,10)
{
    setAttribute(Qt::WA_TransparentForMouseEvents);
    update();
}


void MyRectangle::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);
    QPainter painter;
    painter.begin(this);
    painter.setPen(Qt::blue);
    painter.drawRect(m_rect);
    painter.end();
}

void MyRectangle::changeRect(QRectF inRect)
{
    m_rect=inRect;
    update();
}


В свой view для эксперимента для MyRectangle *m_recttest. В конструкторе сделал m_recttest = new MyRectangle(this), в ивент нажатия мыши для левой кнопки m_recttest->changeRect(QRectF(20,20,20,20)), для правой m_recttest->changeRect(QRectF(10,10,20,20)).

Рисуется, но как-то странно. Он обрезается какой-то областью. Вот, смотрите:
После создания (m_rect равен QRectF(10,10,10,10)):

После m_recttest->changeRect(QRectF(10,10,20,20)):

После m_recttest->changeRect(QRectF(20,20,20,20)):


Почему так?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 27.3.2010, 19:10
Сообщение #5


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Obey-Kun @ 27.3.2010, 22:01) *
Он обрезается какой-то областью
если мышкой работать медленно, то артефакты (следы, остатки) какие-нибудь появляются?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Obey-Kun
  опции профиля:
сообщение 27.3.2010, 19:14
Сообщение #6


Студент
*

Группа: Участник
Сообщений: 96
Регистрация: 24.3.2010
Пользователь №: 1556

Спасибо сказали: 3 раз(а)




Репутация:   0  


нет, никаких артефактов не видно ни при каких условиях
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 27.3.2010, 19:21
Сообщение #7


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


А объект класса MyRectangle, как используется?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Obey-Kun
  опции профиля:
сообщение 27.3.2010, 19:28
Сообщение #8


Студент
*

Группа: Участник
Сообщений: 96
Регистрация: 24.3.2010
Пользователь №: 1556

Спасибо сказали: 3 раз(а)




Репутация:   0  


Я же говорю, в хедере View:
MyRectangle *m_recttest;

В конструкторе:
m_recttest = new MyRectangle(this);

И
void Area::mousePressEvent(QMouseEvent* event)
{
    if(event->button() == Qt::LeftButton) {
        m_recttest->changeRect(QRectF(20,20,20,20));
    }
    if(event->button() == Qt::RightButton) {
        m_recttest->changeRect(QRectF(10,10,20,20));
    }
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 27.3.2010, 19:50
Сообщение #9


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Obey-Kun, Т.е. ты положил этот виджет, в другой и без компоновщика. При этом не задав ни размер виджета ни его координату. Изменяя только прямоугольник рисования. соответвенно виджет пытается себя нарисовать за пределами своих размеров, за которыми Qt просто ничего не нарисует.

См. QWidget::setGeometry(), QWidget::resize(), ...

если вообще использовать такой подход как у тебя, с виджетом. То в представлении вместо:
m_recttest->changeRect(QRectF(20,20,20,20));
использовать:
m_recttest->setGeometry(QRectF(20,20,20,20));

А в самом виджете вместо:
painter.drawRect(m_rect);
использовать:
painter.drawRect(rect());

Тогда метод changeRect вообще не нужен
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Obey-Kun
  опции профиля:
сообщение 27.3.2010, 20:12
Сообщение #10


Студент
*

Группа: Участник
Сообщений: 96
Регистрация: 24.3.2010
Пользователь №: 1556

Спасибо сказали: 3 раз(а)




Репутация:   0  


Спасибо! Поправил конструктор:
MyRectangle::MyRectangle(QWidget* parent): QWidget(parent),
m_rect(10,10,10,10)
{
setAttribute(Qt::WA_TransparentForMouseEvents);
resize(parent->size());
update();
}
Правильное решение?

Вопрос немного не по теме — если планируется использовать несколько виджетов, которые будут рисоваться поверх моего вью, стоит ли использовать компоновщик?

Ух, сообщение тогда ещё не обновилось. Так и сделаю.

А какие ещё могут быть подходы?

setGeometry(QRectF) не бывает, только setGeometry(QRect) и setGeometry(int, int, int, int).

В общем, геометрия виджета описывается как QRect. Смотрим в описание QRect:
Цитата
Note that for historical reasons the values returned by the bottom() and right() functions deviate from the true bottom-right corner of the rectangle

И нарисована всеописывающая картинка. Я из-за этой путаницы c QRect голову ломал пару дней назад. Короче, получается такая фигня:


Верно понимаю, что обходить это вот так:
painter.drawRect(rect().x(), rect().y(), rect().width() -1, rect().height()-1);

?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.3.2024, 16:01