Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Igors от Июнь 19, 2014, 09:58



Название: Виджет с поведением окна
Отправлено: Igors от Июнь 19, 2014, 09:58
Добрый день

Внутри главного окна есть виджеты которые выглядят как окна, и по смыслу окна и есть. Но, к сожалению, поставить им флаг Qt::Window нельзя т.к. они должны быть внутри главного. Нужно пр нажатии на что угодно внутри такого виджета сделать raise чтобы он перекрыл другие (как окно при активации). Как это лучше реализовать?

- навесить фильтры на все внутренности (не нравится)
- перекрыть notify (лучше но придется отследить модальность и.т.п.)
- более элегантное решение?

Спасибо


Название: Re: Виджет с поведением окна
Отправлено: GreatSnake от Июнь 19, 2014, 14:18
- навесить фильтры на все внутренности (не нравится)
Почему не нравится? Заведите базовый класс, в котором и навесите фильтры.
Пихать всё в notify, имхо, как-то не серьёзно.


Название: Re: Виджет с поведением окна
Отправлено: kai666_73 от Июнь 19, 2014, 17:56
- навесить фильтры на все внутренности (не нравится)
Почему не нравится? Заведите базовый класс, в котором и навесите фильтры.
Пихать всё в notify, имхо, как-то не серьёзно.

Базовый класс? Оо. А какого типа?
Или имеется ввиду некий класс, который будет микшироваться во все типы виджетов на диалоге главном виджете?
Задачу не облегчит, а проблем добавит, потому-что энтот класс должен наследоваться от QObject.


Название: Re: Виджет с поведением окна
Отправлено: kai666_73 от Июнь 19, 2014, 18:03
- навесить фильтры на все внутренности (не нравится)

А если в самом диалоге виджете-ака-окно после setupUi (или чего там в конструкторе) пробежаться рекурсивно
Код:
parentWidget.findChildren<QWidget *>()
по всем widget-children-м и повесить на каждый фильтр?


Название: Re: Виджет с поведением окна
Отправлено: _OLEGator_ от Июнь 19, 2014, 18:47
Я бы использовал QGraphicsView/Scene для такого, нужный функционал там имеется.


Название: Re: Виджет с поведением окна
Отправлено: Igors от Июнь 19, 2014, 18:54
Почему не нравится? Заведите базовый класс, в котором и навесите фильтры.
Как-то "несообразно" - цель довольно мелкая, а тут "целое наследование"

А если в самом диалоге виджете-ака-окно после setupUi (или чего там в конструкторе) пробежаться рекурсивно ... по всем widget-children-м и повесить на каждый фильтр?
Так могут добавляться дынамычно.

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


Название: Re: Виджет с поведением окна
Отправлено: kai666_73 от Июнь 19, 2014, 22:17
Дынамично? - флаг в руки, добавляешь - вешай фильтр.

А насчет реализации - можно, наверно, как-то так
Код:
bool MyAutoRaiseWidget::eventFilter(QObject *obj, QEvent *event)
{
  if ( event->type() == QEvent::MouseButtonPress )
    raise();
  return QWidget::eventFilter(obj, event);
}
Не думаю, что raise будет генерить события типа QEvent::MouseButtonPress


Название: Re: Виджет с поведением окна
Отправлено: GreatSnake от Июнь 20, 2014, 09:44
Как-то "несообразно" - цель довольно мелкая, а тут "целое наследование"
Почему ???
Всё делается просто, вот компилируемый пример ( Qt4.8 ):
Код
C++ (Qt)
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QGridLayout>
#include <QToolBar>
#include <QToolButton>
#include <QGraphicsDropShadowEffect>
 
template< typename T > T findParent( QObject* o )
{
while( o )
{
if( T po = /*qobject_cast*/ dynamic_cast< T >( o ) )
return po;
o = o->parent();
}
return 0;
}
 
class SubWindow : public QMainWindow
{
public:
SubWindow( QWidget* p = 0 )
: QMainWindow( p )
{
setWindowFlags( windowFlags() & ~Qt::Window );
setAutoFillBackground( true );
 
QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect( this );
shadow->setColor( QColor( 0, 0, 0, 255 ) );
shadow->setOffset( QPointF( 0, 0 ) );
setGraphicsEffect( shadow );
shadow->setBlurRadius( 16 );
 
qApp->installEventFilter( this );
}
protected:
bool eventFilter( QObject* o, QEvent* e )
{
if( e->type() == QEvent::MouseButtonPress && o->isWidgetType() )
{
if( findParent< SubWindow* >( o ) == this )
raise();
}
return QMainWindow::eventFilter( o, e );
}
};
 
class MainWin : public SubWindow
{
public:
MainWin( QWidget* p = 0 )
: SubWindow( p )
{
QMenuBar* mbar = menuBar();
mbar->addMenu( "&File" );
mbar->addMenu( "&View" );
mbar->addMenu( "&Help" );
 
QToolBar* tbar = addToolBar( "" );
for( int i = 0; i < 5; i++ )
tbar->addAction( QString::number( i + 1 ) );
 
QWidget* bw = new QWidget;
QGridLayout* l = new QGridLayout( bw );
for( int r = 0; r < 5; r++ )
for( int c = 0; c < 5; c++ )
{
QToolButton* tb = new QToolButton;
tb->setText( QString( "%1:%2" ).arg( r ).arg( c ) );
l->addWidget( tb, r, c );
}
setCentralWidget( bw );
}
};
 
int main( int argc, char *argv[] )
{
QApplication a( argc, argv );
QWidget w;
QSize sz;
 
for( int i = 0; i < 3; i++ )
{
MainWin* mw = new MainWin( &w );
mw->adjustSize();
mw->move( i * 100 + 20, i * 100 + 20 );
sz = sz.expandedTo( mw->size() );
}
 
w.resize( sz.width() * 2 + 20 , sz.height() * 2 + 20 );
w.show();
return a.exec();
}
 


Название: Re: Виджет с поведением окна
Отправлено: Igors от Июнь 20, 2014, 10:51
Элегантный примерчик, спасибо.
Код
C++ (Qt)
qApp->installEventFilter( this );
 
Ага, сначала фильтр(ы) QCoreApplication получает управление (этого я не знал). Тогда может еще лучше навесить один такой фильтр и в нем искать парента с типом MyWindow?


Название: Re: Виджет с поведением окна
Отправлено: GreatSnake от Июнь 20, 2014, 10:54
Тогда может еще лучше навесить один такой фильтр и в нем искать парента с типом MyWindow?
Ну да, в top-level окне.