Setting QMainWindow at the center of screen - c++

My QMainWindow contains a QGraphicsView, which should've minimum width and height. So, I've used the following code in the QMainWindow constructor:
ui.graphicsView->setMinimumHeight(VIEWWIDTH);
ui.graphicsView->setMinimumWidth(VIEWWIDTH);
Then I used following code to set QMainWindow at the center of the screen:
QRect available_geom = QDesktopWidget().availableGeometry();
QRect current_geom = frameGeometry();
setGeometry(available_geom.width() / 2 - current_geom.width() / 2,
available_geom.height() / 2 - current_geom.height() / 2,
current_geom.width(),
current_geom.height());
But it is not set at the center of the screen. If I omit setMinimumHeight() and setMinimumWidth() from QGraphicsView, then the main window is set at the center of the screen. How to overcome this problem? I'm using Qt 4.5.2.
Thanks.

The problem you are encountering is that Qt will delay many calculations as long as it can. When you set the minimum width and height of your graphics view, it sets a flag somewhere that the window the graphics view is in needs re-layed out. However, it won't do that until it has to... a few milliseconds before it is actually shown on screen. So, when you call rect() on your main window, you are getting the old rectangle, and not the new one.
My best recommendation is to extend the size change event in your main window, and adjust the positioning in that event. You may also have to flag when the window has actually been shown, so that you don't reposition the window if the user resizes it after it has been shown.
Alternately, you could try repositioning the window by extending the show event function and doing it there. It would probably happen before the user actually sees the window, but might flicker on occasion.

Related

How to control the positioning of the QSplashscreen?

I have an application which uses 3 splash screens in different scenarios. Problem is that I cannot seem to set a geometry or the positioning of these QSplashScreens. In fact, when the application size changes or the positioning of the application on the screen changes, the splash are displaying in random positions uncontrollably. How do I control that?
QSplashScreen inherited from QWidget and QWidget have move function. Use this function to change location of QSplashScreen
For example, splash.move(200, 200)

How can I make a QTextEdit widget scroll from my program

I have a QTextEdit widget with a vertical scroll bar.
report_text = new QTextEdit();
report_text->setAcceptRichText(true);
report_text->setReadOnly(true);
report_text->setTextInteractionFlags(Qt::NoTextInteraction);
report_text->setAlignment(Qt::AlignTop);
report_text->setWordWrapMode(QTextOption::NoWrap);
report_text->setFrameStyle(QFrame::NoFrame);
report_text->setMinimumSize(600, 380);
report_text->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
This is Qt 4.8 embedded.
Now I need a method or an event I can send to the widget to make it it scroll up or down just as if the up or down buttons on the scroll bar had been pressed.
I tried the scroll() method, but I scrolls the whole widget, including the scroll bar.
I also tried sending a QWheelEvent, but nothing happens.
QWheelEvent ev(QPoint(), 10, 0, 0);
report_text->setFocus();
QApplication::sendEvent(report_text, &ev);
What am I missing?
It is probable that the delta you provided is just way too small.
From the documentation of QWheelEvent::delta():
Returns the distance that the wheel is rotated, in eighths of a
degree. A positive value indicates that the wheel was rotated forwards
away from the user; a negative value indicates that the wheel was
rotated backwards toward the user.
Most mouse types work in steps of 15 degrees, in which case the delta
value is a multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
The text scrolling in Qt unit is the number of whole line. So if the widget computes that you want to scroll 0.9 lines, he might do nothing.
So try again with
QWheelEvent ev(QPoint(), 120, 0, 0);
Note: Nothing here apply to an event with control or shift modifier.
Here is what I found as a suitable solution:
The vertical scrollbar may be accessed using the QTextEdit::verticalScrollBar() method.
Scrollbars have a triggerAction() method to conveniently simulate user interaction with the buttons and the slider. The available actions are defined in QAbstractSlider.
So the resulting code is only a single line:
report_text->verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd);
Interestingly, this works even when the scrollbar is hidden with
report_text->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

Unwanted margin inside QGraphicsView with Scrollbars

