I have been messing with this problem for hours, and decided it's time to ask SO :)
I have a Qt program that rotates an image and then updates the size of the widget. Here is the code I'm using to do this currently.
void VideoSubWindow::showFrame(const QImage& frame)
{
QPixmap pixmap = QPixmap::fromImage(frame);
ui->videoFrameLabel->setPixmap(pixmap);
resizeWidgets(pixmap.size());
}
void VideoSubWindow::resizeWidgets(const QSize &size)
{
if(frameSize != size)
{
frameSize = size;
ui->videoFrameLabel->setFixedSize(size);
ui->scrollArea->setMinimumSize(size.width() + 2, size.height() + 2);
}
}
The widgets are structured as follows:
VideoSubWindow (QMainWindow)
-> centralWidget (QWidget) (Vertical layout is set on this)
-> scrollArea (QScrollArea)
-> videoFrameLabel (QLabel)
-> statusBar (QStatusBar)
-> menuBar (QMenuBar)
When the code above is executed, like rotating the image 90 degrees, the image will be rotated, but the window doesn't resize to fit the new pixmap size. I have tried to call adjustSize() and updateGeometry() on SubWindow and centralWidget, but those seem to have zero effect. But, if I manually resize the window with my mouse, the window snaps to the minimum size that was set for the scrollArea, so that seems to be taking effect.
Does anyone have experience with this? Thanks!
Try with the resize(...) function : Qt documentation
adjustSize() used sizeHint() function, so calling adjustSize() on SubWindow and centralWidget cannot have any effet
Related
I have a simple application. In MainWindow's constructor I have:
_someWidget = new someWidgetClass(this);
_someWidget ->setFixedSize(700,700);
_someWidget ->move(50,50);
wid = new QWidget(this);
wid->move(800,800);
wid->setFixedSize(100,100);
centralWidget()->adjustSize();
adjustSize();
I would like to resize MainWindow like that, his right bottom corner should be the right bottom corner of the wid, so I would like to resize MainWindow to his contents. But adjustSize doesn't work.
I tried to add sizeHint() method in someWidgetClass and return his size, but this doesn't help too.
you should set one layout for centralWidget , For Example, I test it with QGridLayout. then add your widget in that layout :
auto _someWidget = new QWidget(this);
_someWidget->move(50, 50);
_someWidget->setFixedSize(700, 700);
centralWidget()->layout()->addWidget(_someWidget);
auto wid = new QWidget(this);
wid->move(800, 800);
wid->setFixedSize(100, 100);
centralWidget()->layout()->addWidget(wid);
centralWidget()->adjustSize();
adjustSize();
about adjustSize Function :
Adjusts the size of the widget to fit its contents. This function uses
sizeHint() if it is valid, i.e., the size hint's width and height are
>= 0. Otherwise, it sets the size to the children rectangle that covers all child widgets (the union of all child widget rectangles).
For windows, the screen size is also taken into account. If the
sizeHint() is less than (200, 100) and the size policy is expanding,
the window will be at least (200, 100). The maximum size of a window
is 2/3 of the screen's width and height.
I'm very new to Qt and trying to create application, that includes main window, QDockWidget and a button.
Suppose my main window has 1280 x 720 resolution. Then I want to implement QDockWidget that pop up from the left side, width of dockWidth and height of 720 without windowTitleBar. The button has size of (buttonWidth, 720). At first its hidden, and only the button is present, when we click the button dock pops up, button changes position to the right edge of dock.
Here is my code:
window::window(unsigned int h, unsigned int v, QWidget *parent) {
this->setFixedSize(h, v);
ui.setupUi(this);
createDockWindow();
}
void window::createDockWindow() {
dock = new QDockWidget(this);
dock->setTitleBarWidget(new QMainWindow());
dock->setGeometry(QRect(this->rect().topLeft(),
QSize(dockWidth, this->height())));
dock->setFloating(true);
dock->hide();
path_button = new QPushButton(">", this);
path_button->setGeometry(QRect(this->rect().topLeft(),
QSize(buttonWidth, this->height())));
connect(path_button, SIGNAL (released()), this, SLOT (showDock()));
}
void rubrick::showDock() {
if(dock->isHidden()){
dock->show();
path_button->setGeometry(QRect(dock->rect().topRight(),
QSize(buttonWidth, this->height())));
} else {
dock->hide();
path_button->setGeometry(QRect(dock->rect().topLeft(),
QSize(buttonWidth, this->height())));
}
}
So button works perfectly, at first my app looks like that screenshot:
But when the dock shows, it blocks app window title bar, like that: screenshot
I figured, this->rect().topLeft() returns top left of screen, but doesn't take into consideration window Title Bar, I tried to get menuBar height, but it return 30, and I found out that if I move left top by (0, 45) with 0 being width and 45 being height, the dock would be perfectly in place.
What am I doing wrong and how to fix that problem?
The method you're probably looking for is QWidget::frameGeometry, which returns the geometry of the window with the frame included. The rect method returns only the internal area. If you look at QWidget::rect in Qt Assistant, you'll find a link to a "Window Geometry" description that explains all of these interactions reasonably well.
I can get a border to display on my QLabels just fine:
But when I try to display a pixmap in them, the border goes away:
I set the frame properties in the constructor of my QLabel subclass:
ObjectSlot::ObjectSlot(int index) {
setIndex(index);
setFrameShape(QFrame::StyledPanel);
setFrameShadow(QFrame::Raised);
setLineWidth(3);
setMidLineWidth(3);
setAlignment(Qt::AlignCenter);
return;
}
The pixmap is set in the paintEvent:
void ObjectSlot::paintEvent(QPaintEvent* event) {
QPixmap* image = new QPixmap("://images/Box.png");
setPixmap(image->scaled(width(),height(),Qt::KeepAspectRatio));
QLabel::paintEvent(event);
}
Why does the border go away? Why is life so cruel?
As doc said:
Setting the pixmap clears any previous content. The buddy shortcut, if
any, is disabled.
So it seems that it is impossible, but I found next solution, you shouldn't setPixmap(), you need just drawPixmap() when all correct label was painted:
void ObjectSlot::paintEvent(QPaintEvent *e)
{
QLabel::paintEvent(e);
//label painted
QPainter p(this);
QPixmap image("G:/2/qt.png");
p.drawPixmap(QPoint(1,1),image.scaled(100,100,Qt::KeepAspectRatio));
}
Result:
Not the best solution because you should adapt it to your purposes, but currently better than nothing.
I'm trying to use dock widgets on the main window class in Qt5. However, when I set the central widget to have a fixed height Qt has trouble docking the windows to the top or bottom. Basically, it looks like there is some "padding" or "margins" above and below the central widget. If I set an auto height on the widget, the docking works fine all they way edge-to-edge (top/bottom). How can I either remove the margins or enable the docking function while using a fixed height central widget?
See screenshots for example.
Dock Right w/ Auto Height (No Margins on Central Widget)
Dock Bottom w/ Auto Height (No Margins on Central Widget)
Dock Bottom w/ Fixed Height (Margins/Padding--Grey areas, won't dock)
Here is the code if that helps.
Header:
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QString);
~MainWindow();
private:
void createDockWindows();
QListWidget *m_dock_list;
QString m_directory;
QWidget *m_mainWidget;
};
Class definition:
MainWindow::MainWindow(QString program)
: m_directory(".")
{
m_mainWidget = new QWidget;
m_mainWidget->setFixedHeight(156);
m_mainWidget->setStyleSheet("background-color: blue;");
createDockWindows();
// set central widget and default size
setCentralWidget(m_mainWidget);
}
// dock functions
void MainWindow::createDockWindows()
{
QDockWidget *dock = new QDockWidget(tr("Dock List"), this);
dock->setAllowedAreas(Qt::LeftDockWidgetArea |
Qt::RightDockWidgetArea |
Qt::BottomDockWidgetArea);
m_dock_list = new QListWidget(dock);
m_dock_list->addItems(QStringList()
<< "item 1"
<< "item 2"
<< "item 3"
<< "item 4");
dock->setWidget(m_dock_list);
addDockWidget(Qt::RightDockWidgetArea, dock);
}
In case anyone else tries to figure out this behavior, here is what I've found. The top and bottom margins are just Qt trying to place the fixed size widget into a space larger than the widget (obvious). However, the restricted docking ability results from the docking widget having a minimum vertical size. Thus, when window height < central widget height + min(docking widget height) Qt does not allow the dock function. Once the threshold window height is reached (by user resize) then Qt allows the dock function.
I would prefer if the docking feature occurred regardless of window height with an automatic window resize to accommodate the docking window.
Solution using signals
Arguably a bit hacky, and may be hard to maintain if you have a complex layout. But for my use case, this is workable.
Don't enforce the size on the center widget, let it auto-fill the main window.
When the dock changes location it emits the dockLocationChanged. We can auto-size the main window if the dockable window is moved into target location. For my case this is the bottom.
Code:
void MainWindow::createDockWindows()
{
...
QObject::connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)),
this, SLOT(s_dock_window_resize(Qt::DockWidgetArea)));
}
// Autosize window slot on dock location change.
void MainWindow::s_dock_window_resize(Qt::DockWidgetArea area)
{
if (area == Qt::DockWidgetArea::BottomDockWidgetArea) {
// m_mainWidget_min_height is the height we would have enforced
// on the widget. Now we set it somewhere else and check it here.
int min_height = m_dock_list->height() + m_mainWidget_min_height;
if (min_height > MainWindow::height()) {
MainWindow::resize(MainWindow::width(), min_height);
}
}
}
I'm working on a basic image viewer/tagger that will need a thumbnail view to select an image. So far, I've used a QDockWidget enclosing a QScrollArea with a QHBoxLayout to contain a series of QLabels, each of which has its QPixMap set.
This seems very inelegant, and it only gets uglier to consider how I might implement auto-scaling of the thumbnails when the QDockWidget is resized. It's further complicated by the additional need to resize the thumbnails when the scroll bar appears and disappears.
There must be a better way to do this?
I've ran into a similar problem when trying to animate resizing a qlabel with a qpixmap. The method I found that worked best was to use a QWidget instead and re-implement the paintEvent function. Then your QWidget image will automatically be scaled if it's resized. Here is an example:
In my case I had the private variables in a private object called private_:
bool image_set_;
QImage image_;
QBrush paintbrush_;
void MyClass::paintEvent( QPaintEvent* event )
{
// if the QWidget has an image set, then we use our custom painting.
if( this->private_->image_set_ )
{
//I've made it so that my QWidget has a 1px white border
this->private_->paintbrush_.setTextureImage( this->private_->image_.scaled(QSize( this->width() - 2, this->height() - 2 ) ) );
QPainter painter( this );
QRect temp_rect = QRect( 1, 1, this->width()-2, this->height() - 2 );
painter.fillRect( this->rect(), Qt::white );
painter.fillRect( temp_rect, this->private_->paintbrush_ );
}
else
{
QWidget::paintEvent( event );
}
}