Показ дописів із міткою QT. Показати всі дописи
Показ дописів із міткою QT. Показати всі дописи

вівторок, 18 травня 2010 р.

Як зробити блок, що розгортається в QT (fold/unfold block)

Задача: зробити частину вікна діалога такою, що згортається і розгортається по кнопці, схоже до folding в Drupal чи Vim.
Згорнутий блок:


Розгорнутий блок:

Після довгих пошуків я знайшов такий шлях вирішення проблеми:
  1. Всі віджети діалогу мають бути поміщені в QLayout зі встановленим "SetDefaultConstraint" (в даній, 4.6 версії QT - по замовчуванню).
  2. Всі дочірні віджети першого рівня кожного QLayout повинні мати "Vertical Policy" встановлені в "Fixed", інакше вони будуть розтягуватися при зміні конфігурації вікна.
  3. Створити кнопку типу QToolButton, якщо ми хочемо мати кнопку з гарненьким трикутничком, який повертається, як на скріншоті. Я її назвав "advSettingsButton". Трикутник: в дизайнері QT Creator'а встановити властивість arrowType рівною RightArrow.
  4. Для кнопки "advSettingsButton", яка згортає/розгортає блок, слід написати подібний код:
    void OurProxyDialog::on_advSettingsButton_clicked()
    {
        // If advanced settings are hidden, show
        if (m_ui->capabilitiesBox->isHidden()) {
            m_ui->advSettingsButton->setArrowType(Qt::DownArrow);
            m_ui->capabilitiesBox->show();
        } else if (m_ui->capabilitiesBox->isVisible()) {
            // If advanced settings are shown, hide
            m_ui->advSettingsButton->setArrowType(Qt::RightArrow);
            m_ui->capabilitiesBox->hide();
        }
        adjustSize();
    }
    

    Тут "capabilitiesBox" це якраз нижній блок (QGroupBox), який згортається/розгортається.
  5. Для краси в цієї кнопки прибрані границі через встановлення "styleSheet" властивості рівною "border: 0;". Також можна додати градієнт там же.
  6. Для конструктора діалогу встановити таку обробку, щоб блок був схований при створенні вікна:
    OurProxyDialog::OurProxyDialog(QWidget *parent) :
        QDialog(parent),
        m_ui(new Ui::OurProxyDialog)
    {
        m_ui->setupUi(this);
    
        // Hide advanced settings
        m_ui->capabilitiesBox->hide();
        setMaximumHeight(0);
        adjustSize();
    }
    

Ніби все.

    PS. Кінцевий варіант коду мені допомогло написати ось це джерело (щодо зміни розміру вікна після видалення певного віджету): http://lists.trolltech.com/qt-interest/2006-10/thread00212-0.html

    середа, 14 квітня 2010 р.

    Проблеми з повторними генераціями сигналу finished для QNetworkReply

    Вчора зіткнувся з досить неочевидною проблемою при тестуванні QT-аплікації. Після відсилання мережевого запиту обробка відповіді відбувається у функції, прив'язаній до сигналу finished.
    Робота з мережевими запитами в QT описана ось тут Creating_an_HTTP_network_request_in_Qt

    Ось, власне, прив'язка у моєму випадку:
    connect(_networkManager, SIGNAL(finished(QNetworkReply*)), this,
        SLOT(replyFinished(QNetworkReply*)));
    

    Виявилося, що цей сигнал генерується декілька разів: QNetworkReply завершив роботу, перед знищенням об'єкта QNetworkReply або під час його закриття функціями close() чи abort(). При цьому лише у першому випадку з нього можна щось прочитати, у решті - ні, що призводить до помилок при парсінгу даних і зупинки обробки наступних запитів (у моєму випадку відбувається перевірка статусу попереднього запиту перед відправкою наступного).

    Правильним рішенням було відключити всі слоти від сигналів QNetworkReply, щоб не отримувати їх після завершення обробки даних. Ось як це реалізовано:
    void MyClass::replyFinished(QNetworkReply* reply) {
        // --------------------------------------
        // Тут насправді міститься обробка даних
        // --------------------------------------
    
        // Close and clean up.
        m_networkManager->disconnect();
        reply->close();
        reply->deleteLater();
    }