Putting QWidgets inside a text field - qt

I'd like to implement a text field in Qt that replicates the "Tags" field on stackoverflow (when submitting a question). Certain keywords would be replaced by widgets and if I backspace a widget it should be replaced with the text that was typed to create that widget. How could I accomplish something like this? Thanks.

You can start by inheriting a QWidget and implementing the KeyPress and KeyRelease events. Basically mimicking a QLineEdit widget. So you might need to look for re-usable code to avoid a lot of work, like inheriting QLineEdit and overwriting paintEvent().
Then, in your paintEvent, you use the painter to render the non-widget text and your widgets.
pseudocode:
SomeWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
foreach (object ; objectsToDraw) {
if (isText) {
painter.drawText();
} else if (isWidget) {
widget.render(&painter);
}
}
}

Related

How to delete objects inside Widget in Qt

I have MainWindow form which has Widget inside. And I have another Widget class (promoted to MainWindow) which has only DockWidget inside. In MainWindow I am opening new one and placing into Widget. However when I close DockWidget from close(cross"X") button. Inside my MainWindow it is not cleaning..
Sorry for my bad english better to paste my code here:
qDebug() << ui->widget->layout()->count();
QueryWidget *lQueryWidget = new QueryWidget(this);
ui->widget->layout()->addWidget(lQueryWidget);
So in everytime although I close DockWindow(lQueryWidget), layout()->count() never decrease. I tried to delete everything inside layout like ;
QList<QObject*> child = ui->widget->layout()->children();
foreach (QObject *var, child)
{
delete var;
}
But it never enters foreach loop.. If you check image below you will see that there is something above DockWidget, but it is not visible.. Could you please help me how can I solve this issue ?
To make dockable widget you should use
QDockWidget::setWidget(QWidget * widget)
The widget will be deleted when the dock widget is deleted.
You should not manipulate the dock widget layout.

How to get selected QTextEdit using on-screen keyboard?

