QLineEdit Subclassing - c++

I have Subclassed QlineEdit. Since I needed a specific operation on mousePress Event.
Now, as soon as I click the mouse on the subclassed QlineEdit (I call it CustomLineEdit). I am trying to pop up a virtual keyboard. A new Window panel shows up, but the virtual keyboard is not showing up. I have checked for the correctness of the virtual keyboard by using it on other classes.
This is my code:
void CustomLineEdit::mousePressEvent(QMouseEvent *s)
{
qDebug() << " Custom Line EDit is kicking";
myKeyBoard->show(this); // once created keyboard object, use this method to switch between windows
myKeyBoard->move(0, 0 + myKeyBoard->height() + 175); // to move keyboard
}
Btw, the virtual keyboard was downloaded from this link.
Any suggestions will highly be appreciated.

myKeyBoard->show(this);
This show method needs a parent to drawing into this widget. If a widget is into another one, it cannot paint out of parent's work area. Maybe, if you change the line in this way, virtual keyboard will show:
myKeyBoard->show( parent( ) );

Related

How to return keyboard control back to an QT window when clicked on it

I am having this weird bug.
I have a class that inherits both QObject and QGraphicsRectItem.
I am having it do something if a key like space bar is pressed. However if I click outside a window, like say my desktop for example, the key no longer works. I tried clicking on the QT window to make the key responsive again but no luck.
Here is my code
Header:
class rectangle : public QObject, public QGraphicsRectItem{
public:
rectangle();
void keyPressEvent(QKeyEvent *event);
}
cpp file:
rectangle::rectangle(){}
void rectangle::keyPressEvent(QKeyEvent *event){
if (event->key() == Qt::Key_Space){
// do something
qDebug() << "Key pressed";
}
}
Normally, clicking on a program would give it back the input control but it isn't the case here. What do I need to do to make the keyPressedEvent worked again after I clicked on another application or just an empty area of my desktop?
Your keyPressEvent does only work if QGraphicsRectItem has focus. This means, if you switch back to your Qt application the focus of QGraphicsRectItem may get lost and another widget (i. e QLabel, MainWindow, etc.) will have focus. Then the keyPressEvent of QGraphicsRectItem will not trigger. You can use installEventFilter to install your keyPressEvent filter on multiple widgets, or you simply use an application wide shortcut.
QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_Space), this);
connect(shortcut, &QShortcut::activated, [](){ qDebug() << "Space pressed"; });

How to disable minimizing by taskbar icon click

I've stumbled across very strange behaviour during work on my program.
I've written custom changeEvent class, which allows me to hide program to SysTray on minimizing.
But when i double click on taskbar app icon, the function goes crazy. It creates 2 to 4 systray icons and on requesting window show again, it just shows main window borders without any content inside.
Here's my changeEvent code:
void MainWindow::changeEvent(QEvent *e) {
QMainWindow::changeEvent(e);
if(e->type()==QEvent::WindowStateChange)
if(isMinimized()) {
trayIcon=new QSystemTrayIcon(QIcon(":/icon/itime.ico"));
connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(on_show(QSystemTrayIcon::ActivationReason)));
QAction *showAction=new QAction("Pokaż",trayIcon);
connect(showAction,SIGNAL(triggered()),this,SLOT(on_show()));
QMenu *trayIconMenu=new QMenu;
trayIconMenu->addAction(showAction);
trayIcon->setContextMenu(trayIconMenu);
trayIcon->show();
this->hide();
}
}
on_show(QSystemTrayIcon::ActivatioReason) SLOT:
void MainWindow::on_show(QSystemTrayIcon::ActivationReason reason) {
if(reason) {
if(reason!=QSystemTrayIcon::DoubleClick)
return;
}
if(this->isMinimized()) {
this->raise();
this->showNormal();
this->setWindowState(Qt::WindowActive);
trayIcon->hide();
}
}
on_show() SLOT is just the same besides that first if.
Soo, I would like to know whether there is any way to disable minimizing of window by taskbar icon click.
If there's none, then maybe you have any ideas what can go wrong in here when doubleclicking on icon in taskbar?
Thanks for help!
I've managed to work around that problem by overloading closeEvent function and leaving alone changeEvent function.
So, I'm using boolean flag to distinct between closing of program by menu item and by clicking "X" button and the rest stays just the same, as posted in my earlier post with one change.
I've moved this whole block of code to window constructor in order to prevent multiple creation of trayIcon, as pointed out by Nicolas.
trayIcon=new QSystemTrayIcon(QIcon(":/icon/itime.ico"));
connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(on_show(QSystemTrayIcon::ActivationReason)));
QAction *showAction=new QAction("Pokaż",trayIcon);
connect(showAction,SIGNAL(triggered()),this,SLOT(on_show()));
QMenu *trayIconMenu=new QMenu;
trayIconMenu->addAction(showAction);
trayIcon->setContextMenu(trayIconMenu);
Thanks for your help!