I am developing a video player, using a QGraphicsView to display the video. The QGraphicsView is displaying a QGraphicsScene with a single QGraphicsPixmapItem which contains the current video frame. The background of the view is black.
As long as the frame is smaller than the view, everything is alright, the video frame is displayed in the center of the view and the rest of the view is black. When the view has the same size as the frame, only the frame is shown, (obviously) no background. When the video frame is greater than the view, scrollbars are shown so the user can scroll to see the other parts of the frame.
The problem: When the scrollbars are shown, it is possible to scroll past the video frame. There is a margin of 8 pixels on the bottom and on the right where the background is visible. If the video frame is greater than the view, there should be no background visible and it should not be possible to scroll past the video frame.
I reduced the problem to a short source code that demonstrates the problem, showing a 200x200 px red QPixmap in a QGraphicsView with green background.
#include <QtGui/QApplication>
#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
QPixmap pixmap(200, 200);
pixmap.fill(QColor(255, 0, 0));
QGraphicsScene scene(&window);
scene.addPixmap(pixmap);
QGraphicsView view(&window);
view.setBackgroundBrush(QColor(0, 255, 0));
view.setScene(&scene);
window.setCentralWidget(&view);
window.show();
window.resize(199, 199);
return app.exec();
}
I've also made an image of the problem (the black border isn't included in the example code): http://imgur.com/4X5eyhC
On the left window, the QGraphicsView has the same size as the rectangle, on the right window it is a little bit smaller, so scrollbars are shown. And also the background is visible (it should not be visible).
I already tried setting the sceneRect and various other attributes of QWidget, QGraphicsView and QGraphicsScene but found nothing that changed anything with the problem.
I also tried running the example problem in a virtual machine to exclude the possibility that my Qt/KDE version has a bug.
I have no idea why the background is suddenly shown when there are scrollbars. How can I get rid of that? If that is not possible, do you have an idea how I could work around that?
Thanks in advance.
Problem is a bug with QGraphicsView::fitInView() they don't care about: https://bugreports.qt.io/browse/QTBUG-11945
Instead of reimplementing your own fitInView, just remove the margins from the view when you create it.
view.setViewportMargins(-2, -2, -2, -2)
view.setFrameStyle(QFrame.NoFrame)
What you're seeing is the area of the Window beyond the QGraphicsView. You'll probably also find that you can resize the window and display more of the border.
To fix it, constrain the size of the window to the size of the QGraphicsView. As you've not set this in your example code, it would be the size of the pixmap.
So add these lines after declaring the window: -
window.setMaximumWidth(200);
window.setMaximumHeight(200);
Doing this will restrict the window from being resized greater than those values, so if you need to resize it beyond that, you'll need a larger QGraphicsView and QGraphicsScene.
I tried the snippet from the question but under Python using the PySide wrapper around Qt. The code is almost identical.
import sys
from PySide import QtGui
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
pixmap = QtGui.QPixmap(200, 200)
pixmap.fill(QtGui.QColor(255, 0, 0))
scene = QtGui.QGraphicsScene(window)
scene.addPixmap(pixmap)
view = QtGui.QGraphicsView(window)
view.setBackgroundBrush(QtGui.QColor(0, 255, 0))
view.setScene(scene)
window.setCentralWidget(view)
window.show()
window.resize(199, 199)
sys.exit(app.exec_())
The scroll bars appear but I don't see any green area!
I guess since it is only a wrapper around the QT library it might be a version or system dependent flaw/ not really intended behavior. It would be interesting to try it again with the current version of QT.
(My specs: Windows 7 64bit, Python 2.7.2 64bit, PySide 1.2.1 wrapping Qt 4.8)
This is really just this question in disguise - take a look and vote on https://bugreports.qt.io/browse/QTBUG-42331
In short, fitInView has hardcoded margins and this can cause all kinds of havoc - the least of which is that now you lose a few pixels of display area and might also force unnecessary rescaling.
ps. Make sure to select an answer
I fixed it creating my own fitInView() method. It is basically the same as the original QGraphicView method, except for the margins:
void MyClass::fitInView_fixed(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
{
if (!scene() || rect.isNull())
return;
auto unity = transform().mapRect(QRectF(0, 0, 1, 1));
if (unity.isEmpty())
return;
scale(1/unity.width(), 1/unity.height());
auto viewRect = viewport()->rect();
if (viewRect.isEmpty())
return;
auto sceneRect = transform().mapRect(rect);
if (sceneRect.isEmpty())
return;
qreal xratio = viewRect.width() / sceneRect.width();
qreal yratio = viewRect.height() / sceneRect.height();
// Respect the aspect ratio mode.
switch (aspectRatioMode) {
case Qt::KeepAspectRatio:
xratio = yratio = qMin(xratio, yratio);
break;
case Qt::KeepAspectRatioByExpanding:
xratio = yratio = qMax(xratio, yratio);
break;
case Qt::IgnoreAspectRatio:
break;
}
scale(xratio, yratio);
centerOn(rect.center());
}

Drag a rectangle over image in Qt

I guess there are lots of ways to achieve this. I have an application in which a video stream is shown over a custom QWidget that I have subclasses from QLabel, and painting frames using QPainter. Given that, is it possible to let the user to drag a rectangle over the image and retrieve the coordinates? The requirement is that the rectangle must be visible during the dragging.
Thanks in advance,
Have a look at QRubberBand. It allows you to place such a rect on top of e.g. a QLabel. The documentation also contains an example how to move and resize the rubberband using the mouse.
the QGraphicsView has the void setRubberBandSelectionMode ( Qt::ItemSelectionMode mode ) but i dont know if the QLabel has some similar feature ...
maybe you have to draw your own rectangle while the user drags the rectangle and catch it on mouserelease
soo long zai
In you widget you could track mouse pressed and released events and track where on the widget the corners of the selection rect are. For drawing the rectangle, I'd take a look at QStyle::drawFocusRect. I think the intent of that is to draw a rect you'd be able to see regardless of what's behind it.
Or perhaps try this:
QStylePainter painter(this);
QStyleOptionFocusRect option;
option.initFrom(this);
option.backgroundColor = palette().color(QPalette::Background);
painter.drawPrimitive(QStyle::PE_FrameFocusRect, option);

Qt - QGraphicsView without ScrollBar

I am trying to show a picture in it's full view using QGraphicsScene. But when ever I put the QgraphicsScene inside the QGraphicsView, I am getting a scroll bar. I tried so many ways But all are went to veins. So can anybody tell me how to obtain the full view without the scrollbar.
You might be getting scrollbars because the scene is larger than the usable area within the graphics view. By default, a QGraphicsView comes with a 1-pixel margin. To fix this, you can try:
QRect rcontent = graphicsView.contentsRect();
graphicsView.setSceneRect(0, 0, rcontent.width(), rcontent.height());
I had been getting scrollbars because I was manually setting the scene rect to the size of the graphics item I was adding -- which was as large as the QGraphicsView widget. I wasn't taking into account the margin.
QGraphicsView v;
v.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
v.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
To adjust the scrolling programmatically once these have been hidden, use one of the overloads of v.ensureVisible().