I have to make a GUI for a touch screen software. It's on the same window as the QTextEdit. I was thinking of something simple with a limited set of characters (I also have to make PIN Pads for other windows later).
The approach I'm thinking of is hard-coding the text modifications done by each button. The problem I'm facing getting the QTextEdit that actually has the focus (is selected by the user's cursor).
So I would like to know how I could find out if a certain QTextEdit currently has focus or not ?
Also if there are better ways to do this whole thing ?
Here is my new code, what's wrong with it ?
#include "settings2.h"
#include "ui_settings2.h"
Settings2::Settings2(QWidget *parent) :
QWidget(parent),
ui(new Ui::Settings2)
{
ui->setupUi(this);
}
Settings2::~Settings2()
{
delete ui;
}
void Settings2::on_q_btn_clicked()
{
QTextEdit *textedit = qobject_cast<QTextEdit*>(QApplication::focusWidget());
if(textedit){
textedit->setText("aze");}
}
The way you are trying to get the QTextEdit in focus is wrong. Moreover as soon as you click on a button on your on-screen keyboard, the focus will move to the key and will not stay on the QTextEdit.
I would suggest using a pointer to hold address of modified QTextEdit as soon as one comes to focus. Thus you will always know which was the last text edit in focus and keep appending the new text to that.
You will have to write your own class inheriting QTextEdit and implement the QTextEdit::focusInEvent where you will be pointing the above mentioned pointer to the this pointer.
Per #thuga's comment QApplication::focusWidget.
If you want to be sure the focused widget is a certain category of widget you can use qobject_cast, which will only return a non-null pointer if that cast is valid:
QLineEdit *lineedit = qobject_cast<QLineEdit*>(widget);
QTextEdit *textedit = qobject_cast<QTextEdit*>(widget);
...
if (lineedit) {
// do QLineEdit stuff with lineedit
...
}
if (textedit) {
// do QTextEdit stuff with textedit
...
}
...

Expandable list of inputs for QT

I am trying to make a GUI so when you increase the "Article" count, then more of the article inputs show up. For example, if I change the Articles count to 2, I would want another group of inputs to show up for Article 2, and if the Articles count changes to three, there would be three groups of inputs, but since that would use up more space than the window has, it would begin to scroll.
I was thinking of using one of the tree, list, or table widgets, but I am not sure if that is even the right direction I am supposed to be going to. Can anyone push me in the right direction?
Here is a picture, since my description is not good.
You should put all the widgets needed for one article into one single custom widget. Whenever the spin box is changed (code in slot) you can add / remove one instance of such a custom widget to a scroll area.
Within the constructor of this custom widget class (let's call it ArticleWidget), you should define signals in your custom widget which notify about changes made in its child widgets. Connect these within your custom widget:
ArticleWidget::ArticleWidget(QWidget *parent) :
QWidget(parent)
{
ui->setupUi(this); // when you use QtDesigner to design the widget
// propagate signals from my inner widgets to myself:
connect(ui->title, SIGNAL(textChanged(QString)),
SIGNAL(titleChanged(QString)));
}
In the outer widget, whenever creating such a custom widget, connect its signals to your processing slots:
void OuterWidget::articleCountChanged(int)
{
...
if(/*increased*/)
{
ArticleWidget *article = new ArticleWidget(this);
connect(article, SIGNAL(titleChanged(QString)),
SLOT(art_titleChanged(QString)));
ui->scrollAreaViewport->layout()->addWidget(article);
}
...
}
You can access the article widget using sender():
void OuterWidget::art_titleChanged(QString)
{
ArticleWidget *articleWidget = qobject_cast<ArticleWidget*>(sender());
Q_ASSERT(articleWidget); // make sure the signal comes from an ArticleWidget
// if you want to store articles in a vector of custom types,
// you could give this type a pointer to the widget, so you can
// find the index if you have the widget pointer:
foreach(Article *article, articles)
if(article->widget == articleWidget)
article->title = title; // make some changes
}
This code assumes that you hold all your articles in a struct similar to this:
struct ArticleData
{
ArticleWidget *widget;
QString title;
...
};
and have a vector of them in your outer widget class:
QVector<ArticleData*> articles;

Qt: how to clear the fields of form?

I have some form with fiels, combos etc. I would like to go over through all the widgets on the form and if for example it's textfield, clear it, something like that:
foreach(QObject *child, this->ui->children())
{
QLineEdit *txtField = qobject_cast<QLineEdit *>(child);
if (txtField)
{
txtField->clear();
}
}
The problem is the ui object doesn't have such property like children and I don't know how to get the whole collection of children widgets.
Maybe the form object has something like Clear method. It would be the best.
Thanks
Try it.
foreach(QLineEdit *widget, this->findChildren<QLineEdit*>()) {
widget->clear();
}
How many QLineEdits are we talking about? Unless there's a good reason I would just add a method to the class that has ui as a member and do it by hand, like this:
void clearform()
{
this->ui->firstlineedit->clear();
this->ui->secondlineedit->clear();
...
this->ui->nthlineedit->clear();
}
A good reason why you can't do it this way is that the QLineEdits are dynamically added and you don't have them as members. In that case you can call QObject::children on the widget that is the parent of all your QLineEdits, if they share some common name, QObject::findChildren will also work.

How to insert QPushButton into TableView?

I am implementing QAbstractTableModel and I would like to insert a QPushButton in the last column of each row. When users click on this button, a new window is shown with more information about this row.
Do you have any idea how to insert the button? I know about delegating system but all examples are only about "how to edit color with the combo box"...
You can use
QPushButton* viewButton = new QPushButton("View");
tableView->setIndexWidget(model->index(counter,2), viewButton);
The model-view architecture isn't made to insert widgets into different cells, but you can draw the push button within the cell.
The differences are:
It will only be a drawing of a pushbutton
Without extra work (perhaps quite a bit of extra work) the button won't be highlighted on mouseover
In consequence of #1 above, you can't use signals and slots
That said, here's how to do it:
Subclass QAbstractItemDelegate (or QStyledItemDelegate) and implement the paint() method. To draw the pushbutton control (or any other control for that matter) you'll need to use a style or the QStylePainter::drawControl() method:
class PushButtonDelegate : public QAbstractItemDelegate
{
// TODO: handle public, private, etc.
QAbstractItemView *view;
public PushButtonDelegate(QAbstractItemView* view)
{
this->view = view;
}
void PushButtonDelegate::paint(
QPainter* painter,
const QStyleOptionViewItem & option,
const QModelIndex & index
) const
{
// assuming this delegate is only registered for the correct column/row
QStylePainter stylePainter(view);
// OR: stylePainter(painter->device)
stylePainter->drawControl(QStyle::CE_PushButton, option);
// OR: view->style()->drawControl(QStyle::CE_PushButton, option, painter, view);
// OR: QApplication::style()->drawControl(/* params as above */);
}
}
Since the delegate keeps you within the model-view realm, use the views signals about selection and edits to popup your information window.
You can use setCellWidget(row,column,QWidget*) to set a widget in a specific cell.

Resources