How to disable scroll function when Ctrl is pressed in QMainWindow

I currently works on QT for my project. I implemented a MainWindow class which inherited from QMainWindow.
In MainWindow, I handled mouse wheel event like this:
void MainWindow::wheelEvent ( QWheelEvent * event )
{
if (event->modifiers().testFlag(Qt::ControlModifier)) {
if (event->delta() > 0) {
zoomInAct();
}
else if(event->delta()<0){
zoomOutAct();
}
}
}
The problem is: when I press CONTROL KEY and Wheel the mouse, the scroll bar alway scroll to top or bottom before reach my wheelEvent function. Would you please help to allow zoom-in/out when press control and wheel the mouse? (Not scroll the scroll bar)
Sorry for my bad english.
Looking at your current implementation here you have not specified event->accept() if you have added your own functionality and you don't want to propagate the event further to the parent. Try adding event->accept() in the if conditions where you have added your logic.
And try adding debug statement to test whether the event is reaching here or someone else is handling the event. By someone else I mean some other child widget. Some description of the UI and what widget is to be zoomed in would be helpful to further investigate the problem.
Make sure you read about the event system in Qt. Docs available here
Acctualy, there is a child widget that handle the wheel event first (default event handle is scroll the scrollbar).
Solution: override wheelevent in child widget to send it to parent widget (MainWindow) when the control key is pressed.
class WorkArea: public QWidget {
...
virtual void wheelEvent(QWheelEvent *event)
{
if(event->modifiers().testFlag(Qt::ControlModifier))
MainWindow::wheelEvent(event);
else
QWidget::wheelEvent(event);
}
...
}

MFC - Changing dialog item focus programmatically

I have a Modeless dialog which shows a bunch of buttons; some of these are customized to draw stuff with GDI.
Now, when the user clicks on a customized one under certain conditions, a message box appears to alert user of the error and this is fine.
The problem is that after accepting the Message Box (showed as MB_ICON_ERROR), everywhere I click in the dialog, I always get the error message as if the whole dialog send the message to the customized button and the only way to get rid this is to press tab and give the focus to another control.
This is a strange behaviour and knowing why happens wouldn't be bad, but a simple workaround for now should do the job.
Since the moment that is probably a matter of focus, I've tried to set it on another control (in the owner dialog) by doing:GetDlgItem( IDC_BTN_ANOTHER_BUTTON )->SetFocus();
and then, inside the customized control by adding:KillFocus( NULL );but had no results.
How should I use these functions?
Thanks in advance.
PS: if I comment the AfxMessageBox, the control does not show this bizarre behaviour.
EDITI'll show some code as requested.
// This is where Message Box is popping out. It is effectively inside the dialog code.
void CProfiloSuolaDlg::ProcessLBtnDownGraphProfilo(PNT_2D &p2dPunto)
{
// m_lboxProfiles is a customized CListBox
if(m_lboxProfiles.GetCurSel() == 0)
{
// This profile cannot be modified.
/*
CString strMessage;
strMessage.Format( _T("Default Profile cannot be edited.") );
AfxMessageBox( strMessaggio, MB_ICONERROR );
*/
return;
}
// Selecting a node from sole perimeter.
SelectNodo(p2dPoint);
}
Actually, the message is commented to keep the dialog working.
// This is inside the customization of CButton
void CMyGraphicButton::OnLButtonDown(UINT nFlags, CPoint point)
{
PNT_2D p2dPunto;
CProfiloSuolaDlg* pDlg = (CProfiloSuolaDlg*)GetParent();
m_pVD->MapToViewport(point,p2dPunto);
switch(m_uType)
{
case GRF_SEZIONE:
pDlg->ProcessLBtnDownGraphProfilo(p2dPunto);
break;
case GRF_PERIMETRO:
pDlg->ProcessLBtnDownGraphPerimetro(p2dPunto);
break;
}
CButton::OnLButtonDown(nFlags, point);
}
Since you are handling the button down event in the button handler for the custom control, you don't need to call the base class. Just comment out CButton::OnLButtonDown(nFlags, point).

