Factory má za úkol vytvářet instance objektů.
Ukazatel na třídu Factory slouží jako “proměnná uchovávající konstruktor třídy”
Třída Factory bude obsahovat jen metodu createInstance
Výsledný typy metody createInstance bude třída společná pro vytvářené objekty, v našem případě QWidget.
Metoda bude abstraktní
class Factory { public: virtual QWidget * createInstance () = 0; };
Vytvoříme třídu ButtonFactory odvozenou z třídy Factory. \ Implemetujeme metodu createInstance.
class ButtonFactory : public Factory { public: QWidget * createInstance () { return new QPushButton ("Button"); } };
Odvozená třída může skladovat další data.
Např. EditorFactory skladuje text, který byl parametrem konstruktoru.
A createInstance použije text při vytváření instance.
class EditorFactory : public Factory { private: QString text; public: QWidget * createInstance () { QTextEdit * e = new QTextEdit; e->setText (text); return e; } EditorFactory (QString p_text) : text (p_text) { } };
class TreeFactory : public Factory { public: QWidget * createInstance () { return new QTreeWidget; } };
Jednotivé Factory budeme skladovat v asociativním poli factories.
Indexem bude jméno předávané pomocí drag and drop, jméno bude typu QString.
Hodnoty v poli budou ukazatele na jednotlivé Factory.
Samotné pole bude typu QHash, což je obdoba std::map.
extern QHash <QString, Factory *> factories;
Během drag and drop budeme data typu Factory přenášet jako data našeho následujícího formátu:
const QString tool_format = "application/x-shape";
Třídu ToolButton odvodíme ze třídy QToolButton, bude obsahovat:
class ToolButton : public QToolButton { private: QString name; protected : void mousePressEvent (QMouseEvent *event); public: ToolButton (QWidget * p_parent, QString p_name) : QToolButton (p_parent), name (p_name) { setText (p_name); } };
Metoda mousePressEvent zahájí “tažení dat pomocí myši”.
void ToolButton::mousePressEvent (QMouseEvent *event) { QDrag * drag = new QDrag (this); QMimeData * data = new QMimeData (); data->setData (tool_format, name.toLatin1()); drag->setMimeData (data); drag->start (); }
Plochu hlavního okna naší aplikace bude pokrývat třída Panel odvozená od QWidget.
class Panel : public QWidget { Q_OBJECT public: explicit Panel (QWidget *parent = nullptr); protected: void dragEnterEvent (QDragEnterEvent *event); void dropEvent (QDropEvent *event); };
Konstruktor bude mít za parametr odkaz na nadřazené okno,
tento odkaz předáme konstruktoru na nadřazenou třídu QWidget
a povolíme vhazování dat pomocí myši setAcceptDrops (true)
Panel::Panel(QWidget *parent) : QWidget (parent) { setAcceptDrops (true); }
Virtuální funkce dragEnterEvent pocházející z nadřazené třídy QWidget
vyzvedne odkaz na přenášená data do proměnné typu const QMimeData *
a pokud data obsahují náš formát, tak drop odsouhlasí.
Výsledek se projeví na vzhledu kurzoru myši během taření dat.
void Panel::dragEnterEvent (QDragEnterEvent *event) { const QMimeData * data = event->mimeData (); if (data->hasFormat (tool_format)) { event->accept(); } }
Implementujeme virtální metodu dropEvent
factory->createInstance () void Panel::dropEvent (QDropEvent *event) { const QMimeData * data = event->mimeData (); if (data->hasFormat (tool_format)) { QString name = data->data(tool_format); Factory * factory = factories [name]; QWidget * widget = factory->createInstance (); QPoint pos = event->pos(); widget->setParent (this); widget->move (pos); widget->setVisible(true); } }
class MainWindow : public QMainWindow { public: MainWindow(QWidget *parent = nullptr); void addTool (QString text, Factory * factory); /* ... */ };
Funkce addTool
void MainWindow::addTool (QString name, Factory * factory) { factories [name] = factory; ToolButton * b = new ToolButton (this, name); ui->toolBar->addWidget (b); }
V konstruktoru vytvoříme jednotlivé nástroje umístěné do palety, funkci addTool předáme jako parametry
MainWindow::MainWindow(QWidget *parent) { /* ... */ addTool ("Button", new ButtonFactory); addTool ("Edit", new EditorFactory ("some text")); addTool ("Tree View", new TreeFactory); }
Vzhled okna po vhození jednoho exempláře od každé “factory”