Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: klim от Июль 18, 2008, 10:33



Название: Не отображается виджет в QScrollArea
Отправлено: klim от Июль 18, 2008, 10:33
Здравствуйте!
Имеется самодельный widget, созданный на основе QWidget, рисующий с помощью paintEvent битмап. При обычном вызове:
Код:
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    paintWidget widget;
    widget.show();

    return app.exec();
}
всё работает как надо.

Однако после попытки запихнуть его в QScrollArea, получаю только серый фон области прокрутки, а сам widget не отрисовывается.
Код:
mainWidget::mainWidget(QWidget *parent) : QWidget(parent)
{
    paintWidget *map = new paintWidget();
    scrollArea = new QScrollArea(this);
    scrollArea->setWidget(map);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    mainWidget widget;
    widget.show();

    return app.exec();
}
В чем косяк?


Название: Re: Не отображается виджет в QScrollArea
Отправлено: spirit от Июль 18, 2008, 11:04
имхо, что-то не то с вашим виджетом, т.к. если сделать следующую земену, то все ок
Код:
mainWidget::mainWidget(QWidget *parent) : QWidget(parent)
{
    QTextEdit *map = new QTextEdit();
    scrollArea = new QScrollArea(this);
    scrollArea->setWidget(map);
}
а ваш paintWidget содержит лейауты?


Название: Re: Не отображается виджет в QScrollArea
Отправлено: klim от Июль 18, 2008, 11:13
Ну, да. Я тоже подсовывал QLabel с тем же битмапом - всё на ура работает.

Если нужно вот мой страшный код paintWidget:
Код:
class paintWidget : public QWidget
{
public:
    paintWidget(QWidget *parent = 0);
   
protected:
    void paintEvent(QPaintEvent *e);
    void mousePressEvent(QMouseEvent *e);
    void mouseMoveEvent(QMouseEvent *e);
    bool isInside(int ix, int iy, int a, int n);
   
private:
    QPixmap mapImage;
    QPoint curLine[2];
    QPoint point[MAX_VERTEX_NUMBER];
    int vert_num;
   
    QPoint area[MAX_AREA_NUMBER][MAX_VERTEX_NUMBER];
    int area_num;
    int a_vert_num[MAX_AREA_NUMBER];
   
    int activeArea;
   
    bool bDrawing;
   
    double x1lon, x2lon;  // ??????? - x
    double y1lat, y2lat;  // ?????? - y
    int width, height;
    double stepx, stepy;
    double curlon, curlat;
};

paintWidget::paintWidget(QWidget *parent) : QWidget(parent)
{
    setMouseTracking(true);
   
    vert_num = 0;
    area_num = 0;
    activeArea = -1;
   
    mapImage = QPixmap("e:\\map.bmp");
    width = mapImage.width();
    height = mapImage.height();
   
    x1lon = 30.146484;
    x2lon = 30.585938;
    y1lat = 59.800634;
    y2lat = 60.108670;
   
    stepx = (x2lon - x1lon) / width;
    stepy = (y2lat - y1lat) / height;
   
    bDrawing = false;
}

void paintWidget::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    QPen pen;
    QBrush brush;
   
    painter.drawPixmap(0,0,mapImage);
   
    pen.setColor(QColor(0,200,0));
    pen.setWidth(2);
    painter.setPen(pen);
    brush.setStyle(Qt::SolidPattern);
    brush.setColor(QColor(0,255,0,10));
    painter.setBrush(brush);
    for(int a=0; a<area_num; a++)
    {
        for(int i=1; i<a_vert_num[a]; i++)
        {
            painter.drawPolygon(area[a],a_vert_num[a]-1);
        }
    }
   
   
    pen.setColor(QColor(Qt::black));
    painter.setPen(pen);
    painter.setFont(QFont("Lucida Console",14));
    painter.drawText(QRect(15,10,200,200),QString("%1\n%2").arg(curlat).arg(curlon));
   
    pen.setColor(QColor(255,128,0));
    pen.setWidth(2);
    painter.setPen(pen);
    if(bDrawing)
    {
        for(int i=1; i<vert_num; i++)
            painter.drawLine(point[i-1],point[i]);
        painter.drawLine(curLine[0],curLine[1]);
    }
    if(activeArea >= 0)
    {
        painter.drawPolygon(area[activeArea],a_vert_num[activeArea]-1);
    }
   
}

