Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: SOL от Август 04, 2009, 05:39



Название: Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 04, 2009, 05:39
Чтобы добраться до сути моего вопроса, надо рассказать небольшую предысторию.
Началось, собственно, с того, что я поставил на комп Windows 7(Впринципе, выглядит она также как и Vista) Так вот, при включении соответствующей графической опции, все окна в винде становятся прозрачными и слегка размывают фон, находящийся за ними( см. скрин 1 ). Смотрится довольно красиво. Однако разрабы Nero пошли дальше. Как видно из скрина 2, окно программы размывает всё, что находится за самим окном, притом смотрится это эффектно и не нагружает интерфейс. Собственно, такую вот штуку я и хочу провернуть.
Первая мысль была - снести фон виджета. Как не пытался, не получается сделать его прозрачным. Пробывал различные варианты с backgroundRole().
З.Ы. функция setWindowOpacity() не подходит. Она дает совершенно другой эффект - делает всё окно прозрачным, а мне нужно, чтобы такие элементы как кнопки и т.п. оставались непроницаемыми.


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: m_ax от Август 04, 2009, 07:01
А что если копировать изображение, то что находится под приложением, применять к нему какой нить фильтр (размытие там али исчо чаво) и в paintEvent е вставлять его на фон...

Теперь вопрос: как получить изображение той области над которой находится приложение средствами Qt?   ???

 



Название: Re: Как сделать фон виджета прозрачным?
Отправлено: registrationfedser87 от Август 04, 2009, 07:22
Посмотри демку qt /demos/deform. Там что-то подобное(линза двигается и увеличивает всё что за ней)


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: fuCtor от Август 04, 2009, 10:22
http://wiki.qtcentre.org/index.php?title=ARGB-Widgets посмотрите вот этот пример. Думаю можно что-то почерпнуть из этого.


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: SASA от Август 04, 2009, 12:44
Теперь вопрос: как получить изображение той области над которой находится приложение средствами Qt?   ???

