Qt widget displayed over other widgets - qt

I have some information/notification widget that should be displayed when some even occurs. My idea was to have a widget that is hidden in top left corner and would be shown when needed. Problem is that if I just put there simple widget and show it, everything will be moved to the right, what I want is to show that widget on top anything that's in that area (it will hide what's there, but that's ok).
I can't use stacked widget, because information widget is in different dimensions then other widgets there. And if I just create floating widget and move it to that area it wont move if main window is moved.
Is there any way how to do that?

Just create and place the widget on the fly. Avoid using UI to place the widget because then the widget position is managed by the layouts.
EDIT: Remember to create the widget after of the dialog's initialization. If you don't take care about this your widget will be inserted at the bottom.
class Dialog : public QDialog
{
Q_OBJECT
std::unique_ptr<Ui::Dialog> _ui;
QWidget* _widgetOnTheTop;
public:
Dialog(QWidget* parent)
: QDialog(parent), _ui(new Ui::Dialog)
{
_ui->setupUi(this);
_widgetOnTheTop = new QPushButton(this);
_widgetOnTheTop->setGeometry(10,10,100,35);
_widgetOnTheTop->show();
}
};

Look at QDialog create and exec one of them when your error occurs, you can construct them to have the default ok cancel buttons
EDIT: Sorry i mean QMessageBos, see code below
QMessageBox error_message(QMessageBox::Icon::Critical, "Title of the window","Some Text about the error to show the user", QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::Cancel), this);
error_message.exec();

Related

Qt ScrollArea on widget messes up size and position of widget [Qt 5.1]