void paintWidget::mousePressEvent(QMouseEvent *e)
{
     if(e->button() == Qt::LeftButton)
     {
         if(bDrawing)
         {
             point[vert_num++] = curLine[1];
             curLine[0] = curLine[1];
         }else{
             point[0] = e->pos();
             vert_num = 1;
             curLine[0] = curLine[1] = e->pos();
             bDrawing = true;
         }
     }
     
     if(e->button() == Qt::RightButton)
     {
         if(bDrawing)
         {
             point[vert_num++] = point[0];
             bDrawing = false;
             
             // ??????????? ?????????? ??????? ? ????????
             int l = sizeof(point) / sizeof(point[0]);
             for(int i=0; i<l; i++)
             {
                 area[area_num][i] = point[i];
             }
             a_vert_num[area_num++] = vert_num;
         }
     }
     
     update();
}

void paintWidget::mouseMoveEvent(QMouseEvent *e)
{
    if(bDrawing)
    {
        // ???????? ? ???????????
        QPoint mouse;
        QPoint point;
        QPoint temp;
        int m = 999;
        int tempm;
        mouse = e->pos();
        for(int a=0; a<area_num; a++)
        {
            for(int i=1; i<a_vert_num[a]; i++)
            {
                temp = mouse-area[a][i];
                tempm = temp.manhattanLength();
                if(tempm < m)
                {
                    point = area[a][i];
                    m = tempm;                   
                }
            }
        }
        if(m<20)
        {
            curLine[1] = point;
        }else{
            curLine[1] = e->pos();
        }
        update();
    }else{
        activeArea = -1;
        for(int i=0; i<area_num; i++)
            if(isInside(e->x(),e->y(),i,a_vert_num[i]))
                activeArea = i;
        update();
    }
   
    curlon = x1lon + e->x()*stepx;
    curlat = y2lat - e->y()*stepy;
}

bool paintWidget::isInside(int ix, int iy, int a, int n)
{
    // mine
    double sx = (double)ix;
    double sy = (double)iy;
   
    int poly[n*2];
    for(int i=0; i<n; i++)
    {
        poly[i*2] = area[a][i].x();
        poly[i*2+1] = area[a][i].y();
    }
    // end of mine
   
  int x[50], y[50];
  n--;
  for(int i=0; i<n; i++)
  {
    x[i] = poly[i*2];
    y[i] = poly[i*2+1];
  }
int pj, pk=0;
double wrkx, yu, yl;
for (pj=0; pj<n; pj++)
{
yu = y[pj]>y[(pj+1)%n]?y[pj]:y[(pj+1)%n];
yl = y[pj]<y[(pj+1)%n]?y[pj]:y[(pj+1)%n];
if (y[(pj+1)%n] - y[pj])
wrkx = x[pj] + (x[(pj+1)%n] - x[pj])*(sy - y[pj])/(y[(pj+1)%n] - y[pj]);
else
wrkx = x[pj];
if (yu >= sy)
if (yl < sy)
{
if (sx > wrkx)
pk++;
if (fabs(sx - wrkx) < 0.00001) return true;
}
if ((fabs(sy - yl) < 0.00001) && (fabs(yu - yl) < 0.00001) && (fabs(fabs(wrkx - x[pj]) + fabs(wrkx - x[(pj+1)%n]) - fabs(x[pj] - x[(pj+1)%n])) < 0.0001))
return true;
}
if (pk%2)
return true;
else
return false;
}


Название: Re: Не отображается виджет в QScrollArea
Отправлено: spirit от Июль 18, 2008, 11:15
желательно еще бы указывать версию кути


Название: Re: Не отображается виджет в QScrollArea
Отправлено: Alex03 от Июль 18, 2008, 11:17
Определите sizeHint() для своего paintWidget, ну или на крайняк установите для него минимальный размер - setMinimumSize().


Название: Re: Не отображается виджет в QScrollArea
Отправлено: klim от Июль 18, 2008, 11:20
желательно еще бы указывать версию кути
4.4.0

Определите sizeHint() для своего paintWidget, ну или на крайняк установите для него минимальный размер - setMinimumSize().
Спасибо, сейчас почитаю.


