I faced an error and I didn't found any solutions for this problem. So I have made a subclass from QLineEdit, and overrided a keyPressEvent method. Now if I try to write something it doesn't allow it, but it triggers the event. Any advices?
.h
class PlayerQLineEdit : public QLineEdit
{
public:
PlayerQLineEdit();
void keyPressEvent(QKeyEvent *);
};
.cpp
PlayerQLineEdit::PlayerQLineEdit()
{
setDisabled(false);
}
void PlayerQLineEdit::keyPressEvent(QKeyEvent *)
{
}
You have to call the base class event handler. Otherwise the line edit can't get any key presses!
void PlayerQLineEdit::keyPressEvent(QKeyEvent *event)
{
// ... do stuff
// optionally return before calling base class handler to suppress key strokes.
QLineEdit::keyPressEvent(event);
// ... do stuff
}
Related
I have third party widget which provides me some context menu. Lets say cut, copy paste, select all.
Now I just want to modify only the paste functionality of the existing context menu. I know that I can implement whole context menu from scratch in the contextMenuEvent. But I do not want to do that as I am satisfied with other context menu actions, and just want to modify only the paste functionality.
I am using QT 4.8 on Mac OSX.
If such a thing is not possible at the moment can someone give me link/reference for that ? So that I can satisfy my stakeholders.
Edit: To be more clearer on what I am trying to do is, disable the paste context menu for some reason, and want to enable it later on depending on the situation/events.
I'm not sure that it can be done in a common way.
Here is a tricky solution:
In contextMenuEvent create a queued call to some slot:
QMetaObject::invokeMethod(this, "patchMenu", Qt::QueuedConnection);
Get visible windows in the slot and find QMenu. Get actions out of it and enable/disable them:
Q_SLOT patchMenu()
{
QWidgetList widgets = QApplication::topLevelWidgets();
foreach (QWidget* widget, widgets)
{
if (QMenu* menu = qobject_cast<QMenu*>(widget))
{
QList<QAction*> actions = menu->actions();
// here you can either get an action by index actions[5]
// or search the action by text
actions;
}
}
}
EDIT:
Here is a working example which demonstrates this approach:
window.h
#pragma once
#include <QtGui>
class Window: public QMainWindow
{
Q_OBJECT
public:
Window(QWidget *parent = 0);
};
class A : public QWidget
{
public:
virtual void contextMenuEvent(QContextMenuEvent* e);
};
class B : public A
{
Q_OBJECT;
public:
virtual void contextMenuEvent(QContextMenuEvent*);
Q_SLOT void patchMenu();
};
window.cpp
#include "window.h"
Window::Window(QWidget *parent) : QMainWindow(parent)
{
setCentralWidget(new B());
}
void B::patchMenu()
{
QWidgetList widgets = QApplication::topLevelWidgets();
foreach (QWidget* widget, widgets)
{
if (QMenu* menu = qobject_cast<QMenu*>(widget))
{
QList<QAction*> actions = menu->actions();
// here you can either get an action by index actions[5]
// or search the action by text
actions;
}
}
}
void B::contextMenuEvent(QContextMenuEvent* e)
{
QMetaObject::invokeMethod(this, "patchMenu", Qt::QueuedConnection);
A::contextMenuEvent(e);
}
void A::contextMenuEvent(QContextMenuEvent* e)
{
QMenu menu;
QAction* action = new QAction(QIcon(), "text", &menu);
menu.addAction(action);
menu.exec(e->globalPos());
}
I want to show osk.exe(onscreenkeyboard) when click on the QLineEdit and when focus out osk.exe hide or minimized?
how can i do?
thanks
You need to use a QProcess and reimplement the methods QLineEdit::focusInEvent and QLineEdit::focusOutEvent. Try implement a class inheriting from QLineEdit like this:
#include <QLineEdit>
#include <QProcess>
class MyLineEdit: public QLineEdit
{
public:
MyLineEdit(QWidget * parent = 0): QLineEdit(parent)
{
process_ = new QProcess();
}
protected:
void focusInEvent(QFocusEvent * e)
{
QLineEdit::focusInEvent(e);
process_->start("start C:\\osk.exe");
}
void focusOutEvent(QFocusEvent * e)
{
QLineEdit::focusOutEvent(e);
process_->kill();
}
private:
QProcess * process_;
}
(Of course replace C:\\osk.exe by the exact address of this osk.exe).
Then just use a MyLineEdit instead of a QLineEdit, it should work. I do not know how to hide or minimize the process, so I decided to kill it and restart it if necessary instead ;-)
Is there a signal that tells when 'show' function finishes?
I have a problem in my code: If I write:
QMainWinObj.show();
QMainWinObj.someGuiFunc();
the code doesn't work. But, if I write:
QMainWinObj.show();
sleep(3000);
QMainWinObj.someGuiFunc();
It does.
So I think the problem is that 'show' dosn't finish its jub before I call 'someGuiFunc'. That's why I want to have some kind of a sign that 'show' is finished..
This may be a bit dated but since nobody else answered it except the one:
Since there is no "Show" signal I suggest overriding the show event like this:
In your mainwindow.cpp file:
void MainWindow::show()
{
QMainWindow::show();
QApplication::processEvents();
emit windowShown();
}
In your mainwindow.h file, somewhere in MainWindow's declaration:
...
class MainWindow: public QMainWindow
{
...
signals:
void windowShown();
...
}
...
Then, when you go to the designer, right click on the main window (very top of the object tree), and select "Change signals/slots". In the "Signals" frame, click the "+" button, and you will need to add "windowShown()" and then press enter, and then the OK button (note that the elipses "..." denote other code that is already in your header).
That's it -- you can now use the signals/slots editor to link slots up to the 'windowShown' signal whenever you want. Now if you want something more like Microsoft's "Loaded" event which I think is used in .NET you will need to create some instance variable and flag it so that every time the window is shown, it isnt emitted, for example:
void MainWindow::show()
{
QMainWindow::show();
QApplication::processEvents();
emit windowShown();
if (firstTimeShown == true)
{
emit windowLoaded();
firstTimeShown = false;
}
}
Also, don't forget to initialize the variable to 'true' in your constructor:
MainWindow::MainWindow(QObject* parent)
...
{
firstTimeShown = true; // put this somewhere before ui->setupUi()
}
If you decide to put it in the initializer list however, make sure it is in proper order. The compiler will complain if the variables are not instantiated in a top-to-bottom fashion as declared in the class' header.
Now, make sure when you define firstTimeShown in your header, that you make it private. And lets not forget the added signals:
class MainWindow : public QMainWindow
{
...
signals:
void windowLoaded();
void windowShown();
private:
bool firstTimeShown;
...
That's about it. With the flexibility of signals and slots, its pretty easy to mimic any event that you might find from windows forms or from MFC. It just takes a little effort on the programmer's part. Once you get the hang of it however it it'll be like second nature.
note: there probably are optimizations or better and more precise ways of making the "Loaded" and "Shown" signals perform but I have left things like this out for simplicity's sake. And to come back to the question at hand, calling QApplication::processEvents() is most likely what you want to do instead of waiting a fixed amount of time because who knows how long it will take if the user is running 100 other things on top of it, etc, etc. Hope that helped, the extra explanation was included hoping that it might give you a better way to do the things that you want to do instead of waiting for something to be done, 'knowing' it is done is a much better alternative.
There is no such signal, but having QMainWindow subclassed you can override showEvent event.
void MainWindow::showEvent(QShowEvent *){
//your code
}
More info here: http://qt-project.org/doc/qt-4.8/qwidget.html#showEvent
Be aware it's called every time your window is about to be displayed.
Problem can decide without subclassing, just installing event filter like this:
class CWidgetIsPainting_EF : public QObject
{
bool m_bIsPainted = false;
public:
CWidgetIsPainting_EF( QObject * parent = 0 ) : QObject (parent) { }
inline bool IsPainted() const { return m_bIsPainted; }
inline void setIsPainted( bool bIsPainted ) { m_bIsPainted = bIsPainted; }
protected:
bool eventFilter( QObject * obj, QEvent *event )
{
if (event->type() == QEvent::Paint)
{
m_bIsPainted = true;
return true;
};
return QObject::eventFilter(obj, event);
}
};
...
...
CWidgetIsPainting_EF * pPaintingEF = new CWidgetIsPainting_EF( m_pWidget );
m_pWidget->installEventFilter( pPaintingEF );
...
...
while ( !pPaintingEF->IsPainted() )
QApplication::processEvents();
Override bool event(QEvent *event) and catch the Paint event. Works for me at least on Windows.
// MainWindow.h
class MainWindow : public QMainWindow
{
...
bool event(QEvent *event) override;
void functionAfterShown();
...
bool functionAfterShownCalled = false;
...
}
// MainWindow.cpp
bool MainWindow::event(QEvent *event)
{
const bool ret_val = QMainWindow::event(event);
if(!functionAfterShownCalled && event->type() == QEvent::Paint)
{
functionAfterShown();
functionAfterShownCalled = true;
}
return ret_val;
}
I have a QLineEdit widget in my menubar which shows the text "search by ID" by default. How can I implement a MouseClicked event handler for the QLineEdit, such that when I click on the LineEdit widget, the default text is cleared and user can enter the text that he wants to search?.
so far
#ifndef SEARCH_H
#define SEARCH_H
#include<QLineEdit>
class search : public QLineEdit
{
signals:
void clicked();
protected:
void mousePressEvent(QMouseEvent *);
};
#endif
You just need to connect QLineEdit::mousePressEvent ( QMouseEvent * e ) signal with function. When this signal will be emited, clear QLineEdit in your function. Simply, isn't it?
EDIT
Or if u have
void mousePressEvent(QMouseEvent *);
in your widget, all what you need is write definition for that method. When user press mouse over QLineEdit, this function will be invoked. Like:
void search::mousePressEvent(QMouseEvent *e)
{
myQLineEdit->setText("");
}
EDIT 2
Then try to do it this way:
class YourWidget : public QLineEdit
{
Q_OBJECT
protected:
void focusInEvent(QFocusEvent* e);
};
and
void YourWidget::focusInEvent(QFocusEvent* e)
{
if (e->reason() == Qt::MouseFocusReason)
{
myQLineEdit->setText("");
}
// You might also call the parent method.
QLineEdit::focusInEvent(e);
}
You'll want to use the QLineEdit::placeholderText property. It shows a grey text which disappears when the user starts editing it (i.e. when it gains focus).
QLineEdit * edit = new QLineEdit;
edit->setPlaceholderText("Search by ID");
I have a QTableView to display a bunch of data, which is stored in a QAbstractTableModel. I also want to edit the data sometime, so I use a QStyledItemDelegate to create an editor (of QTextEdit type) when I double click on the cell. However, I want to handle the key Press event myself, but I never catch Key_Escape pressing in the Text Edit editor (Other keys such as Enter and Ascii can be captured). I checked the code, and found that Escape is directly connected to QTableView's closeEditor() function, which is a virtual method and is automatically invoked. As far as I know, key press event is the bottom layer of event handling, but it is not true with such case.
I do need to capture the Escape key press event so that I can handle it myself, can anyone tell me how to do this? Thanks!
I got the answer, and I think would help others:
Override QStyledItemDelegate::eventFilter() method:
MyItemDelegate::eventFilter(QObject* editor, QEvent* event)
{
if(event->type()==QEvent::KeyPress)
return false;
return QStyledItemDelegate::eventFilter(editor, event);
}
According to Qt's documentation, QStyledItemDelegate::eventFilter() returns true if the given editor is a valid QWidget and the given event is handled; otherwise returns false. Tab, Backtab, Enter, Return and Ecs are handled by default. So, if you want to handle the key press event yourself, you must let eventFilter return false when KeyPress event occurs. So that the editor's keyPressEvent() method will be invoked instead.
QStyledItemDelegate::eventFilter is not a possibility beacuse is virtual protected
In order to get the events you should subclass your own QEditLine and override ::keyPressEvent there. Take notice of the code. I pass actual row and colum of my QTableWidget cell in order to know what we are editing in the overrided QLineEditor.
//.h
class MyStyledItemDelegate : public QStyledItemDelegate
{
public:
MyStyledItemDelegate(QObject *parent = 0);
QWidget* createEditor(QWidget* parent,const QStyleOptionViewItem &option,const QModelIndex &index) const;
};
//.cpp
#include "mylineedit.h"
MyStyledItemDelegate::MyStyledItemDelegate(QObject *parent)
:QStyledItemDelegate(parent)
{
}
QWidget* MyStyledItemDelegate::createEditor(QWidget* parent,const QStyleOptionViewItem &option,const QModelIndex &index) const
{
MyLineEdit* editor = new MyLineEdit(parent,index.row(),index.column());
return editor;
}
/////////////////////////////////////////////////////////////
//My own QLineEdit
/////////////////////////////////////////////////////////////
//.h
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
int _nRow;
int _nCol;
public:
MyLineEdit(QWidget *parent = 0,int nRow=-1, int nCol=-1);
virtual void keyPressEvent(QKeyEvent* event);
signals:
void mySignal(const QVector<QVariant> &);
public slots:
};
//.cpp
MyLineEdit::MyLineEdit(QWidget *parent, int nRow,int nCol):
QLineEdit(parent)
{
_nRow=nRow;
_nCol=nCol;
}
/////////////////////////////////////////////////////////////////////////
void MyLineEdit::keyPressEvent(QKeyEvent* event)
{
qDebug() << "MyLineEdit::OnKeyPressEvent:"<<event->text()<< " row="<<_nRow<<" col=" <<_nCol;
///SET YOUR CODE HERE
QLineEdit::keyPressEvent(event);
}