Results 1 to 8 of 8

Thread: QRubberBand painting in the scroll area widget

  1. #1
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Thumbs up QRubberBand painting in the scroll area widget

    Hi all, I have subclassed QScrollArea because I want to draw a selection rectangle with QRubberband when the user clicks the left mouse button on the viewport. With the code below, the program does exactly what I want (the rubberband is well drawn respect the mouse icon and the scrollbars of the scroll area moves when the user is making a selection and is at the margins of the viewport). The only problem is that the rubberband is painted respect the scrollarea and what I want is paint it respect the widget of the scroll area. So now the rubber band is always painted in the same position even if the scroll bars are moved. Can anybody tell me how to I have to modify the code below to draw the rubberband respect the position of the widget of the scroll area? Thanks

    void FotoAreaEditorFotos::mousePressEvent(QMouseEvent *event)
    {
    if (event -> button() != Qt::LeftButton) return;

    iniSeleccioX = event -> globalX();
    iniSeleccioY = event -> globalY();

    areaSeleccio = new QRubberBand(QRubberBand::Rectangle);

    areaSeleccio -> setGeometry(iniSeleccioX, iniSeleccioY, 1, 1);

    areaSeleccio -> show();
    }


    void FotoAreaEditorFotos::mouseMoveEvent(QMouseEvent *event)
    {
    int x, y, w, h;
    QScrollBar *scrollBar;

    if (event ->buttons() == Qt::LeftButton)
    {
    int auxX = event -> globalX();
    int auxY = event -> globalY();

    QPoint posMax = mapToGlobal(QPoint(viewport() -> width() - 1,
    viewport() -> height() - 1));
    QPoint posMin = mapToGlobal(QPoint(0 , 0));

    if (auxX < iniSeleccioX)
    {
    if (auxX <= posMin.x())
    {
    scrollBar = horizontalScrollBar();
    scrollBar -> setValue(scrollBar -> value() - scrollBar -> singleStep());
    x = posMin.x();
    }
    else
    x = auxX;

    w = iniSeleccioX - x + 1;
    }
    else
    {
    if (auxX >= posMax.x())
    {
    scrollBar = horizontalScrollBar();
    scrollBar -> setValue(scrollBar -> value() + scrollBar -> singleStep());
    w = posMax.x() - iniSeleccioX + 1;
    }
    else
    w = auxX - iniSeleccioX + 1;

    x = iniSeleccioX;
    }

    if (auxY < iniSeleccioY)
    {
    if (auxY < posMin.y())
    {
    scrollBar = verticalScrollBar();
    scrollBar -> setValue(scrollBar -> value() - scrollBar -> singleStep());
    y = posMin.y();
    }
    else
    y = auxY;

    h = iniSeleccioY - y + 1;
    }
    else
    {
    if (auxY > posMax.y())
    {
    scrollBar = verticalScrollBar();
    scrollBar -> setValue(scrollBar -> value() + scrollBar -> singleStep());
    h = posMax.y() - iniSeleccioY + 1;
    }
    else
    h = auxY - iniSeleccioY + 1;

    y = iniSeleccioY;
    }

    areaSeleccio -> setGeometry(x, y, w, h);
    }
    }


    void FotoAreaEditorFotos::mouseReleaseEvent(QMouseEvent *event)
    {
    if (event -> button() == Qt::LeftButton)
    delete areaSeleccio;
    }

  2. #2
    Join Date
    Jan 2006
    Location
    Frankfurt
    Posts
    500
    Thanks
    1
    Thanked 52 Times in 52 Posts
    Platforms
    MacOS X Unix/X11

    Default Re: QRubberBand painting in the scroll area widget

    I think the main purpose of QRubberBand is to show a rubberband above widgets i.e. show a rubberband for resizing a window.

    However, it should also work with QRubberBand. I think the problem is that you are translating to global coordinates. So you are translating the offset of the scrollview away.

    The simplest solution will be to draw the selection rectangle on your own using QPainter. If you draw the rectangle yourself, you can also have semitransparent background. This will look nice.

    Edit: QtDesigner uses such a semi transparent rubberband. You can have a look at the sourcecode there, however, it is a lot of code.
    It's nice to be important but it's more important to be nice.

  3. #3
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QRubberBand painting in the scroll area widget

    Thanks for the advise. But I think that with QRubberBand I could have semitransparent background changing it with setPalette (It's just a supposition)

  4. #4
    Join Date
    Jan 2006
    Location
    Frankfurt
    Posts
    500
    Thanks
    1
    Thanked 52 Times in 52 Posts
    Platforms
    MacOS X Unix/X11

    Default Re: QRubberBand painting in the scroll area widget

    I don't think so because semitransparent background is a bit tricky and I doubt that it as easy in a toplevel-widget as using a QPainter and draw on a window.
    It's nice to be important but it's more important to be nice.

  5. #5
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QRubberBand painting in the scroll area widget

    Finally I have solved the problem painting the selection rectangle with qpainter in the paintEvent of the widget. If anybody is interesed in the code ask here for it.

  6. #6
    Join Date
    Jan 2006
    Location
    Kerala
    Posts
    371
    Thanks
    76
    Thanked 37 Times in 32 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QRubberBand painting in the scroll area widget

    Ofcourse Everyone needs the code
    We have a working example to refer to Don't we ?
    We can't solve problems by using the same kind of thinking we used when we created them

  7. #7
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QRubberBand painting in the scroll area widget

    Ok here's the code:

    Qt Code:
    1. void FotoEditorFotos::mousePressEvent(QMouseEvent *event)
    2. {
    3. if (event -> button() != Qt::LeftButton) return;
    4.  
    5. iniSeleccioX = event -> x();
    6. iniSeleccioY = event -> y();
    7.  
    8. seleccio = true;
    9. x = iniSeleccioX;
    10. y = iniSeleccioY;
    11. w = 1;
    12. h = 1;
    13.  
    14. update();
    15. }
    16.  
    17.  
    18. void FotoEditorFotos::mouseMoveEvent(QMouseEvent *event)
    19. {
    20. if (event -> buttons() == Qt::LeftButton)
    21. {
    22. int auxX = event -> x();
    23. int auxY = event -> y();
    24. int posMaxX = width() - 1;
    25. int posMaxY = height() - 1;
    26.  
    27. if (auxX < iniSeleccioX)
    28. {
    29. if (auxX < 0)
    30. x = 0;
    31. else
    32. x = auxX;
    33.  
    34. w = iniSeleccioX - x + 1;
    35. }
    36. else
    37. {
    38. if (auxX >= posMaxX)
    39. w = posMaxX - iniSeleccioX + 1;
    40. else
    41. w = auxX - iniSeleccioX + 1;
    42.  
    43. x = iniSeleccioX;
    44. }
    45.  
    46. if (auxY < iniSeleccioY)
    47. {
    48. if (auxY < 0)
    49. y = 0;
    50. else
    51. y = auxY;
    52.  
    53. h = iniSeleccioY - y + 1;
    54. }
    55. else
    56. {
    57. if (auxY >= posMaxY)
    58. h = posMaxY - iniSeleccioY + 1;
    59. else
    60. h = auxY - iniSeleccioY + 1;
    61.  
    62. y = iniSeleccioY;
    63. }
    64.  
    65. update();
    66. }
    67.  
    68. //emit UpdateMouseCoords(event->x(), event->y());*/
    69. event -> ignore();
    70. }
    71.  
    72.  
    73. void FotoEditorFotos::mouseReleaseEvent(QMouseEvent *event)
    74. {
    75. if (event -> button() == Qt::LeftButton)
    76. // Do something with the selection rectangle...
    77. seleccio = false;
    78. }
    79.  
    80.  
    81. void FotoEditorFotos::paintEvent(QPaintEvent *event)
    82. {
    83. int pixX, pixY;
    84.  
    85. if (pixmap.width() < width())
    86. pixX = (width() - pixmap.width()) / 2;
    87. else
    88. pixX = 0;
    89. if (pixmap.height() < height())
    90. pixY = (height() - pixmap.height()) / 2;
    91. else
    92. pixY = 0;
    93.  
    94. QPainter painter;
    95. painter.begin(this);
    96. QPen pen(Qt::blue, 2, Qt::DashLine);
    97. painter.setPen(pen);
    98. //painter.rotate(5);
    99. //painter.setBrush(Qt::Dense1Pattern);
    100. painter.drawPixmap(pixX, pixY, pixmap);
    101. if (seleccio)
    102. painter.drawRect(x, y, w, h);
    103. painter.end();
    104. }
    To copy to clipboard, switch view to plain text mode 

    That's the code for the widget that I insert in the scroll area and the code for the scroll area is the next:

    Qt Code:
    1. FotoAreaEditorFotos::FotoAreaEditorFotos(EditorFotos *parent)
    2. : QScrollArea(parent)
    3. {
    4. foto = new FotoEditorFotos;
    5.  
    6. setBackgroundRole(QPalette::Dark);
    7. setWidget(foto);
    8. }
    9.  
    10.  
    11. void FotoAreaEditorFotos::mouseMoveEvent(QMouseEvent *event)
    12. {
    13. QScrollBar *scrollBar;
    14.  
    15. if (event ->buttons() != Qt::LeftButton) return;
    16.  
    17. int auxX = event -> x();
    18. int auxY = event -> y();
    19. int posMaxX = viewport() -> width() - 1;
    20. int posMaxY = viewport() -> height() - 1;
    21.  
    22. if (auxX <= 0)
    23. {
    24. scrollBar = horizontalScrollBar();
    25. scrollBar -> setValue(scrollBar -> value() - scrollBar -> singleStep());
    26. }
    27. else if (auxX >= posMaxX)
    28. {
    29. scrollBar = horizontalScrollBar();
    30. scrollBar -> setValue(scrollBar -> value() + scrollBar -> singleStep());
    31. }
    32.  
    33. if (auxY <= 0)
    34. {
    35. scrollBar = verticalScrollBar();
    36. scrollBar -> setValue(scrollBar -> value() - scrollBar -> singleStep());
    37. }
    38. else if (auxY >= posMaxY)
    39. {
    40. scrollBar = verticalScrollBar();
    41. scrollBar -> setValue(scrollBar -> value() + scrollBar -> singleStep());
    42. }
    43. }
    44.  
    45.  
    46. void FotoAreaEditorFotos::paintEvent(QPaintEvent *event)
    47. {
    48. //I put directly the size of the pixmap (256, 259) because it's a test version, in the final version I have to make a method to return the pixmap size ;)
    49. if (viewport() -> width() <= 259)
    50. {
    51. setWidgetResizable(false);
    52. foto -> resize(259, viewport() -> height());
    53. }
    54. else
    55. setWidgetResizable(true);
    56.  
    57. if (viewport() -> height() <= 256)
    58. {
    59. setWidgetResizable(false);
    60. foto -> resize(qMax(259, viewport() -> width()), 256);
    61. }
    62. else
    63. setWidgetResizable(widgetResizable());
    64. }
    To copy to clipboard, switch view to plain text mode 

    All that code paint the image centered in the scroll area and if the image is larger thn the scroll area shows the scroll bars. Moreover if the user press the mouse under the viewport a selection rectangle is shown and if the rectangle is at the limits of the viewport of the scroll area, the scroll bars move automaticaly. Enjoy it.
    Last edited by SkripT; 14th January 2006 at 11:59.

  8. The following user says thank you to SkripT for this useful post:

    Goddard (29th January 2015)

  9. #8
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QRubberBand painting in the scroll area widget

    Hi all. These days I have made a new version for the code above. Now the image can be scaled and rotated and every time the image is painted automaticly at the center (applying the little bit of trigonometry that I remember ). Well, all goes perfect but there's a little problem: the updating of the rubberband is very slow . The cause is that every time that i call the update function of the widget, paintEvent has to scale and rotate the pixmap to paint it again and, after, paint the rectangle of the rubber band under the pixmap. This means that when I move the mouse, the rubber band takes a little time in being painted under the cursor (the rubber band is delayed respect the cursor when I move the mouse a little fast). Could anyone tell me if there's a solution for it? Something like paint only the viewport of the scroll area or paint only the portion of the image that has to be updated? Thanks
    Last edited by SkripT; 17th January 2006 at 17:06.

Similar Threads

  1. QDockWidget inside another widget in the center?
    By Antebios in forum Qt Programming
    Replies: 1
    Last Post: 16th February 2010, 07:06
  2. Custom Scroll Widget Sizing Problem
    By sepehr in forum Qt Programming
    Replies: 2
    Last Post: 28th November 2008, 11:42
  3. Stacked Widget Scroll
    By csvivek in forum Qt Programming
    Replies: 6
    Last Post: 27th May 2008, 11:36
  4. abstract scroll area
    By moowy in forum Qt Programming
    Replies: 2
    Last Post: 2nd October 2006, 09:15
  5. Problem with QScrollArea updating from 4.0.1 to 4.1.0
    By SkripT in forum Qt Programming
    Replies: 8
    Last Post: 28th January 2006, 22:35

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.