Creating custom buttons in QT - c++

I have my class, which should represent buttons (pads, if I need to be specific). Right now I am wondering if it's possible to draw them in my QMainWindow class.
In first version of app I created buttons in QtCreators designer. But right now I Would like to create them by code. As said before, already got class Pad, where I want to have position, text and other behaviors. Right now my class is pretty poor:
#include <QObject>
class Pad
{
public:
Pad(int x, int y);
private:
int m_xPosition;
int m_yPosition;
};
And here is how I create them (where m_pads is std::vector )
void PadsWindow::createPads(const int &numberOfPads)
{
enablePadsWindow();
for (int index = 0; index < numberOfPads; ++index)
{
m_Pads.push_back(new Pad(10, 100));
}
}
Exactly here I would like to draw buttons in my QMainWindow and have it like normal QPushButton.
Could you help guys ?

To use a custom class as UI widget it must inherit from QWidget, which provides the necessary interface and already a lot of implementations (which you can override to customize the behaviour).
To make a widget behave like a button it is recommandable to use QAbstractButton or one of its derivations as base class, because these already provide much of the behaviour, and customizing is easier than adding all functionality to a plain QWidget.
This class can be added as custom widget to Qt Designer, so you can use it like any original Qt widget in dialogs and layouts.
You can find a lot of tutorials and FAQs regarding custom widgets on the net and here, so getting started should be easy enough for anyone who's got a grasp of the basics of Qt and C++.

Related

Using a factory to create QT promoted widgets

Promoting widgets is one of the best features in the QT Designer. But when using the designer, it 'new's the object there it self ( inside setupUi ). This limits the ability to extend the interface file.
Is it possible to use a factory of some sort to get the promoted widgets, so that when a sub class of a promoted widget is required, this could be achieved via changing the factory and returning the sub class of the widget.
requirement:
NamePanel* myPanel;
void setupUi(QWidget* pWidget)
{
myPanel = Factory::CreateNamePanel();
}
Is there a work around to achieve this?
Unfortunately it seems not to be possible to add a factory into the Ui files. A workaround would be to have a QWidget with an attached layout in the ui and add the factory generated widget to this layout.
The code would look like this:
ui->setupUi(this);
QWidget *panel = Factory::CreateNamePanel();
ui->namePanelContainer->layout()->addWidget(panel);

How to extend QDockWidget functions in Qt?

I'm new to Qt, tried several widgets and found that QDockWidget is the most modern/interactive one to work with
But I've found a little limitation "about where to dock the widget only in the 4 sides, left/right/top/bottom"
I want to do one of the two following things and any one should work.
Add more areas to dock widget "for example it can recognize separators between widgets and get its data from there , then resize itself depending on that"
Reimplement the whole functions of QDockWidget into QWidget and do
it like option 1
Thanks in advance
In Qt you can pretty much inherit any class into a new class of your own and extend it yourself. for example:
// New class that inherits QDockWidget and extends its functionality
ExtendedQDockWidget : public QDockWidget
{
public:
ExtendedQDockWidget(QWidget * parent = 0) :
QDockWidget(parent)
{
// ... do any extra initialisations here
}
ExtendedFunc(/* some params */)
{
// code here
}
}
You can also re-implement or overload existing functions to do exactly what you want.

Promoting code reuse for this situation

This is a bit tricky to explain but I will try my best to explain it.
I'm making a Gui API for games and it has Themes.
First I'll explain how Widgets work.
A Button for example, inherits from Widget.
Themes work similarly.
ButtonTheme inherits from WidgetTheme.
Inside each widget class, there is an instance of its corrosponding Theme.
Widget class has:
private:
static WidgetTheme widgetTheme;
public:
static WidgetTheme& getWidgetTheme();
button class has:
private:
static ButtonTheme buttonTheme;
public:
static ButtonTheme& getButtonTheme();
the Widget constructor, builds itself from its theme ex:
Widget()
{
setFont(getWidgetTheme().getFont());
}
the Button, inheriting from WidgetTheme, has to do the same ones because the internal widget will not know to construct from ButtonTheme, so my button ends up having to do:
Button()
{
setFont(getButtonTheme().getFont());
setButtonPadding(getButtonTheme().getButtonPadding());
}
This is where my problem is. It really feels wrong that I have to reprovide all the WidgetTheme ones and redirect them to ButtonTheme's parameters for Widget. If I do not do this, a SuperButton would inherit the styles of Button which would also inherit the styles of Widget, but what I want is for SuperButton to use its version of ButtonTheme and WidgetTheme because SuperButtonTheme would inherit from ButtonTheme and WidgetTheme.
Is there a way I could redesign this so that the constructor only has to set parts of the theme that it brings, and not have to set those of its parents?
Thanks
A virtual getTheme() (as drewish suggests) but using covariant return types ought to solve your problem without requiring casts.
The Widget constructor can accept a WidgetTheme and use that.
Widget(const WidgetTheme& theme)
{
setFont(theme.getFont());
}
Button() : Widget(getButtonTheme())
{
setButtonPadding(getButtonTheme().getButtonPadding());
}
I'm not quite clear on where getButtonTheme() and getWidgetTheme() live in your object hierarchy but it seems like it should be up to the class to know what its theme is so why not have a getTheme() method on your class? Maybe I'm too used to scripting languages and not appreciating some issues with strict typing.

