Select text of QLineEdit on focus - qt

I have created a dialog using QtDesigner. There is a QLineEdit object in the dialog with some default content. When the dialog initializes and the focus goes to the QLineEdit, I want the default content to be auto selected, so once the user start writing, the previous content will be overwritten.
EDIT:
In constructor:
dialog->accept();
and
connect( dialog, SIGNAL(accepted()), QlineObj, SLOT( selectAll() ) );

This is an older question, but nevertheless, I ended up here searching for a solution this exact problem. It can be solved in the following way:
Create a class derived from QLineEdit and override the focusInEvent in the header:
void focusInEvent(QFocusEvent *event) override;
Then implement it like so:
void MyLineEdit::focusInEvent(QFocusEvent *event)
{
// First let the base class process the event
QLineEdit::focusInEvent(event);
// Then select the text by a single shot timer, so that everything will
// be processed before (calling selectAll() directly won't work)
QTimer::singleShot(0, this, &QLineEdit::selectAll);
}
Just in case anybody else wonders how this can be done ;-)

Call
lineEdit->selectAll();
after you set the default text. (In the dialog constructor, perhaps.)

There is a simpler method to get almost the same behaviour, which is to set the default content using setPlaceholderText() instead of setText(). This will show the default content grayed out and as soon as the QLineEdit gains focus, it will disappear.

You can use QApplication::focusChanged along with QTimer::singleShot to select all the text on a changed focus.
Normally your QApplication is declared in main, so use QObject::connect there, eg:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
My_Main_Window w();
QObject::connect(&a, SIGNAL(focusChanged(QWidget*, QWidget*)),
&w, SLOT(my_focus_changed_slot(QWidget*, QWidget*)));
w.show();
return a.exec();
}
Remember to make the public slot in the My_Main_Window class:
public slots:
void my_focus_changed_slot(QWidget*, QWidget*);
Then in your definition of my_focus_changed_slot, check if the second QWidget* (which points to the newly focused widget) is the same as the QLineEdit you wish to select all of, and do so using QTimer::singleShot so that the event loop gets called, then the QLineEdit has the selectAll slot called immediately after, eg
void My_Main_Window::focus_changed(QWidget*, QWidget* new_widget) {
if (new_widget == my_lineedit) {
QTimer::singleShot(0, my_lineedit, &QLineEdit::selectAll);
}
}
where my_lineedit is a pointer to a QLineEdit and is part of the My_Main_Window class.

Related

How to close the qt application when setQuitOnLastWindowClosed(false)

I wish to create a project including 3 windows: mainWindow, childWindow1, childWindow2, and only one window should show at a time. And I can switch between these windows.
So I have three tasks:
I place two buttons in the mainWindow and want to use them to make one of the child windows showing and the main window hiding.
And when I close the child window, I wish to show the main window.
When I close the main window, terminate the whole application.
I first had a problem:
If I close the child window, the application exit.
So I use the qApp.setQuitOnLastWindowClosed(false), and I got task 2 done.
But another problem occured:
If I close the main window, the program is still running.
Last problem:
How to show the child window in the task bar? It looks wired to run a program which can't be found in the taskbar.
I search everywhere I could, any help would be really appreciated!
main.cpp:
int main()
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
MainWindow mainWindow;
mainWindow.show();
return a.exec();
}
mainWindow.cpp:
void mainWindow::button1Clicked()
{
this->hide();
childWindow1 = new ChildWindow1(this);
connect(childWindow1, &QMainWindow::destroyed, this, &QMainWindow::show);
childWindow1->setWindowModality(Qt::WindowModal);
childWindow1->show();
}
childWindow1.cpp
ChildWindow1::ChildWindow1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
}
To achieve this you need to do the following:
In your main.cpp:
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
MainWindow w;
QObject::connect(&w, &MainWindow::exited, &a, &QApplication::quit);
w.show();
return a.exec();
exited signal would be used to exit the application after closing the main window.
In your MainWindow you should reimplement closeEvent like this:
void MainWindow::closeEvent(QCloseEvent *event)
{
QMainWindow::closeEvent(event);
emit exited();
}
Don't forget to add exited() to MainWindow signals section;
Finally, code for creating new windows should be the following:
child1 = new ChildWindow;
child1->setAttribute(Qt::WA_DeleteOnClose);
connect(child1, &QObject::destroyed, this, &QWidget::show);
child1->show();
hide();
Note that I don't pass this as a parent for a ChildWindow, this allows it to appear in the task bar.
So, creating a new ChildWindow will hide the main window, closing the ChildWindow will delete it automatically (that's another reason why you don't need to pass parent to ChildWindow constructor) and closing MainWindow will close the whole application thanks to our exited signal.

