Please let me know its an functionality behaviour or not - qt

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

Related

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();
}

Get event or notification when user click in taskbar/dock icon in Qt application

I'm developing an application in osx, windows, linux
I want to make feature like skype. when user click close windows, application not exit but hidden. When user click appicon on dock or taskbar, my mainwindow will re-open again.
How do I get a notification or filter events to known when user click on app icon?
First, you need to prevent your application window from closing when you hit the "close window" button. Assuming, that you use QMainWindow:
class MainWindow : public QMainWindow
{
// .. constructors, etc.
// ..
protected:
void closeEvent(QCloseEvent *)
{
// Do not close, but hide the window.
hide();
}
};
Qt has the dedicated class to handle the task bar icons - QSystemTrayIcon. So, the simple application would look like:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mw;
QSystemTrayIcon tray; // needs an icon.
// Show the main window when user activates the tray icon.
QObject::connect(&tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
&mw, SLOT(show()));
tray.show();
return app.exec();
}
This should be helpful:
void setQuitOnLastWindowClosed(bool quit)

Update QMainWindow Parent elements from child

I have two QMainWindows (A and B) defined, and B is initialized from A. In other words, B is the child of A.
I need to update the elements of A based on the user input in B, so what is the way to update elements in the parent window from child window because apparently we can't update elements across windows.
A simple example such as setting a label in A based on input in B would be great.
Thanks in advance.
Use signals and slots to do this, connect them before you instantiate either of the QMainWindows.
Usually I initialize all my windows from within my main class, so that I can set up the signals and slots.
//----- MORE INFO HERE ----//
When you create a new QWindow project, you get a mainwindow.cpp class, what you need to do is create a childWindow.cpp class which looks the same, then your main function looks like this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
ChildWindow child;
connect(&w, SIGNAL(labelChanged),
&child, SLOT(updateLabelChange));
w.show();
return a.exec();
}
Then, you can use signals and slots to control them. The important thing to remember is that you should write a new class for each window, so your child window should have its own class. Hope that helps.

Select text of QLineEdit on focus

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.

Resources