QtVirtualKeyboard focus problem when editing a cell in a QTableView - c++

I have been battling for the last couple of days to include the QtVirtualKeyboard into my QWidget based app that is running on a Raspberry Pi with a 7" touch screen display.
Here's what I've done so far :
Installed the plugin :
sudo apt-get install -y qtvirtualkeyboard-plugin
sudo apt-get install -y qml-module-qtquick-controls2
sudo apt-get install -y qtdeclarative5-dev
sudo apt-get install qml-module-qt-labs-folderlistmodel
Added the QT_IM_MODULE environment variable and set that to qtvirtualkeyboard
Added QT += quickwidgets to my .pro
Created a QQuickWidget to place my virtual keyboard.
.h
private:
QQuickWidget *m_quickWidget;
.cpp
// In constructor
QUrl source(QML_FILE_PATH + "virtualkeyboard.qml");
m_quickWidget->setSource(source);
m_quickWidget->setAttribute(Qt::WA_AcceptTouchEvents);
ui->verticalLayout->addWidget(m_quickWidget);
And finally my virtualkeyboard.qml file
import QtQuick 2.7
import QtQuick.VirtualKeyboard 2.1
Rectangle {
id: window
width: 600
height: 0
InputPanel {
id: inputPanel
width: window.width
states: State {
name: "visible"
when: inputPanel.active
PropertyChanges {
target: window
height: inputPanel.height
}
}
transitions: Transition {
from: ""
to: "visible"
reversible: true
ParallelAnimation {
NumberAnimation {
properties: "y"
duration: 250
easing.type: Easing.InOutQuad
}
}
}
}
}
So up to now, visually everything is looking pretty good. When I open my app, the keyboard widget is not visible (window height: 0 in qml), and when I double-click a cell in my QTableView (which has flags Qt::ItemIsEnabled | Qt::ItemIsEditable), the keyboard widget shows up at the bottom of my vertical layout at the right position and size.
And now to my problems :
The main problem I have is when I double-click on my editable cell, my keyboard widget shows up and my cell seems to still have focus (blinking cursor is visible in the clicked cell). Up to now all is working well. But when I click a button on the virtual keyboard, the editable cell loses focus, the keyboard widget closes, and I get this error in my application console :
InputContext::sendKeyClick(): no focus to send key click - QGuiApplication::focusWindow() is: QWidgetWindow(0x1e68250, name="ConfigWindow") where ConfigWindow is the name of the base widget in my Designer form.
Another smaller yet seemingly unsolvable issue I have is that the keyboard only opens up when I double-click a cell in my QTableView. This is a weird one because i set the editTriggers to CurrentChanged in my designer. I know that works because if I single click my cell, the cursor starts blinking and if I use my physical keyboard which is connected to my raspberry, I can edit the text. (Of course, the physical keyboard is only available during the development of my app and won't be available in the finished product).
I hope I have been clear enough, but will gladly provide more details if required.
Any help on either of these issues would be greatly appreciated.
Cheers.
EDIT:
Some useful links I have come across:
Qt Virtual Keyboard in QQuickWidget
Resize qtvirtualkeyboard according to QObject
Qt Virtual Keyboard

Ok, so after another few days of all out war with the virtual keyboard, I have finally achieved the desired result.
After finding this gem of a guide, it turns out that because the widget containing my QTableView and QtVirtualKeyboard was a QDialog that was being displayed using the exec() method, it meant that the window properties wouldn't allow the keyboard to modify my data. And while the solution proposed in the guide didn't resolve my problem, making my widget inherit QWidget did set me off along the path to getting it all working properly.
I say this because once I changed my QDialog into a QWidget, I then had a console output error saying unknown:0 input method is not set every time I pressed a key.
The solution to this was to remove the Qt:Dialog flag from my setWindowFlags() method. And maybe most importantly, set the focus policy of my QQuickWidget to NoFocus like so:
// In constructor
QUrl source(QML_FILE_PATH + "virtualkeyboard.qml");
m_quickWidget->setSource(source);
m_quickWidget->setAttribute(Qt::WA_AcceptTouchEvents);
m_quickWidget->setFocusPolicy(Qt::NoFocus);
ui->verticalLayout->addWidget(m_quickWidget);
Hallelujah!! My QtVirtualKeyboard finally sends the clicked keys to my editable cell.
Finally, to open the keyboard with a single click on a cell in my table, I'm sure there is a better solution than this, but i connected a slot to my QTableView's pressed signal and manually set the visibility of the input method:
void ConfigWindow::on_tableView_pressed(const QModelIndex &index)
{
if ((index.column() == 0) || (index.column() == 1))
{
QApplication::inputMethod()->show();
}
}
Hope this helps anyone having the same trouble as me with this powerful yet painfully under-documented plugin.

Related

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

Qt: Can't set drag mode

I've been stuck on this for a little while now, I'm trying to set the drag mode of my QGraphicsView to ScrollHandDrag so that I can build a panning feature on my application.
However whenever I try to set the drag mode Qt always complains that DragMode is an undeclared identifier.
I'm also aiming to build a crop functionality (I assume I'd be using rubber band dragging for that?), I'm just wondering why I can't set the drag mode on the View
void MainWindow::on_btnCrop_clicked()
{
cropping = true;
QApplication::setOverrideCursor(Qt::CrossCursor);
// Stuck with this...
ui->imageView->setDragMode(ScrollHandDrag);
}
^ I have tried multiple other workarounds but I've not yet found any solution, any suggestions would be greatly appreciated.
This is not QGraphicsView specific an issue, but generic C++. Your problem is located at this line:
ui->imageView->setDragMode(ScrollHandDrag);
The problem is that you assume that you have visibility to the ScrollHandDrag value, whereas it appears inside the QGraphicsView scope. Therefore, since you are trying to access that value in your MainWindow, you will need add the scope explicitly as follows:
ui->imageView->setDragMode(QGraphicsView::ScrollHandDrag);
Note that how even the documentation specifies the scope for this constant:
QGraphicsView::ScrollHandDrag 1 The cursor changes into a pointing hand, and dragging the mouse around will scroll the scrolbars. This mode works both in interactive and non-interactive mode.
Here is my minimal building code:
#include <QGraphicsView>
int main()
{
QGraphicsView graphicsView;
graphicsView.setDragMode(QGraphicsView::ScrollHandDrag);
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT += widgets
SOURCES += main.cpp
Build and Run
qmake && make

libvncclient SendPointerEvent sending only left button

I am working on a VNC viewer using Qt 5 and the libvncserver / libvncclient library. I am subclassing a QWidget object to provide the VNC viewer widget.
I'm able to connect to a VNC server (running TightVNC and Windows XP), I'm able to move the remote cursor, able to left-click and able to drag things through the viewer, however I have been unsuccessful in getting right-clicks to work. It's as if the server is ignoring right-clicks sent to it, although wherever I right-click does seem to change the focus of the window on the server, but not icons.
Unfortunately the libvncclient documentation is not very helpful if you aren't already an expert. I did look through several projects' code for help, and tried using the approaches there with no success. The one I've settled on for reference is:
https://github.com/LibVNC/libvncserver/blob/master/client_examples/SDLvncviewer.c#L383
This is the SendPointerEvent function:
rfbBool SendPointerEvent (rfbClient * client,
int x,
int y,
int buttonMask
)
The relevant excerpt from the documentation:
A pointer event includes a cursor location and a button mask. The
button mask indicates which buttons on the pointing device are
pressed. Each button is represented by a bit in the button mask. A 1
indicates the button is pressed while a 0 indicates that it is not
pressed.
You may use these pre-defined button masks by ORing them
together: rfbButton1Mask, rfbButton2Mask, rfbButton3Mask,
rfbButton4Mask rfbButton5Mask
I'm not understanding when, where and how I should use these pre-defined button masks. I looked at the enum and they all just correspond with '1', '2', '3', etc. Qt emits '1' for left button and '2' for right button.
Here is my relevant code:
static int nButtonMask;
void VncViewer::handleMouseEvents(QMouseEvent* event)
{
if (event->type() == QMouseEvent::MouseButtonPress) {
nButtonMask |= event->button();
}
if (event->type() == QMouseEvent::MouseButtonRelease) {
nButtonMask &= ~event->button();
}
SendPointerEvent(g.currentViewer->client, event->x(), event->y(), nButtonMask);
nButtonMask &= ~(rfbButton4Mask | rfbButton5Mask);
}
Any clues on how to make right-clicks work?
Thank you in advance :-)
This is resolved.
The problem was that the button numbers emitted by Qt were not matching up with the rfb buttons expected by the VNC server. Again, libvncserver's documentation was very unhelpful, so the button mapping issue wasn't noticeable right away.
All is working well now. :-D Thanks!