Qt How to update GUI in the loop

I need to update screen to show how button is moving.
Here is my code:
void mouseReleaseEvent(QMouseEvent *event){
double b=(button->x()*event->y())/(button->x()-1);
double k=(button->y()-b)/button->x();
int time=0;
fnl=false;
if(event->button()==Qt::LeftButton)
{
while(!fnl)
{
int mX=button->x()-1;
int mY=k*(button->x()-1)+b;
button->setText(QString::number(b));
button->move(mX,mY);
QThread::sleep(1);
//here I need to update screen and show button
}
}
}
But it does not update GUI. It simply plays inside the loop.
Never use QThread::sleep() in the GUI thread, It will block the GUI thread from doing anything. Instead, You can use QTimer to schedule something to run at a later point in time. Also, Your slots/functions should be as short and optimized as possible in order to return control to the event loop and be able to handle other events that may happen.
You may want to have a look at this question for a similar problem.
The same technique can be applied here to solve the problem by replacing your while loop with a slot and a QTimer whose interval is set to 0. But Qt can do all that job using the animation framework, Here is an example of a button that gets moved when clicked:
#include <QtWidgets>
int main(int argc, char* argv[]){
QApplication a(argc, argv);
//create and show button
QPushButton button("Animated Button");
button.move(QPoint(100, 100));
button.show();
//create property animator object that works on the position of the button
QPropertyAnimation animation(&button, "pos");
//set duration for the animation process to 500ms
animation.setDuration(500);
//when the button is clicked. . .
QObject::connect(&button, &QPushButton::clicked, [&]{
//set the starting point of the animation to the current position
animation.setStartValue(button.pos());
//set the ending point to (250, 250)
animation.setEndValue(QPoint(250, 250));
//start animation
animation.start();
});
return a.exec();
}
Qt also provides many examples for using the animation framework. . .
A timer is the best option. If you want to use brute force you can call
qApp->processEvents();
inside your loop. Ugly but gets the job done.

QT 5.6 QVBoxLayout removeWidget then addWidget not working as expected

