Arrow
Arrow11 апреля 2017 г. 4:48

Вопрос по QScrollArea и по созданию класса для доступа к его элементам по индексу.

Есть два вопроса:

Есть ли возможность в QScrollArea определить текущий видимый элемент, когда остальные скрыты.

И каким образом можно реализовать класс с функционалом QLabel, но с возможностью доступа к его элементам по индексу.

Чтобы было возможным обращение типа:

myClassVariable(i)->Text("text");
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

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

11
Evgenii Legotckoi
  • 11 апреля 2017 г. 13:15
  • Ответ был помечен как решение.

Если текущий элемент будет один единственный из видимых, то можно попробовать воспользоваться методом findChildren .

QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly);
for (QWidget * widget : widgets)
{
    if (widget->isVisible())
    {
        // ToDo Something
    }
}

Но это только в том случае, если другие элементы будут действительно скрыты, а не просто не видны из-за того, что выходят за область просмотра.

Если же вопрос идёт о тех виджета, который находятся в области просмотра, то можно поиграться с методом QScrollArea::childAt(int x, int y), который ищет дочерние виджеты по определённым координатам. Думаю, что это будет как раз то, что нужно. По идее под этими координатами должен будет находиться искомый виджет (если только не нужно будет делать трансляцию координат... тут вам в помощь методы mapTo , mapToGlobal , mapToParent )

Что касается вопроса QLabel , то не понятна суть вопроса. QLabel - это не контейнер, чтобы к его элементам по индексу обращаться. Можно конечно наследоваться от QLabel и определить кучку объектов, которые будут доступны по некоторому индексу, или скорее по некоторому enum , который будет перечислением индексов. Только зачем? . Да и выглядеть ваше предполагаемое обращение должно всё таки несколько иначе:

myClassVariable->at(i)->setText("text");

Оператор круглых скобок ради такого точно никто не перегружает, это просто нелогично и является довольно неочевидным решением для стороннего программиста, который будет не в курсе вопроса.

