Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ определение размеров виджета при использовании QPicture

Автор: Litkevich Yuriy 26.12.2009, 1:00

Пытаюсь рисовать на виджете с использованием QPicture.

void PictureViewer::paintEvent(QPaintEvent*)
{
    QPainter painter;
    if (pic){
        painter.begin(this);
        painter.drawPicture(QPoint(0, 0), *pic);
        painter.end();
    }
    
}
здесь pic - указатель на QPicture.

QPicture я загружаю из файла. На основе QPicture::boundingRect().size(), загруженного рисунка, изменяю размер виджета.
Однако рисунок рисовался с отступом от краёв исходного виджета (рисовальщика) по этому получаю такое:
, если увеличить размеры виджета мышкой, то видно весь рисунок:


Вопрос:
Как определить отступ сверху и слева от края виджета, до рисунка.

Была мысль спросить у рисовальщика (QPainter'а) минимальную координату, где он побывал, но такого метода я не нашёл.

На всякий случай проект прикрепил:  PictureViewer.zip ( 3.89 килобайт ) : 168

Файлы:
painter1.log
painter2.log
тестовые, для загрузки.

Автор: Kagami 26.12.2009, 9:27

Юра, ты меня удивляешь. Есть же функции QWIdget::map*().
Так как у тебя рисовальщик лежит в компоновке и он становится его родительским виджетом, то самый простой способ - вызвать у рисовальщика mapToParent(QPoint(0,0)) - не подходит. Вариантов есть два. Либо хранить в рисовальщике указатель на объект Window и использовать mapTo(window, QPoint(0,0)), либо перебирать родительские виджеты в цикле, пока не дойдем до последнего:

   QWidget* topParent = parentWidget();
   while (topParent->parentWidget())
      topParent = topParent->parentWidget();
а затем mapTo(topParent, QPoint(0,0)).

Автор: Litkevich Yuriy 26.12.2009, 12:49

Kagami, не понял.
Я рисую с координат (0, 0) самого виджета.
В итоге мне нужно установить виджету размер, такой, чтобы весь рисунок помещался.

Автор: Kagami 26.12.2009, 14:00

Ты про компоновку забываешь - window -> mainLayout -> viewer. А ведь у нее свои поля есть. Поэтому нулевая точка рисовальщика на viewer'е будет смещена относительно (0,0) виджета window.

Автор: Litkevich Yuriy 26.12.2009, 15:01

Меня не интерисует виджет window.
При изменении размеров окна я вижу ту куртинку, какую создавал (сохранил в файле).
Я умышленно покрасил фон виджета PictureViewer, чтобы видеть его размеры.

Цитата(Litkevich Yuriy @ 26.12.2009, 4:00) *
Как определить отступ сверху и слева от края виджета, до рисунка.
речь идёт о PictureViewer, на котором я рисую. под рисунком я понимаю QPicture, который рисуется рисовальщиком (QPainter).
Я рисую по координатам (0, 0):
painter.drawPicture(QPoint(0, 0), *pic);
, чтобы воспроизвести рисунок, так, как он был в оригинале.

При рисовании компоновщики не играют ни какой роли, равно как и наличие родительского виджета. PictureViewer может быть единственным виджетом (окном верхнего уровня)

Вот этот размер меня интерисует:

Автор: Kagami 26.12.2009, 19:26

Юр, что бы до конца прояснить ситуацию, при создании этих рисунков, они рисовались с точки (0, 0) или со смещением, которое ты и хочешь выяснить?

Автор: Litkevich Yuriy 26.12.2009, 20:03

Цитата(Kagami @ 26.12.2009, 22:26) *
они рисовались с точки (0, 0
рисовались так:
    virtual void paintEvent(QPaintEvent*)
    {
        QPicture    pic;
        QPainterPath path;
        QPointF      pt1(width(), height() / 2);
        QPointF      pt2(width() / 2, -height());
        QPointF      pt3(width() / 2, 2 * height());
        QPointF      pt4(0, height() / 2);
        path.moveTo(pt1);
        path.cubicTo(pt2, pt3, pt4);/**/

        QRect rect(width() / 4, height() / 4, width() / 2, height() / 2);
        path.addRect(rect);
        path.addEllipse(rect);

        QPainter painter;
        qDebug() << "---------- record ------------";
        painter.begin(&pic);
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.setPen(QPen(Qt::blue, 6));
        painter.drawPath(path);
        painter.end();
        if (!pic.save("./painter.log")){
            qDebug() << "anable to save log-file";
        }
        
        qDebug() << "---------- play ------------";
        painter.begin(this);
        painter.drawPicture(QPoint(0, 0), pic);
        painter.end();
        
    }


Это переделанный пример из книги Шлее.

как я понимаю, координаты именно (0, 0)

Автор: Kagami 26.12.2009, 21:30

Чуть-чуть покопался в исходниках QPicture. Заметил что boundRect зашивается в файл при сохранении. Надо посмотреть как они его считают, может какая идея и придет.

UPD. Все оказалось гораздо проще. В файле, куда сохранен QPicture, зашит левый верхний угол ограничивающего прямоугольника и его высота и ширина. Как их считать написано в /opt/qtsdk-2009.05/qt/src/gui/image/qpicture.cpp, смотри функцию QPicturePrivate::checkFormat()

UPD2. Совсем забыл - ответ на твой первоначальный вопрос:

Цитата
int top = pic->boundingRect().y();
int left = pic->boundingRect().x();

Автор: Litkevich Yuriy 26.12.2009, 23:04

Цитата(Kagami @ 27.12.2009, 0:30) *
Надо посмотреть как они его считают
я его чуть ли не наизусть выучил

Цитата(Kagami @ 27.12.2009, 0:30) *
В файле, куда сохранен QPicture, зашит левый верхний угол ограничивающего прямоугольника
блин, как-то я то из виду упустил, что у прямоугольника начальная координата может быть не нулевой.

Kagami, спасибо большое!, почти сутки трахмучаюсь


Нынешний фрагмент кода от моего первоначального исходника:
PictureViewer::PictureViewer(const QPicture &picture, QWidget *pwgt) : QWidget(pwgt)
{
    *pic = picture;
    minSize = pic->boundingRect().size();
    
    int top = pic->boundingRect().y();
    int left = pic->boundingRect().x();
    qDebug() << "X =" << left << " | " << "Y =" << top;
    minSize += QSize(left, top);
}

void PictureViewer::refrash()
{
    minSize = pic->boundingRect().size();
    qDebug() << "PictureViewer::refrash...........minSize =" << minSize << "    size() =" << size();
    int top = pic->boundingRect().y();
    int left = pic->boundingRect().x();
    qDebug() << "X =" << left << " | " << "Y =" << top;
    minSize += QSize(left, top);    
        
    //resize(minSize);
    update();
    updateGeometry();
}


Вот как теперь:

Автор: Kagami 26.12.2009, 23:16

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

Цитата
int top = pic->boundingRect().y();
int left = pic->boundingRect().x();
painter.drawPicture(QPoint(-left, -top), *pic);

Автор: Litkevich Yuriy 26.12.2009, 23:20

Цитата(Kagami @ 27.12.2009, 2:16) *
Кстати, а почему бы тебе не выводить рисунок со смещением?
а потому-что другой рисунок обрежется, проверь на painter2.log

Автор: Kagami 26.12.2009, 23:49

У меня вроде нормально. По сравнению с перыми вариантом я только добавил смещение для вывода. Минимальный размер оставил равным boundingRect()

 

Автор: Litkevich Yuriy 27.12.2009, 1:45

Подумать конечно можно, если смещать ровно на отступ. Но пока не знаю, стоит ли так делать.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)