(C++) QGraphicsProxyWidget example 5
February 24, 2017 · View on GitHub
(C++)
QGraphicsProxyWidget example 5
QGraphicsProxyWidget example 5 is a QGraphicsProxyWidget example.
The final goal is to be able to move the MyItem, even when MyItem has a focusable QLineEdit. This example is the first step in reaching this goal. This is accomplished by letting the original QWidget emit a signal on a mouse press. The QGraphicsView looks up the QGraphicsProxyWidget corresponding to the MyItem and let it follow the mouse cursor. Note that the QLineEdit is disabled: when enabling it, after the first time focus is given to a QLineEdit, it never releases it. Yet...
View a screenshot of
'CppQGraphicsProxyWidgetExample5' (png)
View a screenshot of
'CppQGraphicsProxyWidgetExample5' (png)
Download the Qt Creator project
'CppQGraphicsProxyWidgetExample5' (zip)
Download the Windows executable of
'CppQGraphicsProxyWidgetExample5' (zip)
Technical facts
Operating system(s) or programming environment(s)
Lubuntu 12.10 (quantal)
Qt Creator 2.5.2
- G++ 4.7.2
Libraries used:
Qt project file: CppQGraphicsProxyWidgetExample5.pro
QT += core QT += gui QMAKE_CXXFLAGS += -Wextra -Werror -std=c++11 TARGET = CppQGraphicsProxyWidgetExample5 CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp
main.cpp
#include <cassert> #include <cmath> #include <QApplication> #include <QDesktopWidget> #include <QGraphicsProxyWidget> #include <QGraphicsScene> #include <QGraphicsView> #include <QLineEdit> #include <QLabel> #include <QVBoxLayout> #include <QDialog> #include <QGraphicsSceneMouseEvent> #include <boost/signals2.hpp> struct MyItem : public QWidget { MyItem(QWidget *parent = 0, Qt::WindowFlags f = 0) : QWidget(parent,f), m_edit(new QLineEdit(this)), m_label(new QLabel(this)) { assert(!this->layout()); QVBoxLayout * const layout = new QVBoxLayout(this); this->setLayout(layout); layout->addWidget(m_label); layout->addWidget(m_edit); m_edit->setEnabled(false); } QLineEdit * const m_edit; QLabel * const m_label; boost::signals2::signal<void (MyItem*)> m_signal_mouse_press; protected: void mousePressEvent(QMouseEvent * event) { m_signal_mouse_press(this); QWidget::mousePressEvent(event); } }; struct MyView : public QGraphicsView { MyView(QWidget *parent = 0) : QGraphicsView(parent), m_scene(new QGraphicsScene(this)), m_drag_item(nullptr) { this->setScene(m_scene); //Create the QLineEdit instances const int sz = 10; std::vector<QGraphicsProxyWidget *> proxies; for (int i=0; i!=sz; ++i) { MyItem * const item = new MyItem; item->setGeometry(0,0,100,22); item->m_label->setText(QString("#") + QString::number(i)); item->m_edit->setText(QString("Text ") + QString::number(i)); item->m_signal_mouse_press.connect( boost::bind( &MyView::OnMousePress, this,_1)); //_1 because the signal contains an argument //Add the QWidget and obtain its proxy QGraphicsProxyWidget * const proxy = m_scene->addWidget(item); proxies.push_back(proxy); m_m[item] = proxy; } const double ray = 200.0; //pixels for (int i=0; i!=sz; ++i) { const double angle = 2.0 * M_PI * static_cast<double>(i) / static_cast<double>(sz); const int x = static_cast<int>(0.0 + (std::sin(angle) * ray)); const int y = static_cast<int>(0.0 - (std::cos(angle) * ray)); QGraphicsProxyWidget * const proxy = proxies[i]; proxy->setRotation(angle * 360.0 / (2.0 * M_PI)); proxy->setPos(x,y); proxy->setFlag(QGraphicsItem::ItemIsMovable,true); //No need to set this flag } } //My own added method void OnMousePress(MyItem * item) { assert(item); m_drag_item = item; item->m_edit->setText("Gotcha!"); } void mouseMoveEvent(QMouseEvent *event) { if (m_drag_item) { //Convert the position clicked to the QGraphicsView coordinat QPointF p = this->mapToScene(event->pos()); //Let the m_m[m_drag_item]->setPos(p); } } void mouseReleaseEvent(QMouseEvent *) { m_drag_item = nullptr; } QGraphicsScene * const m_scene; MyItem * m_drag_item; std::map<MyItem *,QGraphicsProxyWidget *> m_m; }; int main(int argc, char **argv) { //Create the application QApplication app(argc, argv); MyView view; view.setGeometry(0,0,800,600); { //Put the dialog in the screen center const QRect screen = QApplication::desktop()->screenGeometry(); view.move( screen.center() - view.rect().center() ); } view.show(); return app.exec(); }