Touch Up Inside event not working after rotation of tab bar

I have a button in one of view controller of tab bar controller. All set up in storyboard. I registered action method like this
- (IBAction)buttonPressed:(id)sender {
NSLog(#"Button pressed");
}
The thing is that once I make left and top constraints (to force it stay in the right upper corner) touch up inside event stops working after I change rotation. So just open app in portrait mode - method is working. Change to landscape and I cannot tap button suddenly.
I've recreated problem in this easy example project.
Many thanks.
Just put the following code in you TabBarViewController class.
- (void)viewDidLayoutSubviews
{
// fix for iOS7 bug in UITabBarController
self.selectedViewController.view.superview.frame = self.view.bounds;
}
Recently I noticed same bug in my application. First I tried Slavco Petkovski method. But this caused me another bug with rotating and getting right bounds and frame, so I kept searching.
I found another solution for this problem, mainly setting autoresizing mask of view controller's view in xib. But since arrows in inspector in my Xcode (version 5.0.1) are inactive and you can't set them, you have to open xib file in text editor find autoresizingMask property for main view and change it like this:
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
EDIT:
Alternatively you can do this in your view controller's code - same result as in changes in xcode:
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

How to gray out a menu item again in Qt

I am working with qt and have created a menu bar like "File" with some sub menu items "Open", "Save", "SaveAs", "Close", "Quit". I also created actions like "actionNew", "actionOpen", ... and so on. I used the same actions for the tool bar and disable the menu and tool bar items into the constructor with the "disableItems()" function, that works fine and the tool bar and menu items are gray out. If I clicked the sub menu item "New", the tool bar and menu items are enabled and not gray out, that also works fine, but if I clicked the sub menu item "Close" only the tool bar items gray out and the menu items are still enabled :(. How can i fix it? Hope you can help me and sorry for my bad English ;)
MainWindow::MainWindow(QWidget *parent)
:QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
/* disable menu items and tool bar items */
disableItems();
}
void MainWindow::disableItems()
{
ui->actionSave->setEnabled(false);
ui->actionSaveAs->setEnabled(false);
ui->actionClose->setEnabled(false);
}
void MainWindow::enableItems()
{
ui->actionSave->setEnabled(true);
ui->actionSaveAs->setEnabled(true);
ui->actionClose->setEnabled(true);
}
void MainWindow::on_actionNew_triggered()
{
enableItems();
}
void MainWindow::on_actionClose_triggered()
{
disableItems();
}
I had the same problem.
I was puzzled because the code behaved differently from Linux 64 (where usually I develop), Windows (customer machine), Linux 32 (old development & backup machine). Then I realized the difference in version.
The only way to solve I found was to upgrade from default QtSDK that came with my Ubuntu distribution to the latest downloaded from here.
I suggest to check if the version you are using can be upgraded.
HTH
edit I noticed that they changed something more radical: after the upgrade the menubar is not more shared on 'top screen' but more traditionally inside the 'main window'. Probably the team overlooked a portability problem, that's reasonable considering the wide target they have.