Так что вердикт такой, хотите некие индексы в QLabel и с функционалом QLabel, то наследуйтесь от этого QLabel, делайте метод at(), который будет возвращать указатель на объекты внутри QLabel, и у них уже реализуйте нужные методы. Но на мой взгляд вас куда-то не туда понесло, скорее всего всё должно быть в точности до наоборот.

    Arrow
    • 11 апреля 2017 г. 14:15

    Спасибо! Со QScrollArea буду пробовать выйти на нужный виджет.

    А насчет вопроса о QLabel, то похоже, что я действительно погорячился - это лишнее.

    Еще один вопрос немного не по теме:

    Как можно сохранить QPixmap в pdf, вернее как сохранить ясно, а вот с масштабированием проблема. Подгоняет изображение под размер листа, а не наоборот и где глюк не ясно. (Сохранение в А4 принципиально - изображения содержат страницы текста со сканера).

    Код:

    QVector<QPixmap>      images;
    
    //------------------------------------------------------------
    
    void MainWindow::on_actionSaveToPdf_triggered()
    {
        // Сохранение в PDF
    
        QString outputName = QFileDialog::getSaveFileName(this, "Сохранить в pdf",
                                            QDir::homePath(), "PDF файл (*.pdf)");
    
        if (outputName.isEmpty() || (images.length() == 0)) return;
    
    #ifdef Q_OS_LINUX
        outputName.append(".pdf");
    #endif
    
    #ifndef QT_NO_PRINTER
        QPrinter printer(QPrinter::HighResolution);
        printer.setPaperSize(QPrinter::A4);
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName(outputName);
        QPainter painter;
        painter.begin(&printer);
        for (int i = 0; i < images.length(); i++) {
            // Здесь намудрил
            QPixmap pix;
            if (images.at(i).heightMM() > images.at(i).widthMM()) {
                float dx = images.at(i).heightMM() / printer.pageSizeMM().height();
                pix = images.at(i).scaled(images.at(i).heightMM() / dx,
                                             images.at(i).widthMM() / dx,
                                             Qt::KeepAspectRatio,
                                             Qt::SmoothTransformation);
            }
            else {
                float dx = printer.pageSizeMM().height() / images.at(i).widthMM();
                pix = images.at(i).scaled(images.at(i).heightMM() / dx,
                                             images.at(i).widthMM() / dx,
                                             Qt::KeepAspectRatio,
                                             Qt::SmoothTransformation);
            }
    
            painter.drawPixmap(printer.pageRect(), pix);
            if (i != images.length()-1) printer.newPage();
        }
        painter.end();
    #endif
    }
      Arrow
      • 11 апреля 2017 г. 14:34

      Извините выше с кодом намудрил все немного проще, но вопрос остается:

      QStringList fNames;
      
      //----------------------------------------
      
      void MainWindow::on_actionSaveToPdf_triggered()
      {
      
          QString outputName = QFileDialog::getSaveFileName(this, "Сохранить в pdf",
                                              QDir::homePath(), "PDF файл (*.pdf)");
      
          if (outputName.isEmpty() || (fNames.length() == 0)) return;
      
      #ifdef Q_OS_LINUX
          outputName.append(".pdf");
      #endif
      
      #ifndef QT_NO_PRINTER
          QPrinter printer(QPrinter::HighResolution);
          printer.setPaperSize(QPrinter::A4);
          printer.setOutputFormat(QPrinter::PdfFormat);
          printer.setOutputFileName(outputName);
          QPainter painter;
          painter.begin(&printer);
          foreach (QString name, fNames) {
              // Масштабирование изображения под страницу        
              QPixmap pix(name);        
                  float dx = pix.heightMM() / printer.pageSizeMM().height();
                  pix = pix.scaled(pix.heightMM() / dx, pix.widthMM() / dx,
                                   Qt::KeepAspectRatio, Qt::SmoothTransformation);
              }
              else {
                  float dx = printer.pageSizeMM().height() / pix.widthMM();
                  pix = pix.scaled(pix.heightMM() / dx, pix.widthMM() / dx,
                                   Qt::KeepAspectRatio, Qt::SmoothTransformation);
              }
      
              painter.drawPixmap(printer.pageRect(), pix);
              if (name != fNames.last()) printer.newPage();
          }
          painter.end();
      #endif
      }
        Evgenii Legotckoi
        • 11 апреля 2017 г. 14:36

        Мм.. Вы пытаетесь масштабировать страницу относительно того в какой ориентации была картинка?

        Может стоит тогда для этого использовать метод QPrinter::setPageOrientation , он вроде бы поворачивает каждую страницу, то есть часть будет в портретной ориентации, а часть в ландшафтной.

        Ну а масштабирование изображения попробуйте делать методом QPixmap::scaledToWidth , чтобы всё подгонялось по ширине. После того как установили ориентацию страницы и добавили новую страницу. Настройка ориентации применяется к следующей новой странице.

          Arrow
          • 11 апреля 2017 г. 15:14

          Спасибо все работает, только изображение на первой странице почему-то съезжает в право. Может нужно что-то дополнительно задавать?

          void MainWindow::on_actionSaveToPdf_triggered()
          {
              QString outputName = QFileDialog::getSaveFileName(this, "Сохранить в pdf",
                                                  QDir::homePath(), "PDF файл (*.pdf)");
          
              if (outputName.isEmpty() || (fNames.length() == 0)) return;
          
          #ifdef Q_OS_LINUX
              outputName.append(".pdf");
          #endif
          
          #ifndef QT_NO_PRINTER
              QPrinter printer(QPrinter::HighResolution);
              printer.setOutputFormat(QPrinter::PdfFormat);
              printer.setOutputFileName(outputName);
              QPainter painter;
              painter.begin(&printer);
          
              foreach (QString name, fNames) {
                  printer.setPaperSize(QPrinter::A4);
          
                  // Масштабирование изображения под страницу
                  QPixmap pix(name);
          
                  if (pix.width() > pix.height())
                      printer.setPageOrientation(QPageLayout::Landscape);
                  else printer.setPageOrientation(QPageLayout::Portrait);
          
                  pix = pix.scaledToWidth(printer.pageRect().width(),
                                          Qt::SmoothTransformation);
          
                  painter.drawPixmap(printer.pageRect(), pix);
                  if (name != fNames.last()) printer.newPage();
              }
              painter.end();
          #endif
          }
            Evgenii Legotckoi
            • 11 апреля 2017 г. 22:53

            В документации сказано, что setPrinterOrientation отрабатывает после вызова newPage() на Windows и Mac .

            On Windows and Mac, this option can be changed while printing and will take effect from the next call to newPage() .

            Возможно проблема в этом. А возможно, что не совсем правильно определяются отступы при вызове pageRect() в первый раз. Возможно имеет смысл настроить margins перед началом печати изображения в файл.

              Arrow
              • 12 апреля 2017 г. 16:40

              Попробовал так:

                  QPrinter printer(QPrinter::HighResolution);
                  printer.setOutputFormat(QPrinter::PdfFormat);
                  // printer.setPageMargins(0, 0, 0, 0, QPrinter::Millimeter); - если установить, то все страницы имеют разную величину
                  printer.setOutputFileName(outputName);
                  QPainter painter;
                  painter.begin(&printer);
                  printer.setPaperSize(QPrinter::A4);
                  foreach (QString name, fNames) {
                      // Масштабирование изображения под страницу
                      QPixmap pix(name);
              
                      qDebug() << "Pixel width: " << pix.width();
                      qDebug() << "Pixel height: " << pix.height();
                      qDebug() << "Page layout (Portal - 0): " << printer.pageLayout();
              
                      if (pix.width() > pix.height())
                          printer.setPageOrientation(QPageLayout::Landscape);
                      else printer.setPageOrientation(QPageLayout::Portrait);
              
                      qDebug() << "Page layout (Portal - 0): " << printer.pageLayout();
              
                      pix = pix.scaledToWidth(printer.pageRect().width(),
                                              Qt::SmoothTransformation);
              
                      painter.drawPixmap(printer.pageRect(), pix);
                      if (name != fNames.last()) {
                          printer.newPage();
                          printer.setPaperSize(QPrinter::A4);
                      }
                  }
                  painter.end();

              Загружаю для создания pdf страницы (все горизонтальные) и получаю следующее:

              Через QDebug() видно, что все настраивается отлично, но в документе первая страница получается вертикальной и все изображение на ней обрезано. С остальными страницами все отлично.

              Похоже, что принтер не обновляет данные о странице после применения setPageOrientation. Как можно заставить его это сделать или как удалить текущую страницу, чтобы потом создать новую с нормальной ориентацией :) ?

                Evgenii Legotckoi
                • 13 апреля 2017 г. 0:43
                Похоже, что принтер не обновляет данные о странице после применения setPageOrientation.

                Я выше уже говорил, что ориентация страницы применяется после вызова newPage() и привёл выдержку из документации...

                Чтобы установить ориентацию для первой страницы, нужно устанавливать её до вызова метода begin() у QPainter() , тогда первая страница будет отрисована с нужной ориентацией.

                QPrinter printer(QPrinter::HighResolution);
                printer.setOutputFormat(QPrinter::PdfFormat);
                printer.setPageOrientation(QPageLayout::Landscape);  // Установить ландшафтную ориентацию
                printer.setOutputFileName(pdfName);
                printer.setPaperSize(QPrinter::A4);
                QPainter painter;
                painter.begin(&printer);

                Что касается сдвига, то пока понятия не имею, как это исправить.

                  Arrow
                  • 13 апреля 2017 г. 13:06

                  Извините, туплю.

                  Проблему решил так:

                  void MainWindow::on_actionSaveToPdf_triggered()
                  {
                      // Сохранение в PDF
                  
                      QString outputName = QFileDialog::getSaveFileName(this, "Сохранить в pdf",
                                                          QDir::homePath(), "PDF файл (*.pdf)");
                  
                      if (outputName.isEmpty() || (fNames.length() == 0)) return;
                  
                  #ifdef Q_OS_LINUX
                      outputName.append(".pdf");
                  #endif
                  
                  #ifndef QT_NO_PRINTER
                      QPrinter printer(QPrinter::HighResolution);
                      printer.setOutputFormat(QPrinter::PdfFormat);
                      printer.setPageMargins(0, 0, 0, 0, QPrinter::Millimeter);
                      printer.setOutputFileName(outputName);
                      QPainter painter;
                      //painter.begin(&printer);
                      printer.setPaperSize(QPrinter::A4);
                      foreach (QString name, fNames) {
                          // Масштабирование изображения под страницу
                          QPixmap pix(name);
                  
                          if (pix.width() > pix.height())
                              printer.setPageOrientation(QPageLayout::Landscape);
                          else printer.setPageOrientation(QPageLayout::Portrait);
                  
                          if (name == fNames.first()) painter.begin(&printer);
                  
                          pix = pix.scaledToWidth(printer.pageRect().width(),
                                                  Qt::SmoothTransformation);
                  
                          painter.drawPixmap(printer.pageRect(), pix);
                  
                          if (name != fNames.last()) {
                              printer.newPage();
                              printer.setPaperSize(QPrinter::A4);
                          }
                      }
                      painter.end();
                  #endif
                  }
                  
                    Evgenii Legotckoi
                    • 13 апреля 2017 г. 14:26

                    Извинения излишни ))
                    Небольшой комментарий по коду.
                    foreach - это чисто Qt-шный макрос, который был сделан в то время, когда стандарт C++ не поддерживал цикл for с возможностью перебора элементов контейнеров, которые имеют итератор. А вы используете как раз такой контейнер, я имею ввиду fNames . На сегодняшний день for поддерживает перебор элементов таких контейнеров (Начиная со стандарта C++11). А foreach можно считать deprecated . Поэтому в своих проектах, если не пишите на устаревших версиях стандарта C++, используйте новую нотацию. То есть с использованием цикла for . Тогда ваш код будет выглядеть следующим образом:

                    for (QString name : fNames) {
                        // ToDo something
                    }
                      Arrow
                      • 13 апреля 2017 г. 15:39

                      Спасибо! Цикл foreach привычка с C#.

                        Комментарии

                        Только авторизованные пользователи могут публиковать комментарии.
                        Пожалуйста, авторизуйтесь или зарегистрируйтесь
                        d
                        • dsfs
                        • 26 апреля 2024 г. 4:56

                        C++ - Тест 004. Указатели, Массивы и Циклы

                        • Результат:80баллов,
                        • Очки рейтинга4
                        d
                        • dsfs
                        • 26 апреля 2024 г. 4:45

                        C++ - Тест 002. Константы

                        • Результат:50баллов,
                        • Очки рейтинга-4
                        d
                        • dsfs
                        • 26 апреля 2024 г. 4:35

                        C++ - Тест 001. Первая программа и типы данных

                        • Результат:73баллов,
                        • Очки рейтинга1
                        Последние комментарии
                        k
                        kmssr8 февраля 2024 г. 18:43
                        Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                        АК
                        Анатолий Кононенко5 февраля 2024 г. 1:50
                        Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                        EVA
                        EVA25 декабря 2023 г. 10:30
                        Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                        J
                        JonnyJo25 декабря 2023 г. 8:38
                        Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                        G
                        Gvozdik18 декабря 2023 г. 21:01
                        Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                        Сейчас обсуждают на форуме
                        IscanderChe
                        IscanderChe30 апреля 2024 г. 4:22
                        Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…
                        G
                        Gar22 апреля 2024 г. 5:46
                        Clipboard Как скопировать окно целиком в clipb?
                        DA
                        Dr Gangil Academics20 апреля 2024 г. 7:45
                        Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
                        a
                        a_vlasov14 апреля 2024 г. 6:41
                        Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
                        Павел Дорофеев
                        Павел Дорофеев14 апреля 2024 г. 2:35
                        QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь

                        Следите за нами в социальных сетях