Qt: scrolling complex content. Web-Browser engine. Selecting a text - c++

Just curious about scrolling complicated content inside web browser - like application. Lets assume i am using Qt and C++. This is not "how to" question, but more like "how does it work"? Completely derived from my curiosity irrational questions.
I did small experiment.
Created large QWidget 800x60000 px.
Added 300 QWidgets 800x200 px that are painting themselves using QPainter. Each widget prints its unique name to console when paintEvent() is called.
Added (1.) to a QScrollArea 800x800.
When scrolling, i notice redrawing only widgets that are not fully displayed on the screen. It is only 1 widget at a time (scene: http://savepic.ru/2670640.jpg).
So QScrollArea (or QWidget? Who deside what widget to repaint?) is smart - we do not have CPU loaded redrawing all the 300 widgets all the time or memory consumption storing 800x60000 pixmap (-;
Lets assume i want to use mouse to select text and other elements on my "webpage". So i want to be able to mark them (by changing background). How would i implement that? How different web browsers do that? Selecting pictures, text, tables... Should i think about tracking the mouse and drawing gray/blue/pink background boxes behind elements and my custom widgets?
I have another experiment - displaying stack of messages. The scheme is the same, except QPainter is not used here - only QLabels, QTextExits, QPushButtons (scene: http://savepic.ru/2632728.jpg). I can set a flag SelectableByMouse for QLabel, but how do i select more than 1 message?
You could suggest me to use some Qt HTML renderer, but this is not the answer for 'how does it work".

Related

Qt: How do I stack widgets to do a transition between them, by fading one in and the other out?

Here's my end goal: I want to transition between two images. I want the original image to fade out, and at the same time, the new image to fade in.
I know I need to modify the opacity, and I found this great link for "How to make Qt widgets fade in or out": How to make Qt widgets fade in or fade out?
I also know I need to set the image for the QWidget, and I found out how to do that with the following code:
m_image1 = new QWidget();
m_image1->setStyleSheet("border-image: url(\"" + m_imagePath1 + "\") 0 0 0 0 strech strech; ");
Where I'm stuck is the layout. How do I lay a QWidget directly on top of another QWidget.
I did read about QStackedWidget, and it seems like it would be useful: https://doc.qt.io/qt-5/qstackedwidget.html . There's a method to set the current widget via setCurrentIndex(int). However, it doesn't seem to allow me to be transitioning out a widget and transitioning in a widget at the same time. It just either is one widget or the other widget. And from the class description, it says "a stack of widgets where only one widget is visible at a time."
A lot of the layouts I'm aware of, position items next to each other, not on top.
So, my question is how do I stack the widgets to do a transition between the widget contents, by fading them in/out?
Thank you.

A custom widget to display and select among multiple graphic views

I have a collection of images, dynamically generated through QGraphicsView widgets, and i'd like my users to choose between them. For that purpose, i would display inside a custom widget available images in some kind of grid and have users click the one they are interested in.
Multiple questions arise :
is there an existing widget that already fits this purpose ?
should i find a way to disable all mouse event handling by QGraphicsView items, or could i add a transparent widget in front of graphic views which would intercept them ?
is there a performance issue displaying many QGraphicsView widgets (up to a few hundreds) ? Should i export them to plain images first ?
First off, no, there's no widget designed specifically for that purpose.
I don't think you are grasping what QGraphicsView is for. It's for displaying a QGraphicsScene, which is meant to hold many QGraphicsItems. Based on your post, I can't see why you would need multiple QGraphicsViews. You can simply have one QGraphicsView and display many images inside of its scene. For example, see QGraphicsPixmapItem.
You definitely should not have hundreds of QGraphicsViews. You probably just want one (although a few could be justified in certain circumstances), in which you display many QGraphicsItems in a QGraphicsScene. You can definitely have hundreds of QGraphicsItems visible at once. In your case, you probably want QGraphicsPixmapItems, which are a subclass of QGraphicsItem. You could even have multiple QGraphicsScenes, and display whichever one is relevant using QGraphicsView::setScene. If you want the user to be able to select an image from a grid, and then work with that image, I would look to the State Pattern.
I can't think of any reason to disable mouse handling in QGraphicsViews, QGraphicsScenes, or QGraphicsItems. Why should these not handle their own mouse events? You can (and should, where necessary) subclass them and reimplement mousePressEvent, mouseMoveEvent, mouseRelease event, etc. to obtain the functionality you want.
Good luck!

Qt - QScrollBar skinning issue

I'm trying to skin a QScrollBar by reimplementing the paintEvent function, but I'm having trouble. I can't find any information on the buttons on the scroll bar, and I can only find (limited) information on the actual slider (the handle you can grab and drag). I looked at the QStyle as well and it still only gives information on the scroll handle and not the buttons. Hardcoding or using magic numbers is not an option because the buttons are placed differently on different operating systems (see: Here). Is there any way to programmatically get the layout of the Scrollbar, so I could accurately render the buttons and scroll handle at their correct positions?
As the painting itself is done by underlying style, not QScrollBar itself I'd suggest following:
Use QProxyStyle to override painting of QScrollBar.
This is how does Qt paints QScrollBar. You can alternate that
As alternative I'd suggest using Qt Style Sheets to change QScrollBar look'n'feel

Qt window resize problem

I am having a problem redrawing a QWidget window after its size has been adjusted. I have tried update(), repaint(), adjustSize(), but all seem to suffer from the same thing: only part of the window is redrawn, resulting in the window frame on the bottom and right sides to not show. The window is also not resized entirely.
Just in case it makes a difference, the window is in a QMdiArea.
Thanks.
// ... some subwidget resizing and moving.
calibrationWindowUIs[activeWindow].layoutWidget2->move(QPoint(oldXLeft, 30 + height + 21));
calibrationWindowUIs[activeWindow].layoutWidget1->move(QPoint(oldXRight, 30 + height + 21));
// Set window size.
calibrationWindows[activeWindow]->setMinimumSize(calibrationWindowUIs[activeWindow].tabWidget->geometry().width() + 40, calibrationWindowUIs[activeWindow].tabWidget->geometry().height() + 40);
calibrationWindows[activeWindow]->update();
Note: I'm new to Qt; perhaps I'm doing something wrong with layouts?
Edit: I may have not given enough information. Alright, to be quite honest, I still have to delve deeper into layouts and related material. What I had tried to do here was to use Qt Designer in order to design the window. I've done what perhaps amounts to a stupid mistake: I didn't use an overall parent layout for the entire window, but hacked it with a couple of smaller layouts that I therefore have to move about and resize individually. See the Qt Designer screen (the red rectangles are the sole layouts): .
What is happening is that in the frame to the right, I am playing a video clip that can be of various resolutions. I want the frame to resize depending on this resolution, which also means that the buttons and window have to move/resize accordingly. That is where the window resize comes in. I'm sure there is a more elegant solution than what I am doing here, but I am trying to handle several other scenarios here and hence the lack of quality of code.
The result is that when I load a clip, the window attempts to resize, but does so badly; the following is the result:
If the window is dragged, it 'pops' into its correct size; in the meantime, however, it just looks ugly.
A couple further questions: do you use the Qt Designer to design your UIs? I found that programmatically you can achieve much better control of your interfaces. One thing which I could not do in the designer was to have a layout parented by the main widget, i.e. the equivalent of having the following bit of code:
QVBoxLayout* layout = new QVBoxLayout;
this->setLayout(layout);
A layout placed in the designer always seems to create this 'layoutWidget' subwidget, which the layout you placed is then parented to. Any way around that?
We use a mix of designer and code to create layouts, the Qt layout system can be very unintuitive at times. But I would probably not layout a full series of tabs in one designer ui file, i would make each tab each own widget and then assemble them either through code or in the designer by promoting to custom classes. This gives you better separation of responsibilities, by putting all the functionality of all the tabs into one file you almost guarantee a large unwieldy class.
When a widget has child widgets in designer you can assign a layout to it by adding it from the context menu. Make sure nothing is selected and click on the background of the widget in which you want to create a layout, select the layout and all of the widgets children will be assigned the layout.
What does help is creating hierarchies of layouts. Looking at your first screenshot, i would probably use a vertical layout with spacers on top and bottom for the items on the right, an horizontal layout with spacers left and right for the button bar and a grid layout for all the items together. Without the spacers your items will extend when the window grows. The spacers will let you control the behavior under resizing better.
you are calling setMinimumSize(). That's fine, but you should also call resize()

Displaying a popup widget in QT over application border

Let's say that I have an application frame, and I want to show a popup QCalendarWidget over on the right side of the frame. Normally, QT will clip the edges of the QCalendarWidget, cutting it in half and not displaying the rest, as it would be over the right side border.
Is there a way to work around this limitation without resorting to implementing a QDialog?
I want the widget to be visible outside the bounds of it's container.
If you'd show your Calendar, let's say, after a button click, as QDateTimeEditor does, it's contents will not be clipped, cause it do not belong to frame. It will be just a widget, that shows in a dialog manner. And maybe you should even place it in QDialog, that is modal and provides some convenience methods, rather then simple QWidget.
Btw, why don't you want to use QDatetimeEditor?