Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ QComboBox, Как задать размер выпадающего списка

Автор: trdm 3.1.2009, 19:50

Задать размер выпадающего списка у QComboBox.
Туплю слегонца.....
Проблема на скрине:

 

Автор: panter_dsd 3.1.2009, 19:56

QAbstractItemView * QComboBox::view () const ?

Автор: Litkevich Yuriy 3.1.2009, 20:02

trdm, а как он у тебя вообще такой получился, может ты с виджетом, вложеным, что-то не так сделал (sizeHint, например)?

Автор: trdm 3.1.2009, 20:12

Цитата(panter_dsd @ 3.1.2009, 19:56) *
QAbstractItemView * QComboBox::view () const ?

На сколько помню const в этом случае типа сторож, что-бы функция view не меняла внутренностей QComboBox.
Или я не понял намека?


+
там же на скрине все операции с комбобоксом.
ПС. Говорю же туплю :)

Автор: panter_dsd 3.1.2009, 20:26

const означает, что ссылка константная, но сам объект можно изменять. Делаешь:
QAbstractItemView * view=comboBox->view () и работаешь уже с самим объектом.
ПыСы: проверить не могу и не работал с этим, но по идее должно.

А вообще, закинь немного кода по созданию и заполнению QComboBox.

Автор: SABROG 3.1.2009, 20:53

Цитата(panter_dsd @ 3.1.2009, 20:26) *
const означает, что ссылка константная, но сам объект можно изменять. Делаешь:
QAbstractItemView * view=comboBox->view () и работаешь уже с самим объектом.
ПыСы: проверить не могу и не работал с этим, но по идее должно.

А вообще, закинь немного кода по созданию и заполнению QComboBox.


Нет, const в данном случае означает всего-лишь то, что метод не меняет внутреннего состояния класса (грубо говоря не меняет данные-члены класса, read-only)

И я думаю, что надо использовать setView, а то перетягивание каната получается. Комбик ресайзит как ему надо, ты ресайзиш как тебе надо.

Автор: trdm 3.1.2009, 21:20

Цитата(SABROG @ 3.1.2009, 20:53) *
И я думаю, что надо использовать setView, а то перетягивание каната получается. Комбик ресайзит как ему надо, ты ресайзиш как тебе надо.

Я уже думал над этим. Изучаю по void QComboBox::showPopup()
setView не попрет :(
Придется идти другим путем...

Мне не очень понравилось юзабелити колор-комбобокса. Так что прийдется как-то извратиться...

Автор: SABROG 3.1.2009, 21:39

Если особо напрягаться не хочется, то можно идти путем "Color Editor Factory Example"

Автор: trdm 3.1.2009, 21:48

Цитата(SABROG @ 3.1.2009, 21:39) *
Если особо напрягаться не хочется, то можно идти путем "Color Editor Factory Example"

не. смысл поделия в том что-бы экономить время девелопера помаксимому.
В "Color Editor Factory Example" выпадающий список, а у меня палитра из специально подобранных цветов.
Пользователь видит сразу варианты и может прикинуть что да как как будет выглядеть.
Если не устроит, уж тогда велком ту системе колор пикер...
Вот хороший вариант:

 

Автор: SABROG 3.1.2009, 21:59

А чем он радикально отличается от QColorDialog'a ?

Автор: trdm 3.1.2009, 22:01

Цитата(SABROG @ 3.1.2009, 21:59) *
А чем он радикально отличается от QColorDialog'a ?

Радикально: предзаданныйми цветовыми схемами.
Очень время экономит.

Автор: SABROG 3.1.2009, 22:02

Цитата(trdm @ 3.1.2009, 22:01) *
Цитата(SABROG @ 3.1.2009, 21:59) *
А чем он радикально отличается от QColorDialog'a ?

Радикально: предзаданныйми цветовыми схемами.
Очень время экономит.


Ну так и предзадай

Цитата
void QColorDialog::setCustomColor ( int number, QRgb color ) [static]

Автор: trdm 3.1.2009, 22:08

не кошерно. :)
плюс ко всему еще пара задач намечается со сходной реализацией, но разными данными.
надо схему отработать.

