implementing custom completer, popup window steal the focus - c++

I need to implement custom completer, similar to QCompleter but containing customized widgets. I got stuck at the very beginning, I can't make the popup work as it should work. In the following example I attach a completer (well, just a plain widget) to the first line edit. The second line edit is there just to test the focus in/out behavior. The problem is that when the popup displays, it steals the focus from the line edit. But this is not what I want, I want to be able to keep typing in the line edit. I tried several other options as commented out in the code below, but non of them worked.
#include <QApplication>
#include <QLineEdit>
#include <QHBoxLayout>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget container;
QLineEdit editor;
QLineEdit editor2;
QHBoxLayout layout(&container);
layout.addWidget(&editor);
layout.addWidget(&editor2);
QWidget completer; // or QWidget completer(&editor);?
//completer.setFocusProxy(&editor); // tried this, but it does not help
completer.setWindowFlags(Qt::Popup);
// the following lines are an alternative to Qt::Popup but the window
// does not close automatically, which is a problem
// e.g. when moving or resizing the parent window
//completer.setAttribute(Qt::WA_ShowWithoutActivating);
//completer.setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
QObject::connect(&editor, &QLineEdit::textEdited,
[&] {
completer.resize(editor.width(), 100);
completer.move(editor.mapToGlobal(QPoint(0, editor.height())));
completer.show();
// editor.setFocus(); // does not help either
});
container.show();
return a.exec();
}
How to implement custom completer?
UPDATE: From the docs, I read that "A popup widget is a special top-level widget that sets the Qt::WType_Popup widget flag, e.g. the QMenu widget. When the application opens a popup widget, all events are sent to the popup. Normal widgets and modal widgets cannot be accessed before the popup widget is closed."
So it seems that when I open a popup it automatically receives the events and therefore I have to forward the events to the line edit using QCoreApplication::sendEvent(editor, event); inside my Completer::keyPressEvent. This seems to work fine except the fact that the cursor in the line edit is not visible or not blinking.

Just apply this method to your completer widget:
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
It works for me.

Related

How to add "status bar" to QT widget - without using QTDesigner

I am creating QT QEditText widget (C++) dynamically at run time.
I cannot use "static ways" AKA QTDesigner to add / design the widget - it is NOT a form.
I know "status bar" is used as default in "MainWindow".
I want to add same functions in QTextEdit.
The QT doc has an example of C++ code on how to use "status bar" in MainWindow - that is of little help.
I have added this code to the QTextEdit constructor
childStatusBar = new QStatusBar();
childStatusBar->setStatusTip(" Show current copy drag and drop text");
childStatusBar->showNormal();
childStatusBar->showMessage("Status test message");
It compiles and runs, but there is no "status bar".
I do not know what is missing in my code and would
appreciate an assistance in solving this issue.
(Links , references to code examples would be helpful)
Please make sure to
read the post
and replay with facts, not opinions.
Suggestion for alternates are NOT solutions.
Please avoid any format of "ask your friend", RTFM.
Been there, done that.
As far as Mt Higgins is concerned, I am not asking for editing my post - I am not
posting to get a lecture in English grammar or composition.
Cheers and
"... thanks for watching..."
Just create a Qt MainWindow or Widget example and create a statusbar on it. Build the project and you can find your ui_...h in your build directory. Open it and find the QStatusBar widget. You can copy from there.
Note: Layouts are very important in Qt. So don't forget main-widget / main-window main layout and it's relation with statusbar. And also statusbar's layout.
As we can see in QStatusBar document :
Typically, a request for the status bar functionality occurs in
relation to a QMainWindow object. QMainWindow provides a main
application window, with a menu bar, toolbars, dock widgets and a
status bar around a large central widget
So you need something like this code:
#include <QApplication>
#include <QMainWindow>
#include <QStatusBar>
#include <QTextEdit>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow *w = new QMainWindow();
w->resize(600, 400);
QTextEdit *textEdit = new QTextEdit(w);
textEdit->setStatusTip("Show current copy drag and drop text");
auto childStatusBar = new QStatusBar(w);
childStatusBar->showMessage("Status test message");
w->setStatusBar(childStatusBar);
w->setCentralWidget(textEdit);
w->show();
return a.exec();
}
and also QTextEdit has a setStatusTip function that you can add "Show current copy drag and drop text" there instead of childStatusBar.
NOTED: As I mentioned ‍QTextEdit‍ cannot have ‍QStatusBar as you use in your code.
Now, if you don't want to use this method(use QMainWindow ), you have to create a custom and personalized class for yourself.
This means that you have to write the StatusBar by yourself

