Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: leonike от Апрель 28, 2011, 19:51



Название: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 28, 2011, 19:51
Собственно задача - написать свой заголовок окна. С функциональной частью проблем не возникло, показываю widget предварительно задав флаг окна FramelessWindowHint, и запускаю экземпляр класса TitleBar (класс заголовка окна).

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


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: Denjs от Апрель 28, 2011, 20:18
.setStyleSheet() не? или ваш TitleBar - он не Qt-шный? в ассистанте смотрели перед тем как в гугле рыться?


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 28, 2011, 20:22
.setStyleSheet() не? или ваш TitleBar - он не Qt-шный? в ассистанте смотрели перед тем как в гугле рыться?

QStyleOptionTitleBar ?

TitleBar конечно кутишный

а какими опциями задавать прозрачность в qss?
закругленность вроде параметр border-radius, но он не срабатывает

И в Assistant смотрел, но ничего не увидел ) Если знаете, ткните носом

Qt 4.7.2


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 28, 2011, 20:52
Можно и без qss попробовать. Например, как реализовано в QSplashScreen


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 28, 2011, 21:03
Вообще что-то подобное можно добиться установив атрибут:

widget.setAttribute(Qt::WA_TranslucentBackground);

Однако все равно визуальный эффект очень далек от идеала.

Можно и без qss попробовать. Например, как реализовано в QSplashScreen
А можно поподробней?


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: Alex Custov от Апрель 28, 2011, 21:13
без композитного оконного менеджера в иксах края будут рваные


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 28, 2011, 21:43
без композитного оконного менеджера в иксах края будут рваные
ну собственно заказчику все равно, как в иксах будет выглядеть )

но у меня все равно и в иксах и в винде рвано выглядит, если вы про Qt::WA_TranslucentBackground


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 28, 2011, 21:56
Ну, может быть, как-нибудь так (делал небольшую программку):

Код:
DropArea::DropArea(QWidget* parent)
  : QLabel(parent)
{
  QPixmap splashImage(":/images/globe.png");
  setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::SplashScreen);
  setPixmap(splashImage);
  setMask(splashImage.mask());
}

Где globe.png картинка с закругленными углами. Флаги оставил свои.


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 28, 2011, 22:47
Ну, может быть, как-нибудь так (делал небольшую программку):

Код:
DropArea::DropArea(QWidget* parent)
  : QLabel(parent)
{
  QPixmap splashImage(":/images/globe.png");
  setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::SplashScreen);
  setPixmap(splashImage);
  setMask(splashImage.mask());
}

Где globe.png картинка с закругленными углами. Флаги оставил свои.

отлично, спасибо, получилось картинку вывести на экран, буду экспериментировать с моим TitleBar


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 28, 2011, 23:08
О результатах отпишитесь, если не сложно  :)


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: Denjs от Апрель 28, 2011, 23:38
TitleBar конечно кутишный
o_0  ??? имя класса скажите пожалуйста?


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 28, 2011, 23:54
О результатах отпишитесь, если не сложно  :)

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

o_0  ??? имя класса скажите пожалуйста?

а вы что имели ввиду? я подумал, что кутишный в данном контексте = реализован средствами qt


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 29, 2011, 00:04
Попробуйте сделать вот так: (опять выдержка из кода)