Автор: SABROG 4.1.2009, 12:17

Цитата(trdm @ 3.1.2009, 22:08) *
не кошерно. :)
плюс ко всему еще пара задач намечается со сходной реализацией, но разными данными.
надо схему отработать.

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

Автор: trdm 4.1.2009, 12:45

Цитата(SABROG @ 4.1.2009, 12:17) *
Ну исходников заполнения combobox мы до сих пор не увидели, т.ч. врятли так удастся чем-то помочь. Нужен компилируемый материал.

Там смотреть не на что.
Комбобоску просто устанавливается модель
tabFont->m_cBoxColor->setModel(m_colorModel);
Модель заполняется цветами:
Раскрывающийся текст

void uoReportPropEditor::addColor(int& row, QColor col, bool def)
{
    m_colorModel->insertRows(row, 1, QModelIndex());
    m_colorModel->setData(m_colorModel->index(row, 0, QModelIndex()),col);
    m_colorModel->setData(m_colorModel->index(row, 0, QModelIndex()),col, Qt::DecorationRole);
}

void uoReportPropEditor::fillColorModel()
{
    m_colorModel->removeRows(0, m_colorModel->rowCount(QModelIndex()), QModelIndex());
    int row = -1;
    addColor(++row, QColor("#000000"), true);
    addColor(++row, QColor("#ffffff"), true);
    addColor(++row, QColor("#ff0000"), true);
    addColor(++row, QColor("#00ff00"), true);
    addColor(++row, QColor("#0000ff"), true);//blue
    addColor(++row, QColor("#ffff00"), true);// желтый
    addColor(++row, QColor("#ff00ff"), true);    //
    addColor(++row, QColor("#00ffff"), true);    //

    addColor(++row, QColor("#800000"), true);    //
    addColor(++row, QColor("#008000"), true);    //
    addColor(++row, QColor("#808000"), true);    //
    addColor(++row, QColor("#000080"), true);    //
    addColor(++row, QColor("#800080"), true);    //
    addColor(++row, QColor("#008080"), true);    //
    addColor(++row, QColor("#808080"), true);    //
    addColor(++row, QColor("#c0c0c0"), true);    //

    //3
    addColor(++row, QColor("#8080ff"), true);    //
    addColor(++row, QColor("#802060"), true);    //
    addColor(++row, QColor("#ffffc0"), true);    //
    addColor(++row, QColor("#a0e0e0"), true);    //
    addColor(++row, QColor("#600080"), true);    //
    addColor(++row, QColor("#ff8080"), true);    //
    addColor(++row, QColor("#0080c0"), true);    //
    addColor(++row, QColor("#c0c0ff"), true);    //

    //4
    addColor(++row, QColor("#00cfff"), true);    //
    addColor(++row, QColor("#69ffff"), true);    //
    addColor(++row, QColor("#e0ffe0"), true);    //
    addColor(++row, QColor("#dd9cb3"), true);    //
    addColor(++row, QColor("#b38fee"), true);    //
    addColor(++row, QColor("#2a6ff9"), true);    //
    addColor(++row, QColor("#3fb8cd"), true);    //
    addColor(++row, QColor("#488436"), true);    //

    // 5
    addColor(++row, QColor("#958c41"), true);    //
    addColor(++row, QColor("#905e42"), true);    //
    addColor(++row, QColor("#a0627a"), true);    //
    addColor(++row, QColor("#624fac"), true);    //
    addColor(++row, QColor("#1d2fbe"), true);    //
    addColor(++row, QColor("#286676"), true);    //
    addColor(++row, QColor("#004500"), true);    //
    addColor(++row, QColor("#453e01"), true);    //

    // 6
    addColor(++row, QColor("#6a2813"), true);    //
    addColor(++row, QColor("#85396a"), true);    //
    addColor(++row, QColor("#4a3285"), true);    //
    addColor(++row, QColor("#c0dcc0"), true);    //
    addColor(++row, QColor("#a6caf0"), true);    //
    addColor(++row, QColor("#7fffd4"), true);    //
    addColor(++row, QColor("#f0ffff"), true);    //
    addColor(++row, QColor("#f5f5dc"), true);    ///// Повтор?!
    // Повторы?!
    // 7
    addColor(++row, QColor("#808000"), true);    //
    addColor(++row, QColor("#800080"), true);    //
    addColor(++row, QColor("#008080"), true);    //
    addColor(++row, QColor("#808080"), true);    //
    addColor(++row, QColor("#fffbf0"), true);    //
    addColor(++row, QColor("#a0a0a4"), true);    //
    addColor(++row, QColor("#313900"), true);    //
    addColor(++row, QColor("#d9853e"), true);    //

}