QApplication::desktop()
QWidget::render
QWidget::frameGeometry ()


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: MoPDoBoPoT от Август 04, 2009, 13:12
Вот еще по теме: Полупрозрачность (http://www.forum.crossplatform.ru/index.php?showtopic=2270). Там далее SABROG рассказывает про атрибут Qt::WA_TranslucentBackground (с примерами), появившийся в Qt, начиная с версии 4.5


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 04, 2009, 16:53
2 shapoclak Хе, ну ты мазахист! Впринципе, такая идея и меня посещала, но зачем самому блюр писать, если в винде он уже предусмотрен, притом там не просто блюр. К нему добавляется эффект падающих лучей, обратите внимание.

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

2 MoPDoBoPoTА вот это уже теплее, сейчас затестим. Только вот Qt у меня старенький(4.3), надо бы поискать поновее.


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 04, 2009, 17:41
Кстати, вот что заметил. Данная фишка с прозрачностью работает в Nero только под Windows7. Окно этой же версии Nero под виндой XP не прозрачно, поэтому складывается такое впечатление, что предложенный метод тут не сработает. К сожалению, Qt я смогу скачать только ночью, поэтому и результаты позже будут.


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 05, 2009, 21:13
Итак, данные ссылки, конечно, инетесные, но мне не подошли.

В интернете нашел кусок кода на неизвестном мне языке(пишу я под С++)

Код:
class Window(QWidget):
        def __init__(self, *args):
                QWidget.__init__(self, *args)
                self.setLayout(QVBoxLayout())
                self.layout().addWidget(QLabel("This is the text"))

                # let the whole window be a glass
                self.setAttribute(Qt.WA_NoSystemBackground)
                from ctypes import windll, c_int, byref
                windll.dwmapi.DwmExtendFrameIntoClientArea(c_int(self.winId()), byref(c_int(-1)))
        def mousePressEvent(self, event):
                self.repaint()

Код дает вот такой эффект как показано на рисунке: делает весь виджет полупрозрачным и размытым - какраз то, что мне надо.

вот ссылка на тему: http://stackoverflow.com/questions/453069/qt-erase-background-windows-aero-glass (http://stackoverflow.com/questions/453069/qt-erase-background-windows-aero-glass)


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 05, 2009, 23:55
Хех....что-то глухо тут. Ну ладно. Сутки убил на эту вестч, теперь хотябы всё работает! Тестил под Windows 7 x64, VS2005, Qt v4.3.
Код:
#include <QtGui>
#include <atlbase.h>
#include <uxtheme.h>
void VistaGlass( int * );
int main( int argc, char *argv[] )
{
QApplication a( argc, argv );
QWidget w;
QVBoxLayout *lyt = new QVBoxLayout();
QPushButton *bt = new QPushButton( "Push me!" );
QLabel *lbl = new QLabel( "Yahoo! I was do it!!!" );
lbl->setAlignment( Qt::AlignCenter );
w.setAttribute( Qt::WA_NoSystemBackground );
VistaGlass( ( int* )w.winId() );
w.setLayout( lyt );
w.show();
w.repaint();
w.resize( 300, 450 );
a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
return a.exec();
};

void VistaGlass( int *Handle )
{
HMODULE dwm = ::LoadLibrary( L"dwmapi.dll" );
if(dwm)
{
typedef HRESULT (WINAPI *pDwmExtendFrameIntoClientArea)(HWND, void * MARGINS);
pDwmExtendFrameIntoClientArea procAddr = (pDwmExtendFrameIntoClientArea)::GetProcAddress(dwm, "DwmExtendFrameIntoClientArea");
if(procAddr)
{
MARGINS a = {0,0,1000,0};
HRESULT hr = (procAddr) ((HWND)Handle,&a);
}
::FreeLibrary(dwm);
}
};
Да, и ещё. в библиотеке dwmapi.dll находится ещё куча полезных функций для интерфейса, описание тут :
http://msdn.microsoft.com/ru-ru/magazine/cc163435.aspx (http://msdn.microsoft.com/ru-ru/magazine/cc163435.aspx)


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: MoPDoBoPoT от Август 06, 2009, 00:06
Это написано на питоне (Python + PyQt).
Этот код будет работать только на компьютере под управлением Windows Vista (или выше), на котором выполняется диспетчер окон рабочего стола (DWM) с включенным эффектом прозрачного стекла.

Цитировать
DwmExtendFrameIntoClientArea является функцией диспетчера окон рабочего стола, которая расширяет фрейм до размера клиентской области. Функция принимает два параметра: дескриптор окна и структуру MARGINS. Структура MARGINS используется для того, чтобы сообщить диспетчеру окон рабочего стола, насколько следует расширить фрейм в клиентской области.

Это не кроссплатформенное решенеие, в общем...


Название: Re: [solved]Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 07, 2009, 12:02
Хммм....всё оказалось не так хорошо, как я предполагал. При попытке разместить на данном виджете QListView с прозрачным фоном, возник такой вот глюк. То есть программа не перерисовывает то, что находится под viewport 'ом QListView виджета. Для того, чтобы сделать фон в QListView  прозрачным, я использовал давольно варварский метод : viewport()->setAttribute(Qt::WA_NoSystemBackground);
Может кто подскажет, как устранить этот косяк?


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 09, 2009, 02:01
Понял, что QListView тут не при чем. ;D
Когда я пытаюсь перерисовывать любые объекты(изменение текста в QLabel, удаления виджета из лэйаута и т.п.) на прозрачном окне, возникают похожие глюки - старая картинка(виджеты и всё остальное) не затирается, а новая рисуется поверх старой.
Однако, старая картинка исчезает при изменении размеров окна. Собственно, как затереть программно эту тарую картинку?


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: Igors от Август 09, 2009, 13:23
Добрый день

С интересом прочитал эту thread и вспомнил что когда-то пытался сделать подобное на Mac платформе. Там с полу/прозрачностью поприятнее, хотя приключений тоже хватает. Дальше экспериментов дело не пошло ввиду:

- неяcно как я буду переносить это с одного framework'а на другой. Например, ну ладно, работает это в Carbon, а что будет в Cocoa? (а переходить прийдется, все равно заставят). Если нужно поддерживать еще и Windows - трудности возрастут многократно.

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

Но это прекрасная задача для Qt - тянет как минимум на половину новой версии  ;-) Так что имеет смысл написать им feature request, и, может быть, Вас заметят :-)


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 09, 2009, 14:45
Что-то не всё я понял из вышесказанного...
Так всё же, этот баг фиксится, или ждать новой версии? Просто я компилил под Qt 4.3, авось в последней данного бага не будет... осталось только собрать.


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: lit-uriy от Август 09, 2009, 20:46
>>Просто я компилил под Qt 4.3
С 4.3 до 4.5 много воды утекло, пробуй 4.5


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: SOL от Август 11, 2009, 15:56
ГЫ) Qt 4.5.2 no comertical + vs2005 - и всё заработало ;D
Решено


Название: Re: Как сделать фон виджета прозрачным?
Отправлено: Andrew12 от Март 07, 2011, 12:04
А не мог бы скинуть примерчик того, что удалось?