I searched everywhere and found nothing that solved this. I make a QVBoxLayout and then make a web call for data. When the data comes back I add 4 custom widgets to this QVBoxLayout
verticalLayout->addWidget(nsd);
For the first four this works great. Everything appears as needed. However, I want to delete any one of the four widgets then add a widget at the bottom. Deleting works fine
verticalLayout->removeWidget(nsd);
delete nsd;
I know it works fine because then that widget not longer draws to my screen. The problem is that adding the widget is not working entirely. I call the same code
verticalLayout->addWidget(nsd);
and checking verticalLayout->count() tells me there are 4 items. The widget is created with the same parent widget as the ones added before. The paint event of the new widget never gets called. Furthermore the 3 that show on the screen show spaced for 3 items. It's not like there's a hole anywhere. I also tried adding then deleting but it's the same problem. The new item never gets drawn and its size never factored in.
If you want to get rid of a widget completely, you only need to destruct it. You don't have to worry if it was in a layout. If the widget is dynamically allocated, then delete nsd is all you need, the layout->removeWidget call is not needed. You also don't have to give widgets any explicit parents - insertion into the layout will set proper parent.
The following works and is safe no matter what is the type of the widget being added/removed. If the deletion had target widget on the call stack, you should use deleteLater instead of plain delete. But this can never be the case when you delete it in response to a signal from an unrelated widget, unless the target widget re-enters the event loop (aargh! it shouldn't).
// https://github.com/KubaO/stackoverflown/tree/master/questions/layout-addremove-37814292
#include <QtWidgets>
int main(int argc, char ** argv) {
QApplication app(argc, argv);
QWidget widget;
QVBoxLayout layout(&widget);
QPushButton button;
QLabel label("Hello");
layout.addWidget(&button);
layout.addWidget(&label);
auto onClick = [&]{
if (layout.count() == 3) {
delete layout.itemAt(2)->widget();
button.setText("Add");
} else {
layout.addWidget(new QLabel("Hello too!"));
button.setText("Remove");
}
};
QObject::connect(&button, &QPushButton::clicked, onClick);
onClick();
widget.show();
return app.exec();
}

Please let me know its an functionality behaviour or not

I have a listview filled with items. By default, the 0th item will be selected.
If I try to navigate the list using the mobile keypad, it's not gaining focus - instead I need to use my mobile select key for focus. In this process my mobile left soft key gets changed to “Done”. Why is the "Done" menu appearing?
How do I provide default focus to the listview? And how do I avoid the display of “Done” at left soft key?
Here is my code:
#include "Test_Doco.h"
#include <QtGui>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QListView *listui = new QListView();
listui->setSelectionMode(QAbstractItemView::SingleSelection);
listui->viewport()->setFocusPolicy(Qt::WheelFocus);
listui->viewport()->setFocus();
QStandardItemModel* listModel = new QStandardItemModel();
for(int i =0; i<10;i++)
{
QStandardItem *item1 = new QStandardItem("AOL");
listModel->appendRow(item1);
}
QModelIndex index = listModel->index(0,0);
listui->setCurrentIndex(index);
listui->setModel(listModel);
listui->showMaximized();
return a.exec();
}
Edit: I have updated the code. Please check it.
For the default focus, stop calling listui->viewport()->setFocus(); and call listui->setFocus() to give it focus when it is created.
As for the display of "Done", I'm not too sure, but you might need to post more code to show the dialog you are creating. Most have a set of default buttons or a button set to default. The "Done" key might be related to that. As seen here "Exit" is the softkey shown.
The issue is w.r.t Qt 4.6.2 and the issue is fixed in Qt 4.6.3

QT NOOB: Add action handler for multiple objects of same type

I have a simple QT application with 10 radio buttons with names radio_1 through radio_10. It is a ui called Selector, and is part of a class called TimeSelector
In my header file for this design, i have this:
//! [1]
class TimeSelector : public QWidget
{
Q_OBJECT
public:
TimeSelector(QWidget *parent = 0);
private slots:
//void on_inputSpinBox1_valueChanged(int value);
//void on_inputSpinBox2_valueChanged(int value);
private:
Ui::Selector ui;
};
//! [1]
the commented out void_on_inputSpinBox1_valueChanged(int value) is from the tutorial for the simple calculator. I know i can do:
void on_radio_1_valueChanged(int value);
but I would need 10 functions. I want to be able to make one function that works for everything, and lets me pass in maybe a name of the radio button that called it, or a reference to the radio button so i can work with it and determine who it was.
I am very new to QT but this seems like it should be very basic and doable, thanks.
You can create a unique slot and obtain the object that emitted the signal with the QObject::sender() method. The following code presents an example of such slot:
public slots:
void onRadioToggled(bool checked)
{
QRadioButton *radio = qobject_cast< QRadioButton* >(QObject::sender());
// radio is the object that emitted the triggered signal
// if the slot hasn't been triggered by a QRadioButton, radio would be NULL
if (radio) {
qDebug() << radio->objectName() << " is set to " << checked << ".";
}
}
Note that radio->objectName() will not give you a good result unless you define it explicitly somewhere.
Now, you can connect the toggled(bool checked) signal of every QRadioButton to the onRadioToggled slot. Note that QRadioButton does not have any valueChanged signal so your code cannot actually work.
connect(radio_1, SIGNAL(toggled(bool)), SLOT(onRadioToggled(bool)));
connect(radio_2, SIGNAL(toggled(bool)), SLOT(onRadioToggled(bool)));
...
connect(radio_10, SIGNAL(toggled(bool)), SLOT(onRadioToggled(bool)));
In the radiobutton case, add the buttons to a QButtonGroup.
Similar functionality offers QSignalMapper.
What you can do is to create your own radio button class that inherits from QRadioButton and create a signal. This signal can have all the parameters you want.
void CheckWithReference(YourRadioButtonClass* rb);
or
void CheckWithReference(QString RadioButtonName);
or anything you would like to have.
Then create a slot in your TimeSelector class with the same set of parameters you will connect to all signals.

Resources