Set text for statusbar in QtDesigner?

By default, if I create a new Form in QtDesigner, of type "Main Window", I get three elements in there: centralwidget, menubar - which is not visible in Preview (Ctrl-R), unless actual menu entries are added; and statusbar.
The problem is - by default, the statusbar is the same background color as the rest, and so, when I do a Preview, I cannot really perceive whether the statusbar is there or not:
Basically, the only thing I can see is the "sizeGrip", which is not always easy to see - so I would like to have a text/message shown in the statusbar as well.
Now, I know that the API for QStatusBar Class has .showMessage used to show text in a statusbar - however, I cannot find any similar field in QtDesigner?!
So - is it possible to set a default/placeholder text in the statusbar in QtDesigner - and if so, how?
No, you cannot.
In QtDesigner, you can only set properties of a widget (see Q_PROPERTY), not invoke methods. The properties are listed in the Properties section of the documentation, and QStatusBar only has sizeGripEnabled (and the inherited properties from QWidget)
But what is the actual problem? You cannot clearly make out the status bar in the preview? The preview is supposed to help in checking singal/slots and layout constraints, not as a full functioning application.
There are also things that will influence the actual look&feel in the final application that cannot be checked in designer preview, like dynamic stylesheets, or custom styles.
if you want to check how your window looks like with text in the statusbar, you will need to make a mock-application that does just this: show some text
#include <QtCore>
#include <QtWidgets>
#include "ui_mainwindow.h"
int main(int argc, char **argv) {
QApplication app(argc, argv);
Ui::MainWindow ui;
QMainWindow wnd;
ui.setupUi(&wnd);
wnd.show();
ui.statusbar->showMessage("Hello World!");
return app.exec();
}

How to set an icon to a new button in QDialogButtonBox?

I'm trying to make a custom button with an icon in QDialogButtonBox in a Qt5 program (Qt 5.5.1) on Kubuntu 14.04. Reading this answer, I understand that it's not recommended to simply edit the stock buttons, so I use QDialogButtonBox::addButton with my custom button. But for some reason, although I do succeed in changing icon of the stock button, my custom button still remains without any icon after using QPushButton::setIcon.
Here's the code
#include <QApplication>
#include <QDialogButtonBox>
#include <QPushButton>
int main(int argc, char** argv)
{
QApplication app(argc,argv);
QDialogButtonBox bbox(QDialogButtonBox::Close);
const auto button=new QPushButton(QObject::tr("Convert..."));
bbox.addButton(QObject::tr("Convert..."), QDialogButtonBox::ApplyRole);
const auto icon=QIcon::fromTheme("system-run");
// This doesn't work - the button remains without icon
button->setIcon(icon);
// But this does
bbox.button(QDialogButtonBox::Close)->setIcon(icon);
bbox.show();
return app.exec();
}
What am I doing wrong? How can I have an icon on my custom button without the need to edit stock buttons?
You are creating two buttons. One button which you don't show anywhere, and one that you add in bbox. And you are setting the icon for the button that you don't show anywhere.
Fix your code so you don't create two separate buttons, and set an icon for the button you are putting in bbox:
QPushButton *button = bbox.addButton(QObject::tr("Convert..."), QDialogButtonBox::ApplyRole);
...
button->setIcon(icon);

Non-modal QWidget dialog that stays on top of the window