QWinWidget Inside MFC Dialog Not Repainting or Responding to Tab/Arrow keys

I am using a QWinWidget inside of an MFC dialog and the QWinWidget is not drawing itself correctly and it is not handling keyboard input correctly.
Repainting [Unsolved]
Within the QWinWidget, I have a QTableWidget. When I scroll the QTableWidget, it does not redraw itself until I stop scrolling, at which point it redraws everything. Similarly, I can type into cells in the QTableWidget and the control is not updated until I force it to re-update by scrolling up or down (it re-updates when the scrolling stops).
Since this QWinWidget is housed in an MFC CDialog, I tried overriding the CDialog's OnPaint method and only call the QWinWidget::repaint method, however this has the opposite problem where now only the QWinWidget is updated and the CDialog is never redrawn, resulting in artifacts. If I call QWinWidget::repaint and CDialog::OnPaint, the result is the same as not overriding the OnPaint method. Has anyone ever seen this problem or know how to resolve it?
Keyboard Input [Solved]
None of the controls within the QWinWidget respond to the tab key or arrow keys correctly. The tab/arrow keys simply skip over the entire QWinWidget (and all child controls). Even if I click inside the QWinWidget and select a control, the next time I press the tab key, it skips the focus completely out of the entire QWinWidget.
I noticed that the QWinWidget has two functions, QWinWidget::focusNextPrevChild and QWinWidget::focusInEvent and both of them have a comment header saying "\reimp". Am I supposed to override these functions in order to get correct tab functionality? If so, how can these functions be implemented for correct tab functionality.
I have fixed the keyboard input issue. The QWinWidget class needed some changes:
in the QWinWidget::init method, the WS_TABSTOP must be added to the window style:
SetWindowLong(winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP);
Also, the QWinWidget::winEvent method needs to respond to the WM_GETDLGCODE to let Windows know that it is interested in receiving key/tab inputs. I had to add this if block:
if(msg->message == WM_GETDLGCODE)
{
*result = DLGC_WANTARROWS | DLGC_WANTTAB;
return(true);
}
I am still working on getting the widget to paint properly.
I don't know about whether you need to reimplement the focusNextPrevChild() and focusInEvent() functions, but I do know that the "\reimp" in the comment header is part of Qt's documentation generation, which merely specifies that the function was a reimplementation of another function in a parent class.
Thanks! It works for me! I have fixed an arrow keys navigation issue for a QTableView inside a QWinWidget.
I am using Qt5.3.0 and qtwinmigrate 2.8.
The QWinWidget::nativeEvent method needs to be modified.
#if QT_VERSION >= 0x050000
bool QWinWidget::nativeEvent(const QByteArray &, void *message, long *result)
#else
...
{
...
if (msg->message == WM_SETFOCUS) {
...
} else if (msg->message == WM_GETDLGCODE) {
*result = DLGC_WANTALLKEYS;
return true;
}
return false;
}
No idea about the keyboard input, but concerning the repainting: have you tried calling QWinWidget::repaint() in the CDialog's OnPaint method AFTER calling the CDialog::OnPaint()?