Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Fregloin от Июнь 07, 2011, 13:05



Название: Перехват фокуса в дочерних виджетах
Отправлено: Fregloin от Июнь 07, 2011, 13:05
Пишу свой инспектор объектов для миниSCADA.
Создал наследника от QWidget EditableWidget, задача которого разместить в себе дочерний виджет (обычно это будет либо lineEdit либо textEdit).
При получении фокуса, будет рядом отображаться кнопка с текстом "...", при нажатии на которую нужно послать сигнал.
При потере фокуса кнопка исчезает. Суть понятна, это стандартная фишка всех инспекторов объектов.
Сами эти виджеты я распологаю в таблице методом setCellWidget. Про делегаты я слышал но пока не вникал. при чем, виджеты будут встраиваться разные.
Код:
QEditableWidget::QEditableWidget(QWidget *parent) :
    QWidget(parent)
{
    ftoolButton = NULL;
    feditableWidget = NULL;
    setFocusPolicy(Qt::ClickFocus);
}

void        QEditableWidget::setEditableWidget(QWidget  * EditableWidget)
{
    if(feditableWidget!=EditableWidget)
    {
        setUpdatesEnabled(false);
        if(feditableWidget)
        {
            setFocusProxy(NULL);
            delete feditableWidget;
            delete ftoolButton;
        }
        feditableWidget = EditableWidget;
        if(feditableWidget)
        {
            feditableWidget->setParent(this);
            feditableWidget->setFocusPolicy(Qt::NoFocus);
            feditableWidget->setGeometry(rect());
        }
        setUpdatesEnabled(true);
    }
}

void    QEditableWidget::focusInEvent(QFocusEvent * event)
{
    if(feditableWidget)
    {
        feditableWidget->setGeometry(rect().adjusted(-1,-1,geometry().width()-geometry().height(),0));
    }
    ftoolButton = new QToolButton;
    ftoolButton->setText("...");
    ftoolButton->setParent(this);
    ftoolButton->setGeometry(rect().adjusted(geometry().width()-geometry().height(),-1,-1,0));
    ftoolButton->show();
    connect(ftoolButton,SIGNAL(clicked()),this,SIGNAL(editButtonClicked()));
    QWidget::focusInEvent(event);
}

void    QEditableWidget::focusOutEvent(QFocusEvent * event)
{
    QWidget::focusOutEvent(event);
    delete ftoolButton;
    if(feditableWidget) feditableWidget->setGeometry(rect());
}
Проблема, как сделать так, что бы отловить событие получение фокуса моим виджетом, затем отобразить кнопку, а потом установить фокус ввода на дочерний виджет, при этом отловить потерю фокуса уже в дочернем виджете что бы кнопка исчезла.


Название: Re: Перехват фокуса в дочерних виджетах
Отправлено: GreatSnake от Июнь 07, 2011, 13:22
Цитировать
Про делегаты я слышал но пока не вникал.
А зря, т.к. не мешало бы вникнуть, чтобы не городить такой огород.


Название: Re: Перехват фокуса в дочерних виджетах
Отправлено: Fregloin от Июнь 07, 2011, 13:59
я и вникну, но позже, так как надо сделать готовую прогу чем быстрее тем лучше, минимально работающий вариант.


Название: Re: Перехват фокуса в дочерних виджетах
Отправлено: GreatSnake от Июнь 08, 2011, 12:40
я и вникну, но позже, так как надо сделать готовую прогу чем быстрее тем лучше, минимально работающий вариант.
Вот тебе более-менее работающий пример:
Код
C++ (Qt)
#include <QApplication>
#include <QTableWidget>
#include <QLineEdit>
#include <QToolButton>
#include <QHBoxLayout>
 
class CellLineEdit : public QWidget
{
public:
CellLineEdit( QWidget* p = 0 )
: QWidget( p )
{
QHBoxLayout* l = new QHBoxLayout( this );
l->setContentsMargins( 0, 0, 0, 0 );
l->setSpacing( 0 );
 
le_ = new QLineEdit;
le_->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
l->addWidget( le_ );
 
btn_ = new QToolButton;
btn_->setText( "..." );
btn_->setFocusPolicy( Qt::NoFocus );
btn_->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
btn_->hide();
l->addWidget( btn_ );
 
setFocusPolicy( Qt::StrongFocus );
 
le_->installEventFilter( this );
}
bool eventFilter( QObject* o, QEvent* e )
{
if( o == le_ )
{
if( e->type() == QEvent::FocusIn )
btn_->show();
else if( e->type() == QEvent::FocusOut )
btn_->hide();
}
return false;
}
void focusInEvent( QFocusEvent* e )
{
QWidget::focusInEvent( e );
le_->setFocus();
}
 
QLineEdit* le_;
QToolButton* btn_;
};
 
int main( int argc, char** argv )
{
QApplication app( argc, argv );
QTableWidget tw;
 
tw.setRowCount( 5 );
tw.setColumnCount( 5 );
 
for( int i = 0; i < tw.rowCount(); i++ )
for( int j = 0; j < tw.columnCount(); j++ )
tw.setCellWidget( i, j, new CellLineEdit );
 
tw.show();
return app.exec();
}
 
Сигналы на кнопку повесишь сам)
Только я никак не могу понять почему-то при нажатии на кнопку она не отжимается :(
Имхо, вся бодяга с фокусом должна решаться через делегаты и cellWidget() для этого не рассчитан.


Название: Re: Перехват фокуса в дочерних виджетах
Отправлено: Fregloin от Июнь 09, 2011, 12:18
а где можно почитать про делегаты, в моем случае что бы реализовать подобный инспектор объектов, как в самом креаторе или наподобие делфи?
свойств отображаться будет не много, порядка 4-10, максимум 15.


Название: Re: Перехват фокуса в дочерних виджетах
Отправлено: GreatSnake от Июнь 09, 2011, 12:45
а где можно почитать про делегаты, в моем случае что бы реализовать подобный инспектор объектов, как в самом креаторе или наподобие делфи?
свойств отображаться будет не много, порядка 4-10, максимум 15.
Программирование модель/представление (http://doc.crossplatform.ru/qt/4.6.x/model-view-programming.html).
Готовый QPropertyEditor (http://qt-apps.org/content/show.php/QPropertyEditor?content=68684) виджет. Там же много чего ещё найдёшь)