I want a dialog which stays on top of my main window and not other windows. I derived a class and added some flags. If I call the dialog now with show() the dialog appears and is staying on top as long as I don't press a button or whatever. Then the dialog goes to background again.
Dial::Dial(QWidget *parent) : QWidget(parent)
{
this->setWindowFlags(Qt::Tool | Qt::Dialog);
// ...
Consequently, I looked into the docu and found this:
Indicates that the widget is a tool window. A tool window is often a
small window with a smaller than usual title bar and decoration,
typically used for collections of tool buttons. If there is a parent,
the tool window will always be kept on top of it.
Happily, I added this line into my singleton creating the dialog.
d->mainWindow = new Foo();
d->dial->setParent(d->mainWindow);
Now the dialog is just embedded into my central widget (QOpenGlWidget) and is not a dialog anymore. Somehow, I seem to lack understanding what the docu is telling me? How can I get the dialog stay on top of my application and what does the docu mean?
I'm not able to reproduce your problem. The following code will generate a QWidget that will allways stay on top of the QMainWindow:
#include "QApplication"
#include "QMainWindow"
#include "QLineEdit"
int main(int argc, char * argv[])
{
QApplication a(argc, argv);
QMainWindow w;
w.show ();
QWidget *pLineEdit = new QWidget(&w);
pLineEdit->setWindowFlags(Qt::Tool | Qt::Dialog);
pLineEdit->show ();
a.exec ();
}
Tested with Qt 5.9.
Not sure if you've already solved this by now but you can try the WindowStaysOnTopHint flag when you construct the dialog:
Qt::WindowFlags flags = this->windowFlags();
flags |= Qt::WindowStaysOnTopHint;
this->setWindowFlags(flags);
Then use show() instead of exec() to make it non-modal:
dlg->show();
You need to set the modality (documentation) of the widget, like this:
QWidget *dialog = new QWidget(window, Qt::Dialog);
dialog->setWindowModality(Qt::ApplicationModal);
dialog->show();
However, I'd recommend to use the pre-configured QDialog class, which handles all that stuff for you:
QDialog *dialog = new QDialog(window);
dialog->exec();
Use QDialog instead of QWidget, and pass the parent widget in its constructor function.
QDialog* pDlg = new QDialog(this);
pDlg->show();

Set QLineEdit focus in Qt

I am having a qt question. I want the QLineEdit widget to have the focus at application startup. Take the following code for example:
#include <QtGui/QApplication>
#include <QtGui/QHBoxLayout>
#include <QtGui/QPushButton>
#include <QtGui/QLineEdit>
#include <QtGui/QFont>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *window = new QWidget();
window->setWindowIcon(QIcon("qtest16.ico"));
window->setWindowTitle("QtTest");
QHBoxLayout *layout = new QHBoxLayout(window);
// Add some widgets.
QLineEdit *line = new QLineEdit();
QPushButton *hello = new QPushButton(window);
hello->setText("Select all");
hello->resize(150, 25);
hello->setFont(QFont("Droid Sans Mono", 12, QFont::Normal));
// Add the widgets to the layout.
layout->addWidget(line);
layout->addWidget(hello);
line->setFocus();
QObject::connect(hello, SIGNAL(clicked()), line, SLOT(selectAll()));
QObject::connect(line, SIGNAL(returnPressed()), line, SLOT(selectAll()));
window->show();
return app.exec();
}
Why does line->setFocus() sets the focus on the line widget #app startup only if it is placed after laying out the widgets and if used before it's not working?
Keyboard focus is related to widget tab order, and the default tab order is based on the order in which widgets are constructed. Therefore, creating more widgets changes the keyboard focus. That is why you must make the QWidget::setFocus call last.
I would consider using a sub-class of QWidget for your main window that overrides the showEvent virtual function and then sets keyboard focus to the lineEdit. This will have the effect of always giving the lineEdit focus when the window is shown.
Another trick that might work is by using the singleshot timer:
QTimer::singleShot(0, line, SLOT(setFocus()));
Effectively, this invokes the setFocus() slot of the QLineEdit instance right after the event system is "free" to do so, i.e. sometime after the widget is completely constructed.
Perhaps this is an update as the last answer was in 2012 and the OP last edited the question in 2014. They way I got this to work was to change the policy and then set the focus.
line->setFocusPolicy(Qt::StrongFocus);
line->setFocus();
In Qt setFocus() is a slot, you can try other overloaded method which takes a Qt::FocusReason parameter like the line shown below:
line->setFocus(Qt::OtherFocusReason);
You can read about focus reason options in the following link:
http://doc.trolltech.com/4.4/qt.html#FocusReason-enum