How to specialize a widget according to a file type?

I'm looking for a way to specialize a widget at runtime. I have a form created with Qt Designer. In this form there is a widget that displays user data, like name, age and so on. Then the user chooses a file and according to the type the widget shall display additional information (like to OO example person -> student, teacher).
I tried to put an empty QWidget on my form, assigned a person widget to it and if the user clicks a button I call deleteLater() on person and assign a new Student(). This works but the new widget then doesn't follow the layout.
I also found QStackedWidget. This seems to work but because all possible widgets are created when the form is shown, even if they are never used, this way doesn't feel right.
What would be the way to accomplish this?
Edit: I feel that my question is a bit unclear. What Qt mechanism should be utilized if one wants to replace a QWidget with a specialized (inherited) version of the original widget? I'm looking for the Qt way to do this.
You need to add a widget dynamically to the widget you have drawn in the designer.
// in UI file
QWidget *wdgFromForm;
// in cpp file
QHBoxLayout *const layout(new QHBoxLayout(wdgFromForm));
SpecializedWidget * specializedWidget( new SpecializedWidget(wdgFromForm));
layout->addWidget(specializedWidget);
Maybe the problem is not that the widget is not suitable, but simply that you're not giving time for the widget to update.
You could take a look at processEvents:
http://web.mit.edu/qt-dynamic/www/qapplication.html#details
This looks like a use case for the factory pattern.
#include <map>
#include <string>
struct Whatever;
struct QWidget;
typedef QWidget*(*WidgetCtor)(Whatever*);
typedef std::map<std::string, WidgetCtor> FileFactory;
QWidget* createFoo(Whatever*);
QWidget* createBar(Whatever*);
QWidget* createDefault(Whatever*);
void factory_init(FileFactory& ff)
{
ff["foo"] = createFoo;
ff["bar"] = createBar;
}
QWidget* create_by_factory(const FileFactory& ff, const std::string t, Whatever* w)
{
FileFactory::const_iterator it(ff.find(t));
if(it != ff.end())
{
return it->second(w);
}
else
{
return createDefault(w);
}
}
Adding widgets dynamically to a layout is not a problem.
You might need to call updateGeometry on the containing widget though.

qt GUI connecting

I am just starting out with QT. I have read through some tutorials, and I think I have an understanding of signals and slots. I am writing a GUI that has various buttons that change the state of my main program. So for example in a drawing app, you would pick different drawing tools (using various buttons).
What is the best way to go about this? My first thought was to try to connect the clicked signal of the PushButton to some function that sets a current_tool variable. I did some searching and couldn't find a way to connect a QObject signal to a regular function.
This leads me to believe that there is probably a different approach. One where I create a new QObject (my own extension that is) that has various GUI properties. I would then define my slots here for the various buttons.
What is the best way to do this in QT. I am new and do not know of the preferred practice.
Any info would be useful,
thanks
You can define these "normal functions" as slots. Slots are just normal functions that can also be called by signals:
class ToolSelector : public QObject {
Q_OBJECT
public:
Tool *selected;
public slots:
void selectBrush();
void selectPen();
void selectFill();
};
ToolSelector::selectBrush() {
delete selected;
selected = new Brush();
}
ToolSelector::selectPen() {
// ...
}
// ...
toolsel = new ToolSelector();
brushButton = new QPushButton();
connect(brushButton, SIGNAL(clicked()), toolsel, SLOT(selectBrush()));
Inherit from the class that uic generates, creating, say, a MyAppWindow class. Provide extra METHODs in that class, as well as a Document or Drawing object. Connect these methods to the signals you're interested in, and them alter a member variable that contains the drawing state.