ДК
25 мая 2020 г. 14:12

Disable autoscroll

Привет. Есть QTableView, когда обновляются данные от модели, verticalScroll меняет свое положение на самое верхнее. Как сделать так, чтобы скролл остался на том месте, на каком он был до обновления данных, если кол-во строк, конечно, позволяет?
Я пробовал делать так:

  1. qDebug() << "maxBefore: " << ui->_samples->verticalScrollBar()->maximum();
  2. const int sliderPos = ui->_samples->verticalScrollBar()->sliderPosition();
  3. auto conn = std::make_shared<QMetaObject::Connection>();
  4. *conn = connect(_samplesModel, &Models::SampleModel::rowsInserted, [&](){
  5. QObject::disconnect(*conn);
  6. qDebug() << "maxAfter: " << ui->_samples->verticalScrollBar()->maximum();
  7. ui->_samples->verticalScrollBar()->setSliderPosition(sliderPos);
  8. });

Проблема вся в том, что maxAfter всегда 0! и, поэтому, значение для позиции слайдера устанавливать смысла нет. Но в этот момент модель ведь уже имеет строки! Я уже всё перелопатил, не понимаю как решить пробелему. Нативного решения я так понимаю нет? Ставить какой-то таймер, ставищий паузу, пока этот скролл заимеет максимальное значение, конечно же, я не буду.
Если делать коннект на такой сигнал

  1. connect(_samplesModel, &QAbstractSlider::valueChanged...)

то, несмотря на то, что сигнал об изменении позиции (на 0, тк скролл в самое верхнее положение встанет) был принят, maximum слайдера всё-равно 0, хотя, строк уже полно, чтобы слайдер имел несколько позиций. Прошу хотя бы подсказать направление решения проблемы. Я бы написал делегат, да не понимаю на какие эвенты смотреть.

Дополню: хотел решить проблему так- насильно ставить максимальное значение для скролла. Потратил время, чтобы вычислить примерный коэффициент соотношения строк\слайдов. Но, если я делаю установку максимального кол-ва слайдов, а потом программно ставлю скролл в нужный мне слайд, то выесняется, что метод установки макс значения слайдов тупо не отрабатывает. Все-равно максимум 0! а строк то уже много на вьюхе!

  1. ui->_samples->verticalScrollBar()->setMaximum(maxSliders);
3

Вам это нравится? Поделитесь в социальных сетях!

4
Evgenii Legotckoi
  • 25 мая 2020 г. 15:21

Добрый день
Сдаётся мне, что проблема совсем в другом месте, поскольку обычно скролл как раз остаётся на месте.

У модели есть такие методы beginInsertRows, endInsertRows, beginRemoveRows, endRemoveRows, которые обычно вызывают при вставке и удалении строк. В эти методы добавляют индекс, с которого начинается вставка/удалени, а также от и до какой строки делается вставка и удалени.

Эти методы служат для управления View, чтобы как раз не возникало таких проблем как у вас.

То есть вам надо модель данных допиливать. Она же у вас кастомная, не так ли?

    ДК
    • 25 мая 2020 г. 15:37

    Модель от общей TreeModel, а она в свою очередь от QAbstract. Вьюха тоже дважды абстрактная, если так можно выразиться. Мне кажется вы указали верный путь- смотреть в работу модели. Тк с другими моделями подобное нормально отрабатывает. А может и вью, из-за абстракций лагает, попробую и её поменять на обычную. Не приходило таких мыслей раньше.

      МЛ
      • 26 мая 2020 г. 12:44

      Я так понимаю, речь идет о том, чтобы после обновления выделенная записб оставалась прежней, а не слетала на верхнюю. Тогда перед обновлением нужно запомнить индекс выделенной записи и после обновления стать на нее.

        ДК
        • 26 мая 2020 г. 13:24
        • (ред.)

        такие естественные решения все перепробовал.
        Получилось вчера так:

        1. const int maximumScroll = ui->_samples->verticalScrollBar()->maximum();
        2. const int sliderPos = ui->_samples->verticalScrollBar()->sliderPosition();
        3. auto conn = std::make_shared<QMetaObject::Connection>();
        4. *conn = connect(_samplesModel, &Models::SampleModel::dataReceived, [conn, this, sliderPos, maximumScroll](){
        5. QObject::disconnect(*conn);
        6. ui->_samples->verticalScrollBar()->setMaximum(maximumScroll);
        7. ui->_samples->verticalScrollBar()->setSliderPosition(sliderPos);
        8. });

        у нас просто есть свой сигнал у общей модели dataReceived (отрабатывает после endInsertRows() и endResetModel() ), вот с ним всё заработало. Короче, это внутренние проблемы, никак с Qt не связанные. А я грешил на баг какой-то.

          Комментарии

          Только авторизованные пользователи могут публиковать комментарии.
          Пожалуйста, авторизуйтесь или зарегистрируйтесь
          • Последние комментарии
          • Evgenii Legotckoi
            16 апреля 2025 г. 17:08
            Благодарю за отзыв. И вам желаю всяческих успехов!
          • IscanderChe
            12 апреля 2025 г. 17:12
            Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
          • AK
            1 апреля 2025 г. 11:41
            Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
          • Evgenii Legotckoi
            9 марта 2025 г. 21:02
            К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
          • VP
            9 марта 2025 г. 16:14
            Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…