Russian Qt Forum
Ноябрь 24, 2024, 04:12 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QPushButton::setChecked() и вызов меню  (Прочитано 9838 раз)
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« : Февраль 17, 2013, 00:50 »

Здравствуйте!
Помогите разобраться и доделать Улыбающийся

Задание:
Создать кнопку. При нажатии на нее она помечается (checked = true) и появляется меню.
Меню и функцию его появления сделать самому. При повторном нажатии на кнопку, меню исчезает и исчезает метка на кнопке (checked = false). Меню также исчезает, если оно теряет фокус. Если у меню нет фокуса, метка с кнопки также исчезает.


В общем, сделал почти все, вот только проблемка возникла.

Нажатие на кнопку вызывает этот слот:
Код:
void showPopup()
{
    bool checked = pButtonShowHideDropDownMenu->isChecked();

    QPoint pos = pButtonShowHideDropDownMenu->mapToGlobal(QPoint(0,
                                                  pButtonApply->height()));
    dropDownMenu->move(pos);

    dropDownMenu->setVisible(checked);
}
т.е. получаем состояние кнопки (checked) и взависимости от него показываем/прячем наш виджет-меню с флагом Qt::Popup

Осталось сделать так чтобы, при исчезновении меню кнопка перестала быть помеченной.

Переопределил я у виджета-меню событие исчезновения (hideEvent()), в нем добавил генерацию сигнала. Когда сигнал отлавливается, вызывается слот с строкой:
Код:
pButtonShowHideDropDownMenu->setChecked(false);

Теперь нажатие на кнопку, вызывает меню, а повторное нажатие, прячет и снова его показывает
Если убрать строку
Код:
pButtonShowHideDropDownMenu->setChecked(false);
, то такого безобразия нет

Как сделать такое же поведение кнопки как и в QComboBox?

Спасибо Улыбающийся
Записан

Bepec
Гость
« Ответ #1 : Февраль 17, 2013, 00:52 »

Ты скорее всего подцепил слот свой на изменение состояния кнопки, а не на нажатие Улыбающийся

Собственно ты этой строкой снова его вызываешь. Чудом не попадая в рекурсию Веселый
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #2 : Февраль 17, 2013, 00:56 »

слот поставил на сигнал clicked()
Записан

gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #3 : Февраль 17, 2013, 01:10 »

Минимально компилируемый код:

h:
Код:
class UDropDownMenu: public QWidget
{
    Q_OBJECT

public:
    UDropDownMenu(QWidget *parent = 0)
    {
        setWindowFlags(Qt::Popup);

        gridLayout = new QGridLayout();

        setLayout(gridLayout);
    }

private:
    QGridLayout *gridLayout;

signals:
    void iHide();

protected:
    void paintEvent(QPaintEvent *event)
    {
        QWidget::paintEvent(event);

        QPainter painter(this);

        QPen pen;
        pen.setWidth(2);
        painter.setPen(pen);

        painter.drawRect(rect());
    }

    void hideEvent(QHideEvent *)
    {
        emit iHide();
    }
};

class UComboBoxButton: public QWidget
{
    Q_OBJECT   

public:
    UComboBoxButton(QWidget *parent = 0);

private:
    void createGUI();

private:
    QPushButton *pButtonShowHideDropDownMenu;
    UDropDownMenu *dropDownMenu;

public slots:
    void showPopup();

private slots:
    void dropDownMenuHide();
};

cpp:
Код:
/// PUBLIC
UComboBoxButton::UComboBoxButton(QWidget *parent)
    : QWidget(parent)
{
    createGUI();
}

/// PRIVATE
void UComboBoxButton::createGUI()
{
    QHBoxLayout *hBoxLayoutMain = new QHBoxLayout();

    dropDownMenu = new UDropDownMenu();
    connect(dropDownMenu, SIGNAL(iHide()),
            this, SLOT(dropDownMenuHide()));

    pButtonShowHideDropDownMenu = new QPushButton();
    pButtonShowHideDropDownMenu->setCheckable(true);
    pButtonShowHideDropDownMenu->setFixedSize(20, 20);

    connect(pButtonShowHideDropDownMenu, SIGNAL(clicked()),
            this, SLOT(showPopup()));

    hBoxLayoutMain->addWidget(pButtonShowHideDropDownMenu);
    hBoxLayoutMain->setSpacing(0);

    setLayout(hBoxLayoutMain);
}

