Russian Qt Forum

Qt => Общие вопросы => Тема начата: PulSar.CE3194694 от Январь 27, 2013, 11:33



Название: Перенос виджета в пределах окна с помощью мыши
Отправлено: PulSar.CE3194694 от Январь 27, 2013, 11:33
Добрый день.
Как перенести виджет по экрану с зажатой ЛКМ? Смотрел примеры Drag and Drop, лабуда какая-то, ничего не понял как делать.


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: Bepec от Январь 27, 2013, 11:37
Отлавливаем нажатие, далее ловим движения мыши. Куда мышь - туда и виджет.


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: PulSar.CE3194694 от Январь 27, 2013, 11:53
А пример можно?
Код:
void MyWidget::mousePressEvent(QMouseEvent *e)
 {
     if (e->button() == Qt::LeftButton)
     {
         this->move(e->globalPos());
     }
 }
Так не работает.


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: iroln от Январь 27, 2013, 13:08
Надо менять позицию виджета в mouseMoveEvent же! Вы же мышь двигаете. В mousePressEvent нужно запоминать координаты, а в mouseMoveEvent использовать смещение, вычитая из запомненных текущие.

Как то так (это просто пример того, как надо делать, сами его допилите, +/- там и т.п.):

Код
void MyWidget::mousePressEvent(QMouseEvent *e)
{
    if (e->button() == Qt::LeftButton)
    {
        this->posPrev = e->globalPos();
    }
}
 
void MyWidget::mouseMoveEvent(QMouseEvent *e)
{
    QPoint dt = QPoint(this->posPrev - e->globalPos());
    this->move(this->pos()-dt);
 
    this->posPrev = e->globalPos();
}

Вот пример на Python, который точно работает. :)

Код
Python
class MyWidget(QWidget):
 
   def __init__(self, parent=None):
       super(MyWidget, self).__init__(parent)
       self.prevPos = QPoint(0, 0)
 
   def mousePressEvent(self, event):
       self.prevPos = event.globalPos()
 
   def mouseMoveEvent(self, event):
       dt = self.prevPos - event.globalPos()
       self.move(self.pos()-dt)
       self.prevPos = event.globalPos()
 


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: LEO от Январь 27, 2013, 18:57
посмотри примеры в примере, может найдешь что тебе надо
...QtSDK\Examples\4.7\draganddrop


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: PulSar.CE3194694 от Январь 27, 2013, 19:36
посмотри примеры в примере, может найдешь что тебе надо
...QtSDK\Examples\4.7\draganddrop
Так смотрел уже, лабуда какая-то... Какие-то мимы, пиксмапы и прочее. Не прозрачно как-то.
А вот предыдущая схема прозрачная и работает. Но только один раз. После того, как один раз перетащил виджет, больше его подцепить мышью не могу. И все виджеты, которые на нем, становятся недосягаемыми (мои лейблы не хотят больше редактироваться)


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: iroln от Январь 27, 2013, 21:29
Так смотрел уже, лабуда какая-то... Какие-то мимы, пиксмапы и прочее...
Ну так по уму всегда чуть сложнее, зато надёжнее и вернее! :)
Чего у вас там не получается? Можете показать минимальный проект, который можно скомпилировать и запустить?


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: PulSar.CE3194694 от Январь 28, 2013, 07:27
Попытаюсь разобраться.
Нет, все работает, оказывается, что виджет, который пытаюсь перенести не является виджетом верхнего уровня, и когда его перетаскиваю в другую часть экрана, он начинает закрываться другим прозрачным виджетом более высокого уровня.


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: GreatSnake от Январь 28, 2013, 10:44
он начинает закрываться другим прозрачным виджетом более высокого уровня.
Нужно поднимать виджет через raise().
Вот работающий пример:
Код
C++ (Qt)
#include <QApplication>
#include <QToolButton>
#include <QScrollArea>
#include <QMouseEvent>
 
