robby987
robby987

Reputation: 827

Qt Resizing a window to fit an aspect ratio in a scroll area issue

I've made a preview object using Qt which is a container that has the screen widget inside it. In order to make its aspect ratio correct, when the width of the screen is changed the height also needs to be changed.

This causes a problem as the screen is inside of a scroll area, when its height goes beyond a certain point the scroll bar comes in. This reduces the width and therefore the height needs to be reduced, this can cause a loop where the scroll bar keeps coming in and out.

One way I have tried to fix this is taking the required size and averaging over a number of iterations of the function that is responsible for working out and setting the size, if the average is not significantly different from the required size the size will not change. This has sort of fixed the problem but seems to me less than optimal...

I wondering if anyone has an idea of how to fix this issue?

//********************************************************************************
/// \brief Called to make the size of the preview pane the correct size
void PreviewDisplayWidget::SetSizeOfScreen()
{
  double aspect_ratio = _preview_controls->_video_settings.getVideoFormat().GetAspectRatio();

  // Calculate the new minimum size
  int minimum_size = _container->width()/aspect_ratio;

  // HACK TO FIX ISSUE WITH RESIZING:
  // The preview sets its height from the width, if the width is changed, so will the height.
  // This causes an issue with the scroll area as it can be in a situation that will cause the
  // scroll area to get thinner (due to scroll bars being added), causing the width of the widget
  // to change, therefore causing the height to change. Which can be enough to make the scroll bar go
  // away. This can loop and cause a stack overflow.
  //
  // Store the last 10 sizes.
  _previous_sizes.push_back(minimum_size);

  const int sizes_to_scan = 10;
  if (_previous_sizes.size() > sizes_to_scan)
  {
    _previous_sizes.pop_front();
  }

  int sum = 0;
  for (auto i =_previous_sizes.begin(); i != _previous_sizes.end(); i++)
  {
    sum += *i;
  }

  double average = (double) sum / (double) _previous_sizes.size();

  std::cout << "Average " << average << std::endl;

  bool change_in_average = false;
  // Significant change in average means a size change should occur
  if (average > minimum_size + 5 || average < minimum_size - 5)
  {
    change_in_average = true;
  }


  if (change_in_average || _previous_sizes.size() < sizes_to_scan - 1)
  {
    _preview_frame->setMinimumHeight(minimum_size);
    std::cout << "Preview sizes " << minimum_size << std::endl;
    _preview_frame->updateGeometry();
  }

  SetPreviewSize();
}

Upvotes: 3

Views: 511

Answers (1)

Vinod Paul
Vinod Paul

Reputation: 359

Will this work?

int minimum_size;

if(scrollArea->verticalScrollBar())
minimum_size = (_container->width()+scrollArea->verticalScrollBar()->width())/aspect_ratio;
else
minimum_size = _container->width()/aspect_ratio;

Upvotes: 1

Related Questions