Название: Re: Не отображается виджет в QScrollArea
Отправлено: klim от Июль 18, 2008, 11:26
А setMinimumSize() где нужно прописывать? Я в конструкторе piantWidget написал, так у меня scrollArea вообще в точку превратилась  >:(


Название: Re: Не отображается виджет в QScrollArea
Отправлено: spirit от Июль 18, 2008, 11:30
в общем все работает.
Код:
paintWidget::paintWidget(QWidget *parent) : QWidget(parent)
{
    setMouseTracking(true);
   
    vert_num = 0;
    area_num = 0;
    activeArea = -1;
   
mapImage = QPixmap("e:/map.bmp");
    width = mapImage.width();
    height = mapImage.height();

    resize(width, height);
....


Название: Re: Не отображается виджет в QScrollArea
Отправлено: klim от Июль 18, 2008, 11:33
в общем все работает.
Да, точно... хм..
Спасибо.

А почему он в первом случае выводит с какими-то размерами по-умолчанию виджет, а во втором (там где qscrollarea появляется) - нет?


Название: Re: Не отображается виджет в QScrollArea
Отправлено: Alex03 от Июль 18, 2008, 12:24
А setMinimumSize() где нужно прописывать? Я в конструкторе piantWidget написал, так у меня scrollArea вообще в точку превратилась  >:(
Совсем простенький пример проекта не помешал бы.

Цитировать
When using a scroll area to display the contents of a custom widget, it is important to ensure that the size hint of the child widget is set to a suitable value. If a standard QWidget is used for the child widget, it may be necessary to call QWidget::setMinimumSize() to ensure that the contents of the widget are shown correctly within the scroll area.
И
Цитировать
Size Hints and Size Policies

When implementing a new widget, it is almost always useful to reimplement sizeHint() to provide a reasonable default size for the widget and to set the correct size policy with setSizePolicy().

By default, composite widgets which do not provide a size hint will be sized according to the space requirements of their child widgets.

The size policy lets you supply good default behavior for the layout management system, so that other widgets can contain and manage yours easily. The default size policy indicates that the size hint represents the preferred size of the widget, and this is often good enough for many widgets.



Название: Re: Не отображается виджет в QScrollArea
Отправлено: klim от Июль 20, 2008, 18:13
Совсем простенький пример проекта не помешал бы.
Пример программки, где QScrollArea в точку превращается?


Название: Re: Не отображается виджет в QScrollArea
Отправлено: Alex03 от Июль 21, 2008, 08:33
Совсем простенький пример проекта не помешал бы.
Пример программки, где QScrollArea в точку превращается?
Да, я имел ввиду минимально возможный вариант кода, который целиком компилируется, и в котором проявляется Ваша "проблема".

Потому как иначе многое не понятно.
например приводя код
Код:
mainWidget::mainWidget(QWidget *parent) : QWidget(parent)
{
    paintWidget *map = new paintWidget();
    scrollArea = new QScrollArea(this);
    scrollArea->setWidget(map);
}
Ничего не ясно об этом mainWidget, и сдаётся мне что тут проблема не только в том что paintWidget не ресайзится в QScrollArea, но и в том что QScrollArea не ресайзится в mainWidget, по крайней мере Вы про это ничего не сказали, и не привели остального кода mainWidget с лэйаутами или чёнить типа:
Код:
void mainWidget::resizeEvent(QResizeEvent * event)
{
    m_pScrollArea->resize(event->size());
}


Приведите примерчик типа такого:
Код:
#include <QApplication>
#include <QPushButton>
#include <QPainter>
#include <QImage>
#include <QRgb>
#include <QMainWindow>
#include <QScrollArea>

//#define USE_SET_MIN_SIZE 1
//#define USE_MIN_HINT     1

class paintWidget : public QWidget
{
public:
    paintWidget(QWidget *parent = 0);
   
#ifdef USE_MIN_HINT
    virtual QSize sizeHint() const;
#endif
protected:
    void paintEvent(QPaintEvent *e);
   
private:

    QSize m_size;
    QImage m_img;
};

paintWidget::paintWidget(QWidget *parent) : QWidget(parent)
{
    m_size = QSize(256, 256);
    m_img = QImage(m_size, QImage::Format_RGB32);
#ifdef USE_SET_MIN_SIZE
    setMinimumSize(m_size);
#endif
}
#ifdef USE_MIN_HINT
QSize paintWidget::sizeHint() const
{
    return m_size;
}
#endif
void paintWidget::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    QPen pen;
    QBrush brush;

    for(int y=0; y<m_size.height(); y++)
    {
        QRgb* prgb = (QRgb*)m_img.scanLine(y);
        for(int x=0; x<m_size.width(); x++)
        {
            *prgb++ = qRgb(x, y, x+y);
        }
   
    }

    painter.drawImage(QRect(0, 0, width(), height()), m_img, QRect(0, 0, 256, 256));
}

int main( int argc, char **argv )
{
    QApplication a( argc, argv );

    paintWidget pw1;
    pw1.show();

    QMainWindow mw;
    mw.show();

    QScrollArea* psa = new QScrollArea(&mw);
    mw.setCentralWidget(psa);
    paintWidget* ppw2 = new paintWidget(psa);
    psa->setWidget(ppw2);

    return a.exec();
}
Попробуйте в нём последовательно разкомментировать строки
Код:
//#define USE_SET_MIN_SIZE 1
//#define USE_MIN_HINT     1