How can i move the QWidget in QGraphicsView? - c++

I want to move the QPushButton or kind of QWidget in QGraphicsView for example QListWidet, QTableWidget etc.
So, I used QGraphicsProxyWidget.
Then I clicked the widget and drag. But It is not moving.
How can i move QWidget?
This is my code.
ui->graphicsView->setGeometry(0,0,geometry().width(),geometry().height());
scene = new QGraphicsScene(0, 0, geometry().width(), geometry().height(), this);
ui->graphicsView->setScene(scene);
btn =new QPushButton(NULL);
QGraphicsProxyWidget *proxy = scene->addWidget(btn);
proxy->setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsSelectable);
scene->addItem(proxy);
Can you tell me What is wrong?
Thanks.

Cause
In your case you cannot move the button, because although you have made the proxy movable, the button handles the mouse input differently in order to implement its clicked functionality. In other words, on a mouse press, how could a move action be differentiated from a click action?
Solution
My solution would be to make the button part of a somewhat bigger QGraphicsRectItem. The latter will serve as a draggable handle, i.e. if the user interacts with the button - it clicks, but if the other portion of the QGraphicsRectItem (not covered by the button) is interacted with, the button could be moved around.
Example
Here is an example showing exactly how to do that:
auto *item = new QGraphicsRectItem(0, 0, 75, 40);
auto *proxy = new QGraphicsProxyWidget(item);
auto *btn = new QPushButton(tr("Click me"));
btn->setGeometry(0, 0, 77, 26);
item->setFlag(QGraphicsItem::ItemIsMovable);
item->setBrush(Qt::darkYellow);
proxy->setWidget(btn);
proxy->setPos(0, 15);
proxy->setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsSelectable);
scene->addItem(item);
Note: To make this work it is important to set the parent of proxy to item.

Related

Qt window resize event after resize is done

I have a QtChart in a QDialog and I use a simple QWidget to show it on the screen. I need to resize this hart whenever the dialog window is resized by user.
This is how I add the chart to the dialog (in constructor):
// Setup chart view to show the chart
mChartView = new QChartView(mChart, ui->widget);
mChartView->setParent(this);
mChartView->resize(ui->widget->size());
mChartView->setRenderHint(QPainter::Antialiasing);
I have overrided the resizeEvent of the QDialog in my own dialog:
void CurveDialog::resizeEvent(QResizeEvent *event)
{
mChartView->resize(ui->widget->size());
}
This works, and the chart gets resized...but the problem is it is terribly slow! because it will resize for all the steps that user drags the window corner to resize it!
How can I do the resize only when there resize is done? I wanted to use a timer but this looks like a dirty hack! any better ideas?
Qt provides a layout system to manage the geometries of child widgets within a widget. A layout will arrange the size and the position of each child to ensure that it will take all the available space.
The layout will automatically resize the child widgets when the parent is resized:
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QDialog* dialog = new QDialog();
QVBoxLayout* layoutDialog = new QVBoxLayout(dialog);
QWidget* widget = new QWidget();
QVBoxLayout* layoutWidget = new QVBoxLayout(widget);
layoutDialog->addWidget(widget);
layoutWidget->addWidget(chartView);
dialog->exec();

Qt5: QPushButon size setting

it's a bit frustrating, but I can't find proper way to set QPushButton size. From what I read I suppose that this code should work:
// SEND BUTTON
sendButton = new QPushButton(this);
sendButton->setText("Send");
sendButton->setMinimumSize(QSize(0,0));
sendButton->setMaximumSize(QSize(10000,10000));
sendButton->setGeometry(QRect(QPoint(30, 100),QSize(10, 20)));
connect(sendButton, &QPushButton::released, this, &MainWindow::handleSendButton);
// CENTRAL WIDGET
QWidget* centralWidget = new QWidget(this);
centralWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
// LAYOUT
QGridLayout* layout = new QGridLayout(centralWidget);
layout->addWidget(sendButton,0,0,0,0);
But the button is always expanded to the whole application window. Could you please help?
The policies that the Widgets have by default is QSizePolicy::Preferred, but in your case you should use QSizePolicy::Fixed.
QSizePolicy::Preferred: The sizeHint() is best, but the widget can be
shrunk and still be useful. The widget can be expanded, but there is
no advantage to it being larger than sizeHint() (the default QWidget
policy).
QSizePolicy::Fixed: The QWidget::sizeHint() is the only acceptable
alternative, so the widget can never grow or shrink (e.g. the vertical
direction of a push button).
In addition you must establish the alignment to be centered, so that from the above you get the following:
sendButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
layout->addWidget(sendButton,0,0,0,0, Qt::AlignCenter);

In QT "ui->scrollArea->horizontalScrollBar()->setValue(0)" has no effect