I'm new with Qt and I want to implement a scrollable widget which can grow dynamically, e.g. by adding buttons into it when another button is pressed. I try to implement it using the following layout and code:
scrollArea = new QScrollArea(ui->outerWidget);
scrollArea->setWidget(ui->innerWidget);
layout = new QVBoxLayout(ui->outerWidget);
ui->innerWidget->setLayout(layout);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// code for PushButton to add buttons in innerWidget
void MainWindow::on_pushButton_clicked()
{
QPushButton *button = new QPushButton("button"+QString::number( nameCounter ));
nameCounter ++;
ui->innerWidget->layout()->addWidget(button);
}
This implementation has two problems when I run the program, first the innerWidget appears out of place (I define its position in Qt Creator's Design mode) and second after many widgets are added in the layout the scroll bar is doesn't grow, but instead the widgets are become smaller to fit into the layout:
In another thread it was suggested to set widgetResizable to true:
scrollArea->setWidgetResizable(true);
The scroll bar seems to work now but the new problem is that the innerWidget becomes very small so it is barely visible:
So, how can I achieve a scrollable widget that will respect the size and position of the design?
have no environment to verify but good luck.
to place scrollArea the target position,
Manually call SetGeometry, or
Place a QScrollArea in ui form, (suggested if it's static), or
Place a widget in your target position, and set QScrollArea's parent to it, and add QScrollArea to its layout, and Set QScrollArea to be expanding.
manually create a QWidget innerWidget and assign it to scrollArea via QScrollArea::setWidget(*QWidget), try different size policy to innerWidget, such as "Preferred".
Also be aware of Qt's reference mentioned : void QScrollArea::setWidget ( QWidget * widget )
Sets the scroll area's widget.
....
Note that You must add the layout of widget before you call this function; if you add it later, the widget will not be visible - regardless of when you show() the scroll area. In this case, you can also not show() the widget later.
Above list solutions, below are reasons to the problems you mentioned:
scrollArea->setWidget(ui->innerWidget); Setting a widget to ScrollArea will change the parenting and layouting of ui->innerWidget, so the geometry values written in ui form (in Qt Creater) will no longer take effect, this is the reason of innerWidget out of place. ui->innerWidget is no longer a child of outerWidget, it's geometry will follow its new parent (but not scrollArea, there's some tricky layouting inside QScrollArea". To be clear, innerWidget is not helpful to locate scrollArea in such scenario.
In your first clip of code, widget 'scrollArea' is created with parent outerWidget, again no size policy or layout or geometry is specified, so scrollArea will by default be placed at the left top corner of the parent "outerWidget". To place scrollArea to your target geometry, you can " set geometry manually " or " assign innerWidget as scrollArea's parent and expand scrollArea". Obviously the latter method cannot assign ui->innerWiget to scrollArea->setWidget().
scrollArea->setWidgetResizable(true); makes the scrollArea "shrink" at left top corner of outerWidget. This is because, QScrollArea does not increase along with it's contents, it can scroll to display all of it contents so the required size of QScrollArea can be as small as possible. Once the 'Resizable' property is set to "true", QScrollArea decides to shrink to its minimum necessary size, thus the size to display its scroll bar and scroll buttons....

QT: two layouts add the same widget

In Qt: I create a widget-ui class, and I want to make the widget appear in two different layouts in two separate base widget(or window). So I want to:
widget_based_class* inside = new widget_based_class(base_widget1);
QHBoxLayout *lay1=new QHBoxLayout(base_widget1);
base_widget->setLayout(lay1);
lay1->addWidget(inside);
base_widget1.show();
-------------------------------
base_widget1.hide();
QHBoxLayout *lay2=new QHBoxLayout(base_widget2);
base_widget->setLayout(lay2);
lay2->addWidget(inside);
base_widget2.show();
How cound I achieve this? (My program is more complicated, and I didn't see the code work.)
Tank you.
A QWidget has only one parent widget and only one geometry (position and size) in that parent. Every call of QLayout::addWidget() will reparent that widget to the widget, the layout is installed on.
Your second call of setLayout won't work as expected, because you have to delete the the existing layout manager before setting the new one:
delete base_widget->layout();
base_widget->setLayout(lay2);
If base_widget hasn't already got a layout manager, the layout manager lay2 would simply be reparented.
If the widget will never be displayed twice on the screen, I don't see why you can't reparent it by addWidget/removeWidget.
In the OP, the parent widget/window is always hidden before the other one is shown. addWidget is called on the fly. We should also call removeWidget on the fly. It should be possible to move the widget around.
widget_based_class* inside = new widget_based_class(base_widget1);
QHBoxLayout *lay1=new QHBoxLayout(base_widget1);
base_widget->setLayout(lay1);
lay2->removeWidget(inside); // remove widget from other layout
lay1->addWidget(inside); // add widget to this layout
base_widget1.show();
-------------------------------
base_widget1.hide();
QHBoxLayout *lay2=new QHBoxLayout(base_widget2);
base_widget->setLayout(lay2);
lay1->removeWidget(inside); //remove widget from other layout
lay2->addWidget(inside); // add widget to this layout
base_widget2.show();
Make one widget and use a pointer in each layout?

Qt : event invisible widget?

For some reasons, I need to draw a widget onto one another.
The structure is the following (see the image) :
I have an original QTableWigetItem
On the QTableWigetItem, I create a QWidget at the foreground with the same geometry
This QWidget contains a QBoxLayout
This QBoxLayout contains a QPixmap and a QComboBox
I want to do the following things :
The QWidget is just a "container" for my QBoxLayout and I would like to set him completely "invisible" for the user. If the user click or move at the position of the widget, I want the event of the QTableWigetItem in the background to be trigerred. But the problem is that I want the QPixmap and the QComboBox to be at the foreground, visible and "normal". For me it's just a trick to be able to put children widgets in a QTableWidget of a HeaderView.
How to make the QWidget "completely invisible" (from the event/signals point of view) ?
Thank you very much.
Try QWidget::setWindowOpacity(0)

How does QWidget size when used as a window?

Several examples on trolltech use QWidget rather than a QMainWindow as the main window for simple Qt applications.
Now I need just a simple window with a single content widget (QGlWidget) that covers the entire client area.
However, when I show a QWidget window with a single content window it automatically resizes itself to be tiny.
If I create the QWidget parent window without a child It is a nice large default size.
I don't want to resort to using Layouts for a single child window :/
What I understand is that you use a QWidget to display your QGIWidget. Try calling the show method of your QGIWidget directly (if your QGIWidget class inherits QWidget), Qt will create the window decoration for you.
Otherwise if you really need your widget to be inside one another, and fit its size, you'll have to use a layout.
Either follow gregseth's advice or you can simply resize the widget yourself.
(though this way you'll loose nice auto-resizing which is provided by Qt when you use layouts)
In your case you can basically do something like:
QGlWidget* myWidget = new QGlWidget;
myWidget->resize(QApplication::desktopWidget()->availableGeometry().size());
// or maybe instead of resizing show it in fullscreen:
myWidget->showFullScreen();
(actually I don't remember if showFullScreen() will do resizing for you, maybe you'll need both resize+showFullScreen :))
Cheers :)
P.S. Using layout is actually an option. It's not expensive and it's flexible. All it gets: "layout = new QVBoxLayout(myWidget); layout->addWidget(myWidget);" and you're done :)
Not always.
I've found that a QMainWindow will not work as the parent widget when using the QVBoxLayout and QHBoxLayout to arrange child widgets.
If you create a QWidget and use that in place of the QMainWindow then the layouts will work correctly.
QWidget* centralWidget = new QWidget( MainWindow );
MainWindow->setCentralWidget( centralWidget );
If you use QtCreator and look at the code it creates you can see it creating a 'hidden' widget if you try to use the layouts directly at the top level.
It's not obvious, intuitive, or documented anywhere that I've found.

QT4: Is it possible to make a QListView scroll smoothly?

I have a QListView in Icon mode with lots of icons, so that a scrollbar appears, but the scrolling is not smooth and this IMHO confuses the user since it jumps abruptly from one point to another at each scroll. I would like to make the scrolling smooth but I didn't find anything in the docs. Is it possible?
Maybe QListView.setVerticalScrollMode(QAbstractItemView::ScrollPerPixel)
If I understand your question correctly you would like to redefine the scrolling behavior of the widget. I guess what happens is that listview is getting scrolled by the item's height whenever users hits a scroll arrow (marked as b on the image below).
For a vertical scroll bar connected to a list view, scroll arrows typically move the current position one "line" up or down, and adjust the position of the slider by a small amount. I believe line in this case it is an icon's height. You can adjust items height by installing and item delegate (setItemDelegate) and overriding its sizeHint method. Though this would not help you to solve this problem. What you could try is to create a QListView descendant and override its updateGeometries method. There you can setup the vertical scrollbar step to the value you want, I guess 1 or 2 for this task. Below is an example of the custom listview:
class TestListView : public QListView
{
Q_OBJECT
public:
explicit TestListView(QWidget *parent = 0);
protected:
virtual void updateGeometries();
};
TestListView::TestListView(QWidget *parent) :
QListView(parent)
{
//???
}
void TestListView::updateGeometries()
{
QListView::updateGeometries();
verticalScrollBar()->setSingleStep(2);
}
hope this helps, regards
I have a QlistWidget* in ui->barra_scroll and I feel very smooth with this.
QScrollBar *qsb = ui->barra_scroll->verticalScrollBar();
qsb->setSingleStep(5);

Resources