Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Авварон от Октябрь 18, 2011, 00:59



Название: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 18, 2011, 00:59
Задача - сделать просто иконку в углу табвиджета. С ходу повесить кнопку с прозрачным бэкграундом не удалось - под кнопкой виден артефакт в виде не прорисованной области (под ней нет ни таббара, ни текущего виджета)
Как костыль решил так:
Код:
class TabBarButton : public QAbstractButton
{
public:
    TabBarButton() :
        QAbstractButton(),
        hovered(false),
        pressed(false)
    {
    }

    void paintEvent(QPaintEvent *e)
    {
        QPainter p(this);

        QStyleOptionTabBarBaseV2 opt;
        opt.init(this);
        // hardcoded document Mode
        opt.documentMode = true;

        int overlap = style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &opt, this);
        QRect rect;
        // hardcoded north position
        rect.setRect(0, size().height() - overlap, size().width(), overlap);
        opt.rect = rect;

        qApp->style()->drawPrimitive(QStyle::PE_FrameTabBarBase, &opt, &p, this);

        int w = iconSize().width();
        int h = iconSize().height();
        QIcon::Mode mode = pressed ? QIcon::Selected : QIcon::Normal;

        icon().paint(&p, (width() - w)/2, (height() - h)/2, w, h, Qt::AlignCenter, mode);
    }

    QSize sizeHint() const { return iconSize(); }
    void enterEvent(QEvent *) { hovered = true; update(); }
    void leaveEvent(QEvent *) { hovered = false; update(); }
    void mousePressEvent(QMouseEvent *e) { pressed = true; update(); QAbstractButton::mousePressEvent(e); }
    void mouseReleaseEvent(QMouseEvent *e) { pressed = false; update(); QAbstractButton::mouseReleaseEvent(e); }

private:
    bool hovered;
    bool pressed;
};
Но тут есть проблема - нет возможности отрисовать иконку при ховере (у иконки нет больше модов, наложить полупрозрачную серую маску не получется, почему-то fillRect игнорирует альфаканал). Два вопроса - не извращенец ли я и как сделать отрисовать ховер?


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 18, 2011, 07:13
Два вопроса - не извращенец ли я и как сделать отрисовать ховер?
Для ховера нужно перегрузить event() и уже в нём следить за QEvent::HoverEnter/QEvent::HoverLeave.
Может проще будет запихнуть QTabBar с одним табом?


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 18, 2011, 07:58
А не проще будет создай label  с иконкой и с родителем Tab Widget? правда расчет расположения останется на вас, но все ховеры, евенты будут в вашей же власти.

PS на TabWidgete не проверял, но с modelView'рами работает.


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 18, 2011, 10:02
А не проще будет создай label  с иконкой и с родителем Tab Widget? правда расчет расположения останется на вас, но все ховеры, евенты будут в вашей же власти.
Дык QTabWidget::setCornerWidget() именно для этого и был сделан.
Мало того, если сам будешь позиционировать этот cornerWidget, то QTabWidget растянет QTabBar на всю ширину QTabWidget-а и cornerWidget будет располагаться поверх какого-нибудь таба. Так что, имхо, совсем "не проще")


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 18, 2011, 10:07
Не совсем понял, таб виджет будет растягиваться отдельно от label, и даже не будет учитывать его при компоновке. И получится как раз наложение (как мяклей бякнуть по стеклу).

Хотя если велисопед сделан, то у меня вопросов нет, надо на нем ездить :)


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 18, 2011, 10:11
Не совсем понял, таб виджет будет растягиваться отдельно от label, и даже не будет учитывать его при компоновке. И получится как раз наложение (как мяклей бякнуть по стеклу).
Т.е. label будет поверх таба. И что, это по-твоему нормально?


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 18, 2011, 13:51
Подправил костыль в 1м посте (криво рисовалось на линупсе и винде, нужен и таббаррект и рект)
Так у кого-нибудь есть идеи, как наложить хотя бы серый фильтр поверх кнопки при ховере/нажатии?
У меня не рисуется альфа:(

Пока выглядит как-то так: http://mtgs.clan.su/andromeda/addtab.png (кнопка нажата)


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 18, 2011, 14:33
а положить css'ку на эту кнопку низя? Или не принимается?


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 18, 2011, 14:49
Еще раз - проблема не в кнопке, а том, что под ней (серый фон табвиджета, не таббара). QSS модифицирует кнопку, но она все равно смотрится инородно, занимая всю ширину таббара.


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 18, 2011, 14:54
Ну дык скинь скрины с закрашенной областью кнопки, потому что на той картинке, что ты выложил нигде вот блин не разглядеть. Сколько она занимает, где ее границы и прочая.

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

PS если я не въехал в тему, значит ты дал мало инфы :)


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 18, 2011, 15:01
http://mtgs.clan.su/andromeda/assistantbug.png

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


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 19, 2011, 08:36
Так убери рамку.

И вообще давай по частям (если есть у тебя на это время и желание).

1) у тя фон табвиджета установлен как и какой (чтоб воссоздать условия твои)
2) фон соответственно всего виджета.
3) величина табБара меняется или нет? (в будущем, сейчас, в перспективах)
4) вообще желательно было бы кусок проекта с оформлением, но вырезанной функциональностью.