/// PUBLIC SLOTS
void UComboBoxButton::showPopup()
{
    QPushButton *pButton = pButtonShowHideDropDownMenu;   

    QPoint pos = pButton->mapToGlobal(QPoint(0,
                                                  pButton->height()));

    dropDownMenu->move(pos);

    bool checked = pButton->isChecked();
    dropDownMenu->setVisible(checked);
}

/// PRIVATE SLOTS
void UComboBoxButton::dropDownMenuHide()
{
    QPushButton *pButton = pButtonShowHideDropDownMenu;
    pButton->setChecked(false);
}
« Последнее редактирование: Февраль 17, 2013, 01:13 от gil9red » Записан

Bepec
Гость
« Ответ #4 : Февраль 17, 2013, 10:33 »

Осмелюсь спросить - а запускать то его как? Веселый

update:
Красотааа, а инклуды наверняка не нужны Веселый

update:
Проблему увидел, пока думаю. Там у тебя кнопка при потере фокуса с меню твоего испускает toggled. Пытаюсь найти что да как.

update:
Проблема банальна.

Код:
bool checked = pButton->isChecked(); // всегда равняется true


Выглядит лог примерно так
Цитировать
toggled true  - сигнал изменения состояния кнопки
button true   - твоя проверка, приведённая выше
click            - сигнал о нажатии кнопки (приходит позже, ибо подключён после твоего слота)
// - вот тут появляется твоё меню, далее я теряю фокус с меню (тыкаю на заголовок окна)
toggled false - сигнал изменения состоянии кнопки (pButton->setChecked(false)Подмигивающий

Вот и всё. Неправильный алгоритм просто.

update: Ещё упрощу:
Теперь нажатие на кнопку, вызывает меню, а повторное нажатие, прячет и снова его показывает
Если убрать строку
Код:
pButtonShowHideDropDownMenu->setChecked(false);
, то такого безобразия нет

Анализируем твой вопрос.
Алгоритм:
Первое нажатие:
clicked pushButton: Нажатие на кнопку
                           Проверка условий (всегда true, как я уже писал)
                           Вызов меню

Повторное нажатие
clicked pushButton: Переводим фокус с меню на кнопку (при повторном нажатии)
                           Меню исчезает
                           Проходит сигнал нажатия кнопки
                           Проверка условий (всегда true, как я уже писал)
                           Появление меню Улыбающийся


PS и да, в следующий раз лучше уж проект выложи. Со всеми main/include. Улыбающийся
« Последнее редактирование: Февраль 17, 2013, 11:08 от Bepec » Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #5 : Февраль 17, 2013, 15:17 »

Создать кнопку. При нажатии на нее она помечается (checked = true) и появляется меню.
Меню и функцию его появления сделать самому. При повторном нажатии на кнопку, меню исчезает и исчезает метка на кнопке (checked = false). Меню также исчезает, если оно теряет фокус. Если у меню нет фокуса, метка с кнопки также исчезает.

Задача как минимум странная.
Во-первых, меню при своём появлении захватывает и мышь и клавиатуру - нажать кнопку не получится пока меню не будет спрятано.
Во-вторых, очень сильно попахивает изобретением велосипеда ибо QToolButton имеет нужную функциональность. См. QToolButton::setPopupMode().
Записан

Qt 5.11/4.8.7 (X11/Win)
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #6 : Февраль 17, 2013, 15:50 »

Верес, покажите что нужно исправить в алгоритме?
Записан

Bepec
Гость
« Ответ #7 : Февраль 17, 2013, 16:15 »

Омм... Используй не свойство кнопки, а собственный флаг,как вариант. Честно - лень думать Веселый
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #8 : Февраль 17, 2013, 21:31 »

Решил воспользоваться советом GreatSnake, и реализовать через QToolButton.
Записан

Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.067 секунд. Запросов: 23.