class Button : public QToolButton
{
public:
Button( const QString& s, QWidget* parent = 0 )
: QToolButton( parent )
{
setText( s );
setMouseTracking( true );
}
 
protected:
void mouseMoveEvent( QMouseEvent* e )
{
if( drag_pos_ != QPoint() )
{
move( pos() + ( e->globalPos() - drag_pos_ ) );
drag_pos_ = e->globalPos();
}
}
void mousePressEvent( QMouseEvent* e )
{
raise();
drag_pos_ = e->globalPos();
setCursor( QCursor( Qt::SizeAllCursor ) );
}
void mouseReleaseEvent( QMouseEvent* e )
{
drag_pos_ = QPoint();
unsetCursor();
}
private:
QPoint drag_pos_;
};
 
 
int main( int argc, char** argv )
{
QApplication app( argc, argv );
QScrollArea w;
 
Button b1( "Drag me", w.viewport() );
b1.move( 10, 10 );
 
Button b2( "Drag me", w.viewport() );
b1.move( 40, 40 );
 
w.show();
return app.exec();
}
 


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: Igors от Январь 28, 2013, 10:53
Код
C++ (Qt)
move( pos() + ( e->globalPos() - drag_pos_ ) );
drag_pos_ = e->globalPos();
 
А если юзверь увлекся и вынес виджет за пределы parent'а - как потом его достать?


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: GreatSnake от Январь 28, 2013, 10:56
А если юзверь увлекся и вынес виджет за пределы parent'а - как потом его достать?
Тут 2 варианта: либо запрещать двигать за пределы окна, либо организовать прокрутку.


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: panAlexey от Январь 28, 2013, 22:40
Код
C++ (Qt)
move( pos() + ( e->globalPos() - drag_pos_ ) );
drag_pos_ = e->globalPos();
 
А если юзверь увлекся и вынес виджет за пределы parent'а - как потом его достать?
Используй опыт 1С-а. Его редактор диалогов окном самого виджета не ограничивается.
ПС. Очень удобно. Можно "стащить" неиспользуемые контролы без развязывания зависимостей за экран и забыть про них...
Особенно удобно ЭТО при компоновке/перекомпоновке виджетов - стаскиваешь вниз формы, а потом по одному закидываешь на свои места..


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: PulSar.CE3194694 от Январь 29, 2013, 07:24
А если по науке делать, то какое решение все же вернее: через Qdrag или MouseEvent'ы?


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: panAlexey от Январь 29, 2013, 11:12
А если по науке делать, то какое решение все же вернее: через Qdrag или MouseEvent'ы?
В данном случае через моус-эвенты наверное. Тебе же таскать в пределах формы прийдется.
Надо видеть размер объекта и как вписываются.
ПС. к верхнему посту: нельза в 1С-ном редакторе перетащить контрол вверх или влево за границу. Вниз и вправо - можно.


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: iroln от Январь 29, 2013, 17:41
Используй опыт 1С-а. Его редактор диалогов окном самого виджета не ограничивается.
ПС. Очень удобно. Можно "стащить" неиспользуемые контролы без развязывания зависимостей за экран и забыть про них...
Особенно удобно ЭТО при компоновке/перекомпоновке виджетов - стаскиваешь вниз формы, а потом по одному закидываешь на свои места..
Да что там далеко ходить? Qt Designer же так работает! :)


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: panAlexey от Январь 29, 2013, 17:56
Используй опыт 1С-а. Его редактор диалогов окном самого виджета не ограничивается.
ПС. Очень удобно. Можно "стащить" неиспользуемые контролы без развязывания зависимостей за экран и забыть про них...
Особенно удобно ЭТО при компоновке/перекомпоновке виджетов - стаскиваешь вниз формы, а потом по одному закидываешь на свои места..
Да что там далеко ходить? Qt Designer же так работает! :)
вы не правы. В Qt Designer нельзя вынести виджет(ы) за пределы редактируемой формы, а потом втащить обратно.
По крайней мере в Qt Creator 2.4.1.
Виджет режется если он выходит за границу формы.


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: iroln от Январь 29, 2013, 19:37
В Qt Designer ничего не режется. Появляются полосы прокрутки если вытащить виджет за пределы рабочей области. В QtCreator вообще виджет таскать нельзя, только изменять размеры, что так же приводит к появлению полос прокрутки. Или вы что-то другое имеете ввиду?


Название: Re: Перенос виджета в пределах окна с помощью мыши
Отправлено: panAlexey от Январь 29, 2013, 20:54
В Qt Designer ничего не режется. Появляются полосы прокрутки если вытащить виджет за пределы рабочей области. В QtCreator вообще виджет таскать нельзя, только изменять размеры, что так же приводит к появлению полос прокрутки. Или вы что-то другое имеете ввиду?
Скрин покажи.