PS все на усмотрение ваше, бояре


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 19, 2011, 09:50
Попробуй использовать обычную QToolButton с дефолтной отрисовкой без рамки:
Код
C++ (Qt)
QToolButton::setStyleSheet( "border: 0px" );


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 19, 2011, 10:07
Bepec
все стандартное, простой табвиджет и простой таббар, никаких стилей

Код:
{
...
    newTabButton = new TabBarButton();
    newTabButton->setIcon(QIcon(":/images/icons/addtab.png"));
    newTabButton->setIconSize(QSize(32,32));
    connect(newTabButton, SIGNAL(clicked()), q, SLOT(newTab()));

    tabWidget = new MyTabWidget;
    tabWidget->setDocumentMode(true);
    tabWidget->setMovable(true);
    tabWidget->setTabsClosable(true);
    tabWidget->setUsesScrollButtons(true);
    tabWidget->setCornerWidget(newTabButton);

    q->setCentralWidget(tabWidget);

    connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(onCurrentChanged(int)));
    connect(tabWidget, SIGNAL(tabCloseRequested(int)), q, SLOT(closeTab(int)));
    connect(tabWidget, SIGNAL(tabBarDoubleClicked()), q, SLOT(newTab()));
...
}
MyTabWidget отличается от QTabWidget'a тем, что вешает евент фильтр на таббар и кидает сигнал когда по тому даблкликают.


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 19, 2011, 10:13
2 Авварон
попробовал так?
Попробуй использовать обычную QToolButton с дефолтной отрисовкой без рамки:
Код
C++ (Qt)
QToolButton::setStyleSheet( "border: 0px" );
В этом случае кнопка будет прозрачной и без рамки, что имхо, тебе и нужно.


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 19, 2011, 10:18
GreatSnake
Багает.


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 19, 2011, 10:35
Чтоб было понятно, что мне не нравится в обычной кнопке - болтается как инородный элемент.


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 19, 2011, 11:58
А у самого QTabWidget documentMode() включен?


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 19, 2011, 12:05
Он кусок своего кода привел выше - там он его включает.


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 19, 2011, 12:56
Тогда предлагаю перегрузить только QToolButton::paintEvent():
Код
C++ (Qt)
class TabBarButton : public QToolButton
{
public:
   TabBarButton( QWidget* p ) : QToolButton( p )
   {
       setStyleSheet( "border: 0px" );
   }
   void paintEvent(QPaintEvent *e)
   {
       QPainter p(this);
 
       QStyleOptionTabBarBaseV2 opt;
       opt.init(this);
       // hardcoded document Mode
       opt.documentMode = true;
 
       int overlap = style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &opt, this);
       QRect rect;
       // hardcoded north position
       rect.setRect(0, size().height() - overlap, size().width(), overlap);
       opt.rect = rect;
 
       style()->drawPrimitive(QStyle::PE_FrameTabBarBase, &opt, &p, this);
 
       QToolButton::paintEvent( e );
   }
};


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 19, 2011, 13:21
Строка         QToolButton::paintEvent( e ); перекроет всё предыдущее рисование. Либо отрисовка полностью кастомна, либо полностью стандартна, другого тут не дано.


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 19, 2011, 13:42
Строка         QToolButton::paintEvent( e ); перекроет всё предыдущее рисование. Либо отрисовка полностью кастомна, либо полностью стандартна, другого тут не дано.
А ты уже пробовал? Или заранее делаешь выводы?


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 19, 2011, 13:43
Пробовал


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 19, 2011, 13:48
Пробовал
странно, т.к. setStyleSheet( "border: 0px" ) отменяет отрисовку фона кнопки в QToolButton::paintEvent().


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 19, 2011, 13:51
Можно сначала стандартный paintEvent запустить, а после уже свое накалякать. и спокойно прокатывает :)


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 19, 2011, 14:24
Попробовал еще раз. Либо мое рисование полностью перекрывает тулбатона, либо наоборот.


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 19, 2011, 15:15
Попытался запустить твой проект - и увы попал в несовместимость ) версию Qt и прочая спрашивать не буду - уже умаялся я креатору рот затыкать :P

to Авварон - если сначала пропечатать paintEvent его, а после добавить свой, ТО... получится прорисовка ЕГО, с калякой ТВОЕЙ дополнительно. так понятнее?


Название: Re: TabWidget::cornerButton
Отправлено: GreatSnake от Октябрь 19, 2011, 15:39
Попробовал еще раз. Либо мое рисование полностью перекрывает тулбатона, либо наоборот.
Да, похоже что это style-specific  :(


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 19, 2011, 16:48
Bepec
Я отрисовываю кусок тулбара поверх ВСЕГО ректа кнопки - то есть всё, что было нарисовано на кнопке, стирается моей рисовалкой. Ваш способ подошел, если бы я рисовал только иконку или часть ректа.


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 20, 2011, 08:06
Глупо ожидать, что если сбросить ядерную бомбу на город, то город будет стоять.

PS а смысл тогда в вашем маляве, если вы не отрисовываете поверх, а просто заливаете участок?


Название: Re: TabWidget::cornerButton
Отправлено: Авварон от Октябрь 20, 2011, 12:06
Bepec
Действительно, я всю тему пытаюсь объяснить что дефолтное рисование кнопки не подходит, даже скриншот сделал


Название: Re: TabWidget::cornerButton
Отправлено: Bepec от Октябрь 20, 2011, 12:12
Увы, без обид, но делали вы это недоходчиво :)

печаль :) как вариант рисуй сам изображение, и высчитывай клик по координатам :)