Автор: SABROG 5.1.2009, 1:22

Жесть какая. Может цикл сделать и массив цветов ?

Автор: trdm 5.1.2009, 11:30

Цитата(SABROG @ 5.1.2009, 1:22) *
Жесть какая. Может цикл сделать и массив цветов ?

Сделаю.

Автор: SABROG 5.1.2009, 14:31

view->updateGeometry();


Вызывал ?

Автор: trdm 5.1.2009, 21:36

Цитата(SABROG @ 5.1.2009, 14:31) *
view->updateGeometry();


Вызывал ?

нет, я пошел другим путем.

Автор: trdm 6.1.2009, 3:27

Вот таким путем пошел:
Как думаете, нормально?

 

Автор: Litkevich Yuriy 6.1.2009, 6:11

Цитата(trdm @ 6.1.2009, 6:27) *
Как думаете, нормально?
неа, декорацию окна убери

Автор: molchanoviv 6.1.2009, 11:34

А по моему вполне себе ничего

Автор: SABROG 6.1.2009, 11:58

Titlebar с фреймом имхо не нужны, а так вполне.

Автор: trdm 6.1.2009, 12:32

Цитата(Litkevich Yuriy @ 6.1.2009, 6:11) *
Цитата(trdm @ 6.1.2009, 6:27) *
Как думаете, нормально?
неа, декорацию окна убери

Какую декорацию?

Автор: molchanoviv 6.1.2009, 12:35

В окне выбора цвета убери шапку. Хотя по мне в ООо сделано с шапкой и ничего.

Автор: trdm 6.1.2009, 14:33

Цитата(molchanoviv @ 6.1.2009, 12:35) *
В окне выбора цвета убери шапку. Хотя по мне в ООо сделано с шапкой и ничего.

убрал. чуток доточить надо, а так в принцыпе готово..

 

Автор: Litkevich Yuriy 6.1.2009, 15:18

Цитата(trdm @ 6.1.2009, 15:32) *
Какую декорацию?
так называют рамку и, возможно, заголовок, которые рисует менеджер окон, чтобы пользователь мог управлять размером и положением окна. По буржуйски (frame & title = decoration)

Цитата(trdm @ 6.1.2009, 17:33) *
чуток доточить надо
ага, положи свой виджет на QFrame и поэксперементируй со стилем его границ.

Автор: trdm 9.1.2009, 22:14

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

Автор: SABROG 9.1.2009, 23:03

Вообще за сокрытие попапов отвечает сам класс QWidget.

void QWidget::mousePressEvent(QMouseEvent *event)
{
    event->ignore();
    if ((windowType() == Qt::Popup)) {
        event->accept();
        QWidget* w;
        while ((w = qApp->activePopupWidget()) && w != this){
            w->close();
            if (qApp->activePopupWidget() == w) // widget does not want to dissappear
                w->hide(); // hide at least
        }
        if (!rect().contains(event->pos())){
            close();
        }
    }
}


Помимо кликов он отслеживает фокус всплывающих окон. Если фокус пропадает, то и окно закрывается (см. QWidgetPrivate::show_helper()).