So in my UI designer I have a ScrollArea Widget, I then in my MainWindow.cpp, I create a QGraphicScene and a QGraphics View. I create a new widget and give that widget a QVBoxLayout so that it will auto-size(which is correct to my understanding).
I then use ui->scrollArea->setWidget(widget); to make this new widget the child of my scrollView.
All of this seems correct because I have scroll bars that I can navigate my scene with. However; using the line ui->scrollArea->horizontalScrollBar()->setValue(0); still has no effect on the scroll bar values.
scene = new QGraphicsScene();
scene->setSceneRect(0,0,2500,2500);
view = new QGraphicsView(scene);
QWidget *widget = new QWidget;
view->setBackgroundBrush(Qt::white);
QVBoxLayout* bLayout = new QVBoxLayout(widget);
ui->scrollArea->setWidget(widget);
bLayout->addWidget(view);
widget->show();
ui->scrollArea->horizontalScrollBar()->setValue(0);
ui->scrollArea->verticalScrollBar()->setValue(0);
I just had the this problem. Then, after debugging with ui->scrollArea->verticalScrollBar()->value() I realized that the scrolling area has no size before the component is show on the screen, i.e., it does not change the scrolling because it is not visible yet.
This is a sample Python code, but the is the same for C++, except the Language Syntax.
from PyQt5.QtWidgets import QDialog
...
dialog = QDialog()
...
verticalScrollBar = dialog.QPlainTextEdit.verticalScrollBar()
horizontalScrollBar = dialog.QPlainTextEdit.horizontalScrollBar()
# Has no effect, if you print the values, you will see always 0
verticalScrollBar.setValue( horizontalScrollBar.maximum() )
horizontalScrollBar.setValue( horizontalScrollBar.minimum() )
dialog.show()
# Now it has effect
verticalScrollBar.setValue( horizontalScrollBar.maximum() )
horizontalScrollBar.setValue( horizontalScrollBar.minimum() )
Autoscroll PyQT QTextWidget
If you are sure to address the correct scrollbar (as pointed in the comments by thuga), maybe check if your scroll area is modified after that init. I mean I'm not sure of the bahaviour, but if you modified some text in your widget for example, I think the scrollbar will be impacted.
You may need to catch some of your widget's event to reapply those:
ui->scrollArea->horizontalScrollBar()->setValue(0);
ui->scrollArea->verticalScrollBar()->setValue(0);
If it doesn't help, you should try to debug by tracking scrollbar value with
ui->scrollArea->verticalScrollBar()->value()
and see if your set is well applied, and maybe when it is overriden
Just in case, you may also try some of the methods indicated here, but it's probably not relevant to your issue: setValue of ScrollBar Don't work at first time

How to make window look symmetric after adding buttons to taskbar?

I have QMainWindow and I want to populate statusbar with buttons.
I achieve this by using the code:
QWidget *widget = new QWidget();
QPushButton *leftBut = new QPushButton("left");
QPushButton *rightBut = new QPushButton("right");
QHBoxLayout *layout = new QHBoxLayout(widget);
layout->addWidget(leftBut, 1, 0);
layout->addWidget(rightBut, 1, 0);
statusBar()->addWidget(widget,1);
so, I have this: MainWindow with buttons in statusbar
But you can see that right border of layout are far from window corner, not like on the left side.
What I want is to make window look symmetric (move right border right or make borders invisible or something else).
What was needed is this string after those code that I wrote in question:
statusBar()->setSizeGripEnabled(false);
In some reason statusbar contains "size grip" that is situated in bottom-right corner of statusbar and is enabled by default. That wast the thing that prevent widget to fill whole space.

QGraphicsItem::SetCursor Won't Deselect

All,
I have a QGraphicsEllipseItem with setFlags(Qt::ItemIsSelectable | Qt::ItemIsMovable). This allows me drag and move ellipses quickly in a QGraphicsView.
I decided to be fancy, and setCursor(Qt::OpenHandCursor) to let the user know they can move it by clicking. However, now it won't let go when I let go of the left mouse button? What am I doing wrong?
Example code: Custom QGraphicItem and Repaint Issues
Note: I removed the update() calls, and added prepareGeometryChange() calls.
Now modify the MakeNewPoint function:
QGraphicsEllipseItem * InteractivePolygon::MakeNewPoint(QPointF & new_point)
{
QGraphicsEllipseItem * result = 0;
result = new QGraphicsEllipseItem();
result->setPos(new_point);
result->setRect(-4, -4, 8, 8);
result->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
result->setCursor(Qt::OpenHandCursor); //Setting this removes my ability to let go of an item. NOTE: result is parented by this.
return result;
}
later:
QGraphicsEllipseItem * new_item = MakeNewPoint(bla);
new_item->setParent(this);
//add it to my QList<QGraphicsEllipseItem *> m_points;
I would like to note that my QGraphicsEllipseItem is parented by a custom QGraphicsItem. I don't change the parents/Custom Item cursor, only the ellipse's. I do not experience this problem with non parented ellipses...
Interesting result: So my class custom QGraphicsItem class (the parent of the ellipses) is a QObject so I can filter incoming mouse events from the scene. I did a setCursor(Qt::ArrowCursor) in my custom class's constructor... and here's where it gets interesting:
The eventFilter now catches (event->type() == QEvent::GraphicsSceneMouseMove) even if a mouse button isn't pressed down. If I don't have the setCursor call, that event only fires while a mouse button is pressed... thoughts?
Okay got it, here's what's happening, it's intuitive once you realize it:
When you set that a QGraphicsItem to a unique cursor, the QGraphicsView has to setMouseTracking(true) otherwise the QGraphicsScene will never know when to change the cursor (ie when it's over the graphics item with the unique cursor.) The mouse move events were affecting my ellipse.
Normally, the QGraphicsScene only gets mouse move events when a button is held down.