вівторок, 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