void QComboBoxPrivateContainer::mousePressEvent(QMouseEvent *e)
{

    QStyleOptionComboBox opt = comboStyleOption();
    opt.subControls = QStyle::SC_All;
    opt.activeSubControls = QStyle::SC_ComboBoxArrow;
    QStyle::SubControl sc = combo->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt,
                                                           combo->mapFromGlobal(e->globalPos()),
                                                           combo);
    if ((combo->isEditable() && sc == QStyle::SC_ComboBoxArrow)
        || (!combo->isEditable() && sc != QStyle::SC_None))
        setAttribute(Qt::WA_NoMouseReplay);
    combo->hidePopup();
}


А ComboBox'у похоже все-равно когда закрываться куда ни кликни. По координатам мышки он определяет на какой элемент контрола (стрелка или еще что) был сделан клик и в зависимости от этого выставляет аттрибут Qt::WA_NoMouseReplay. В описании говорится:

Цитата
Используется для всплывающих виджетов. Указывает, что самое последнее событие нажатия кнопки мыши не должно быть воспроизведено, когда всплывающий виджет закрывается. Флаг устанавливается автором виджета и сбрасывается ядром Qt каждый раз когда виджет принимает новое событие мыши.

Но вот что означает это "воспроизведено" (reply) не ясно.

Автор: trdm 10.1.2009, 0:13

Вот проектик:
Через попуп у меня не получился виджет, чего-то я не догоняю в этом деле.
Если выпадающему виджету установить Qt::Popup, то вопервых получается какое-то прозрачное оконце, которое не ловит paintEvent() и соответственно нефига не рисует.
Если брать текущую реализацию, то есть 2 момента.
Если виджет-родитель при открытом попупе перетащить или поместить вниз зет-ордера то окно попупа останется на экране.
Как правильно отработать момент не въеду пока.
Может кто чего сообразит?

 uoWidget.zip ( 9.28 килобайт ) : 117
 

Автор: Litkevich Yuriy 10.1.2009, 0:26

Цитата(SABROG @ 10.1.2009, 2:03) *
"воспроизведено" (reply) не ясно
ну типа повторение

Автор: SABROG 10.1.2009, 0:52

Цитата(Litkevich Yuriy @ 10.1.2009, 0:26) *
ну типа повторение


А в каком контексте ? Что повторяется и зачем :) ?
---
А кажись понял

Цитата
When the application opens a popup widget, all events are sent to the popup.


Т.е. если кликнуть где-нить при активном попапе, то эвент пойдет дальше по всем виджетам, а аттрибут это блокирует.

Автор: SABROG 10.1.2009, 16:30

Проверил рисование на popup'e, все отлично

В подтверждение тому http://filebeam.com/01e10c0291ef992eb579b35132cafa2f (7Mb)

 

Автор: Litkevich Yuriy 10.1.2009, 18:56

SABROG, а чето за метёлка? Она к теме какое отношение имеет?

Автор: SABROG 10.1.2009, 19:10

Это скрин из демки, там 24 телки рандомно выводятся в виде popup окна. Это я так проверял работу paintEvent'a попап окна. А телок выбрал, чтобы глаз радовали. Могу мужиков поставить. Предупредите заранее, когда в след. раз что-нибудь ваять надумаю. ;)

Надо будет на досуге с .mng пошаманить. Что-нить типа десктопного анимированного питомца или виртуалгёрл замутить.

Автор: trdm 10.1.2009, 19:58

Какой парент у попупа? QDialog? А у меня унаследованный от QFrame виджет.
Попробуй в конструкторе проекта, который я подцепил выше установить у uoColorCContainer флаг Qt::Popup и увидишь о чем я говорил.

Автор: SABROG 10.1.2009, 20:42

Цитата(trdm @ 10.1.2009, 19:58) *
Какой парент у попупа? QDialog? А у меня унаследованный от QFrame виджет.
Попробуй в конструкторе проекта, который я подцепил выше установить у uoColorCContainer флаг Qt::Popup и увидишь о чем я говорил.