Код:
int main(int argc, char* argv[])
{
  QCoreApplication::setApplicationName("TorgiAdder");

  QApplication a(argc, argv);
  [b]a.setQuitOnLastWindowClosed (false);[/b]


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 29, 2011, 00:06
Насчет флага Qt::Popup не уверен, что он нужен


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 29, 2011, 00:13
Насчет флага Qt::Popup не уверен, что он нужен
а как? если не применять его (или Qt::SplashScreen), то на панели задач отображается и titlebar и виджет приложения.
а надо, чтобы только что-то одно.
если кликнуть по виджету с флагом Qt::SplashScreen, то он делает hide, надо этого избежать

либо есть другой флаг, скрывающий окно на пенили задач, либо флаг, предотвращающий hide по клику, либо другие хаки использовать


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 29, 2011, 00:15
кажется, нашел такой флаг - Qt::Drawer


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 29, 2011, 00:25
Покажите кусок кода, тогда проще будет разбираться


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 29, 2011, 00:44
Покажите кусок кода, тогда проще будет разбираться
да все работает, покажу завтра, сегодня уже отрубаюсь.

проблема в том, что приведенный тобой пример, как вывести прозрачную иконку прекрасно работает в Linux, но не работает в Windows, вместо прозрачности рисуется фон.


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 29, 2011, 07:25
Не верю, так как сам вообще-то писал программу под вин. Опровержение могу выложить в виде скриншота


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 29, 2011, 07:55
Вот еще я писал о классе Pretty OSD из программы Clementine - http://slow-tone.blogspot.com/2011/04/qt-pretty-osd.html ? скриншот прилагается


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 29, 2011, 08:55
titlebar.h:
Код:
#ifndef TITLEBAR_H
#define TITLEBAR_H

#include <QtGui/QLabel>

QT_BEGIN_NAMESPACE
class QPushButton;
class QPixmap;
class QPoint;
QT_END_NAMESPACE

class TitleBar : public QLabel
{
    Q_OBJECT

private:
    QPushButton* _minimizeButton, * _closeButton;
    QPixmap _titleBarPixmap;

    QPoint startPos;

    bool _isPressed;

    QWidget* contentWidget;

protected:
    void mousePressEvent(QMouseEvent* );
    void mouseReleaseEvent(QMouseEvent* );
    void mouseMoveEvent(QMouseEvent* );

public:
    TitleBar(QWidget * contentWidget);
    ~TitleBar();

public slots:
    void show();
    void move(int x, int y);
    void close();
    void showMinimized();
};

#endif // TITLEBAR_H

titlebar.cpp:
Код:
#include "titlebar.h"

QT_BEGIN_HEADER
#include <QPushButton>
#include <QPainter>
#include <QImage>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QPoint>
#include <QApplication>
#include <QPixmap>
#include <QBitmap>
#include <QShowEvent>
QT_END_HEADER

TitleBar::TitleBar(QWidget* contentWidget) :
      _titleBarPixmap(":/images/title_bar.png")
{
    _isPressed = false;

    _closeButton = new QPushButton;
    _minimizeButton = new QPushButton;

    QString qss = "";

    qss.append("QPushButton { border: none; background-image: url(:images/button/window/line.png); background-position: center center; background-repeat: none; height: 16px; width: 16px; }");
    qss.append("QPushButton:hover { border: none; background-image: url(:images/button/window/line_hover.png); background-position: center center; background-repeat: none; height: 16px; width: 16px; }");
    qss.append("QPushButton:pressed { border: none; background-image: url(:images/button/window/line_active.png); background-position: center center; background-repeat: none; height: 16px; width: 16px; }");

    _minimizeButton->setStyleSheet(qss);

    qss = "";
    qss.append("QPushButton { border: none; background-image: url(:images/button/window/close.png); background-position: center center; background-repeat: none; height: 16px; width: 16px; }");
    qss.append("QPushButton:hover { border: none; background-image: url(:images/button/window/close_hover.png); background-position: center center; background-repeat: none; height: 16px; width: 16px; }");
    qss.append("QPushButton:pressed { border: none; background-image: url(:images/button/window/close_active.png); background-position: center center; background-repeat: none; height: 16px; width: 16px; }");

    _closeButton->setStyleSheet(qss);

    QHBoxLayout* layout = new QHBoxLayout;
    layout->addStretch();
    layout->addWidget(_minimizeButton);
    layout->addWidget(_closeButton);
    layout->addSpacing(10);

    setLayout(layout);

    setFixedHeight(48);
    setFixedWidth(368);

    this->contentWidget = contentWidget;
    this->contentWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Drawer);

    connect(_closeButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(_minimizeButton, SIGNAL(clicked()), this, SLOT(showMinimized()));

    setPixmap(_titleBarPixmap);
    setMask(_titleBarPixmap.mask());
}

TitleBar::~TitleBar()
{

}

void TitleBar::mousePressEvent(QMouseEvent* event)
{
    if (event->button() == Qt::LeftButton) {
        _isPressed = true;
        startPos = event->pos();
    }
}

void TitleBar::mouseReleaseEvent(QMouseEvent* event)
{
    if(event->button() == Qt::LeftButton) {
        _isPressed = false;
    }
}

void TitleBar::mouseMoveEvent(QMouseEvent* event)
{
    if (_isPressed) {
        move(event->globalX() - startPos.x(), event->globalY() - startPos.y());
    }
}

void TitleBar::show()
{
    QWidget::show();
    contentWidget->show();
    contentWidget->move(x(), y() + height());
}

void TitleBar::move(int x, int y)
{
    QWidget::move(x, y);
    contentWidget->move(x, y + height());
}

void TitleBar::close()
{
    QWidget::close();
    contentWidget->close();
}

void TitleBar::showMinimized()
{
    QWidget::showMinimized();
}

Qt 4.7.2
В Linux все работает почти идеально. В Win вместо прозрачного фона отображается системный цвет и после сворачивания окна разворачивается только заголовок, после переключения с окна приложения на окно любой другой программы и обратно остается заголовок, а contentWidget делает hide, в Linux в таком случае contentWidget возвращается на место


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: Igors от Апрель 29, 2011, 10:29
[/оффтор]

У меня иногда возникают иногда "позывы" сделать в UI что-нибудь "эдакое" (да и у других наверное тоже). Я прекрасно понимаю что это будет "заброшено и забыто" (когда первая волна энтузиазма пойдет и надо будет вернуться к текучке). В таких случаях может стоит подумать: а дизайнер ли я? Ну закруглю я титул, дальше что? Смогу ли я подобрать цвета, стили контролов и многое др. так чтобы было не только "оригинально" но и другим нравилось? Или просто так, ну делаю пока мне это интересно :) Такой взгляд помогает сэкономить немало времени


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: GreatSnake от Апрель 29, 2011, 10:45
2 Igors :
+1
Мало того, частенько наступает момент, когда всё это начинает безбожно глючить.
Имхо, коли уж очень хочется "поизвращаться" над видом, то нужно иметь опциональный переключатель к стандартному виду.


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 29, 2011, 11:07
А почему вы не рисуете этот titleBar на самом contentWidget? Меньше проблем было бы


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: leonike от Апрель 29, 2011, 15:36
2 Igors :
+1
Мало того, частенько наступает момент, когда всё это начинает безбожно глючить.
Имхо, коли уж очень хочется "поизвращаться" над видом, то нужно иметь опциональный переключатель к стандартному виду.

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

но заказчик хочет дизайн, который сделали его дизайнеры

А почему вы не рисуете этот titleBar на самом contentWidget? Меньше проблем было бы

хотел сначала реализовать так, вечером попробую, как вы сказали, мб что-то получится


Название: Re: Свой заголовок окна и прозрачность.
Отправлено: SeverusSnape от Апрель 29, 2011, 16:06
И посмотрите все-таки код pretty osd из ответов выше.