У меня от чистого QWidget'a. Изменил на QFrame, ничего не изменилось.

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

Автор: trdm 10.1.2009, 21:28

да уж... наверное замутил....
я еще и не такое замутить способен :)
фиг кто разберется....

Автор: SABROG 10.1.2009, 22:05

Попробуй пропиши вот это в main.cpp

QObject::connect(btnOK, SIGNAL(clicked()),colCh, SLOT(popupShow()));


И раскомментируй Qt::Popup. Затем сравни результаты, выбери из комбобокса попап, а потом с помощью кнопки OK. В первом случае зависнет, во второй отработает на все 100.

---
Пардон забыл еще кое-что.
Надо закомментировать это:

setWindowFlags(Qt::ToolTip);


Иначе popup окно не будет попапом и следовательно закрываться при потере фокуса.

Если в uoColorCContainer::mousePressEvent закомментировать все и оставить только это:

QWidget::mousePressEvent(event);


То окно будет закрываться при потере фокуса, но не будет выбираться элемент, а если раскомментировать, то цвета будут выбираться, но попап не будет закрываться при потере фокуса.

Зато если совместить вот так:

void uoColorCContainer::mousePressEvent(QMouseEvent *event)
{

    QPoint pt = event->pos();
    QList<uoColRect>::const_iterator  cIt = m_colRects.begin();
    uoColRect colrRct;
    int cur = 0;

    while(cIt != m_colRects.end()){
        colrRct = *cIt;
        if (colrRct.m_rect.contains(pt))
        {
            m_curentItem = cur;
            cur = -1;
            break;
        }
        cIt++;
        ++cur;
    }
    if (cur == -1){
        setCurentItem(m_curentItem);
        hide();
    }
    QWidget::mousePressEvent(event);
}


То окно и закрывается и элемент выбирается.
---
Похоже я опять что-то забыл...
Блин, если сначала нажать на кнопку, а потом использовать комбо, то все нормально. А если просто на кнопку комбика жать, то отрисовка не идет.
---
Мистика какая-то. Если сначала нажать на комбик, потом выбрать предполагаемый цвет, то этот так и не отрисовавшийся попап пропадает. Затем если снова нажимать на комбик то все работает. В общем эвенты - зло.

Автор: trdm 10.1.2009, 22:48

Стало быть проблема в МЕСТЕ вызова метода popupShow().
Я это замечал когда пытался проанализировать Qt-шный пример windowsFlag.
вот правленный проект. я тут кое-что подкрутил. Вобщем меня вроде как устраивает, но если есть шанс сделать нормально, то лучше сделать нормально...

 uoWidget.zip ( 8.72 килобайт ) : 108
 

Автор: SABROG 10.1.2009, 23:32

Добавил setFocus стало все отрисовываться

void uoColorChooser::popupShow()
{
    if (m_colorList.isEmpty())
        return;
    getContainer();
    QSize sz = m_Container->recalcSize();
    m_Container->doChangeCurColor(m_colorCurPos);

    QPoint below = mapToGlobal(frameRect().bottomLeft());
    QRect contRect = QRect(below, QPoint(below.x()+sz.width(), below.y()+sz.height()));
    m_Container->setGeometry(contRect);
    m_Container->move(below);
    m_Container->raise();
    m_Container->show();
    m_Container->update();
    m_Container->setFocus();
}


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

В общем пока все свелось к следующим изменениям:

- раскомментировать Qt::Popup
- закомментировать Qt::Tooltio
- добавить в конец метода uoColorCContainer::mousePressEvent - QWidget::mousePressEvent(event);
- в методе uoColorChooser::mousePressEvent заменить popupHide() на popupShow()
- добавить setFocus

Автор: trdm 11.1.2009, 0:19

Цитата(SABROG @ 10.1.2009, 23:32) *
Добавил setFocus стало все отрисовываться

фокус на сонтайнере как бы и не нужен в принципе по задумке.

Автор: SABROG 11.1.2009, 0:29

Цитата(trdm @ 11.1.2009, 0:19) *
Цитата(SABROG @ 10.1.2009, 23:32) *
Добавил setFocus стало все отрисовываться

фокус на сонтайнере как бы и не нужен в принципе по задумке.


Ну QComboBox фокус же на вьюху ставит. Правда до сих пор не могу понять как этот фокус влияет на отрисовку попапа. Или почему фокус сам не переходит на открытое окно. В общем проблема скрылась где-то в зарослях логики работы Qt с виджетами и эвентами.

Автор: trdm 11.1.2009, 21:27

Цитата(SABROG @ 10.1.2009, 23:32) *
Добавил setFocus стало все отрисовываться....

Вобщем сделал как ты написал и добавил от себя.
После установки фокуса все стало перерисовываться.
ПС. Вобщем дорожка проторена, можно идти :)
Сенк!

Автор: SABROG 11.1.2009, 21:40

Цитата(trdm @ 11.1.2009, 21:27) *
Цитата(SABROG @ 10.1.2009, 23:32) *
Добавил setFocus стало все отрисовываться....

Вобщем сделал как ты написал и добавил от себя.
После установки фокуса все стало перерисовываться.
ПС. Вобщем дорожка проторена, можно идти :)
Сенк!


Имхо там заросли те еще :) Хотелось бы докапаться до сути, почему:
  1. фокус не переходит на окно, если окно показывается в эвенте (если по сигнату то все ок)
  2. окно не отрисовывается без фокуса


И понять каждую строчку кода, чтобы можно было написать какой-нибудь гайд по созданию своих виджетов. Я думаю там еще будут проблемы с keyPressEvent'ом. А так код сейчас выглядит так как будто его выдрали частями из исходников QComboBox :)

Автор: trdm 11.1.2009, 21:53

Цитата(SABROG @ 11.1.2009, 21:40) *
Я думаю там еще будут проблемы с keyPressEvent'ом.

это я доточил.
Цитата(SABROG @ 11.1.2009, 21:40) *
А так код сейчас выглядит так как будто его выдрали частями из исходников QComboBox :)

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

Автор: SABROG 11.1.2009, 23:04

А ты победил залипание кнопок при первом клике ? Т.е. когда у QComboBox жмешь на стрелку, то она залипает до момента пока контейнер не скроется. А у меня получается что при первом вызове не залипает, а потом нормально.

Автор: trdm 11.1.2009, 23:30

Цитата(SABROG @ 11.1.2009, 23:04) *
А ты победил залипание кнопок при первом клике ? Т.е. когда у QComboBox жмешь на стрелку, то она залипает до момента пока контейнер не скроется. А у меня получается что при первом вызове не залипает, а потом нормально.

неа. Оставил пока для как несущественную фичу. Думю доточить несложно. Сейчас другие приоритеты.
Собственно я просто хотел "познакомиться" с имплементациями такого рода: выпадающий список и свои кнопки "на контроле".

Автор: SABROG 12.1.2009, 15:22

Создал тестовое приложение и в mousePressEvent динамически создаю QWidget и там же его отображаю. Проблем с отрисовкой вроде нет никаких, даже оригинальный обработчик вызывать не приходится. Где же косяк зарылся ?

Кстати забавно. Если на форме находится кнопка и на нее нажимаешь, то эвент не вызывается, а если на неё нажать правой кнопкой мышки, то вызывается :)

Кстати выбор клавиатурой при закрытом контейнере работает криво. Если зажать клавишу вверх/вниз, то через некоторое время цвет зацикливается.

Автор: trdm 9.2.2009, 2:08

Цитата(SABROG @ 12.1.2009, 15:22) *
Кстати выбор клавиатурой при закрытом контейнере работает криво. Если зажать клавишу вверх/вниз, то через некоторое время цвет зацикливается.

это зафиксено.

Автор: niXman 10.2.2009, 5:01

Ну так финальную версию кто нибудь покажите.
Спасибо!

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)