views:

228

answers:

3

I am trying to implement a input method with Qt Embedded.

There is a lookup table for choosing the candidate words for typing. "text input area" to the "lookup table" and the selected word cannot be sent to the "text input area".

Dose anyone have any idea to solve this problem? Thanks~


Here I give a simple example:

main.cpp

#include "InputWidget.h"
#include "ButtonWidget.h"
#include <QApplication>

int main(int argc,char *argv[])
{
    QApplication app(argc,argv);
    InputWidget *inputWidget=new InputWidget();
    ButtonWidget *buttonWidget=new ButtonWidget();
    inputWidget->show();
    buttonWidget->show();
    int ref=app.exec();
    inputWidget->deleteLater();
    buttonWidget->deleteLater();
    return ref;
}

InputWidget.h

#include <QWidget>
#include <QPlainTextEdit>

#ifndef _InputWidget_H_
#define _InputWidget_H_

class InputWidget:public QWidget
{
Q_OBJECT
public:
    InputWidget(QWidget *parent=0);
private:
    QPlainTextEdit *inputArea;
};

#endif

InputWidget.cpp

#include "InputWidget.h"
#include <QPushButton>
#include <QVBoxLayout>

InputWidget::InputWidget(QWidget *parent):QWidget(parent)
{
    //input area setup
    inputArea=new QPlainTextEdit(this);
    //main layout
    QVBoxLayout *mainLayout=new QVBoxLayout(this);
    mainLayout->setContentsMargins(1,4,1,1);
    mainLayout->addWidget(inputArea);
    setLayout(mainLayout);
}

ButtonWidget.h

#include <QWidget>
#include <QPushButton>

#ifndef _ButtonWidget_H_
#define _ButtonWidget_H_

class ButtonWidget:public QWidget
{
Q_OBJECT
public:
    ButtonWidget(QWidget *parent=0);
private:
    QPushButton *selectedBtn;
public slots:
    void changeBtnText();
};

#endif

ButtonWidget.cpp

#include "ButtonWidget.h"
#include <QPushButton>
#include <QVBoxLayout>

ButtonWidget::ButtonWidget(QWidget *parent):QWidget(parent)
{
    //selectedBtn setup
    selectedBtn=new QPushButton(tr("Click Me!!"),this);
    connect(selectedBtn,SIGNAL(clicked()),this,SLOT(changeBtnText()));
    //main layout
    QVBoxLayout *mainLayout=new QVBoxLayout(this);
    mainLayout->setContentsMargins(1,4,1,1);
    mainLayout->addWidget(selectedBtn);
    setLayout(mainLayout);
}

void
ButtonWidget::changeBtnText()
{
    selectedBtn->setText("I am clicked :)");
}

Those codes would generate a widget which has a PlainTextEdit "inputArea" and a widget which has a PushButton "selectedBtn".

First, I input some words in the "inputArea". The current foucs is on "inputArea" in the InputWidget.

But when I move mouse to ButtonWidget and click the "selectedBtn", the foucs is changed to "selectedBtn" in the ButtonWidget.

How do I click the "selectedBtn" but still keep the foucs on "inputArea"? Thanks~


Just like my comment described in laura's answer, InputWidget and ButtonWidget may have no identical parent and I cannot use QWidget's "setFocus" slot to change the current focus between them.

A: 

First of all, you will need to make the two widgets know about each other. Once you have done that (by setting the text widget into the button widget or by adding them both to the same parent widget), you can try to see if QWidget's setFocus slot can help you (look at the other slots too, some might be useful for this).

Perhaps implement something like this, in the ButtonWidget:

  1. (in the header) declare a signal foo()
  2. (in the constructor) connect button widget's foo signal to InputWidget's setFocus slot
  3. (in the changeBtnText) after you've done everything you wanted, emit foo()

Note though that setFocus works if the window is active.

laura
Your answer is not suitable for my situation because the "inputArea" may be in any other AP which is running in QT environment and the "selectedBtn" is in the input method panel. They may be two independent programs and have no identical parent.But still thank you for your answer~~
Sibevin Wang
I see - that was not obvious from your example, you might consider adding this comment to the question.
laura
A: 

You might be able to get what you want by playing with the focusPolicy for your widget. Pay attention to the Qt::NoFocus option. I don't think it prevents mouse clicks on your widget, but you'll want to test to be sure.

Caleb Huitt - cjhuitt
I try to set focusPolicy(Qt::NoFocus) on "selectedBtn", but it doesn't work. After doing some tests, I find that if I create an another PushButton "testBtn" in ButtonWidget, set focusPolicy(Qt::NoFocus) on "selectedBtn", and do the steps described in my question. The focus would still change to ButtonWidget and selectedBtn clicked signal would still be triggered, but the focus is on the "testBtn". I.e., the focusPolicy seems only to work with the widgets which have the same parent. But still thanks for your response~~
Sibevin Wang
A: 

Thank laura and cjhuitt, your responses give me a big hint to solve my question.

Because InputWidget and ButtonWidget are two independent widgets, if we want to deal with the focus issue between them, we need a "global" control, i.e., use QApplication to do the focus job.

The key point is using QApplication's "focusChanged" slot and QWidget's "activateWindow". The following is my modification.

main.cpp

#include "InputWidget.h"
#include "ButtonWidget.h"
#include <QApplication>

int main(int argc,char *argv[])
{
    QApplication app(argc,argv);
    InputWidget *inputWidget=new InputWidget();
    ButtonWidget *buttonWidget=new ButtonWidget(0,&app);
    inputWidget->show();
    buttonWidget->show();
    int ref=app.exec();
    inputWidget->deleteLater();
    buttonWidget->deleteLater();
    return ref;
}

ButtonWidget.h

#include <QWidget>
#include <QPushButton>
#include <QApplication>

#ifndef _ButtonWidget_H_
#define _ButtonWidget_H_

class ButtonWidget:public QWidget
{
Q_OBJECT
public:
    ButtonWidget(QWidget *parent=0,QApplication *app=0);
private:
    QPushButton *selectedBtn;
public slots:
    void changeBtnText();
    void changeFocus(QWidget *oldWidget,QWidget *curWidget);
};

#endif

ButtonWidget.cpp

#include "ButtonWidget.h"
#include <QPushButton>
#include <QVBoxLayout>

ButtonWidget::ButtonWidget(QWidget *parent,QApplication *app):QWidget(parent)
{
    //selectedBtn setup
    selectedBtn=new QPushButton(tr("Click Me!!"),this);
    connect(selectedBtn,SIGNAL(clicked()),this,SLOT(changeBtnText()));
    //main layout
    QVBoxLayout *mainLayout=new QVBoxLayout(this);
    mainLayout->setContentsMargins(1,4,1,1);
    mainLayout->addWidget(selectedBtn);
    setLayout(mainLayout);
    //deal with focus
    connect(app,SIGNAL(focusChanged(QWidget*,QWidget*)),this,SLOT(changeFocus(QWidget*,QWidget*)));
}

void
ButtonWidget::changeBtnText()
{
    selectedBtn->setText("I am clicked :)");
}

void
ButtonWidget::changeFocus(QWidget *oldWidget,QWidget *curWidget)
{
    if(oldWidget && curWidget==this)
        oldWidget->activateWindow();
}

InputWidget.cpp and InputWidget are not modified.

This solution can work in this example, but I am not sure that it can work in two independent Qt programs(they have their own QApplication), especially in Qt Embedded environment. I would continue doing some tests on it. If there are any results, I would also post them here.

Thank for this discussion, I have learned a lot and thank you all again!!

Sibevin Wang
This solution is still not suitable for the "input method", because the InputWidget would send out the "focus out" event even I reset the current focus to InputWidget. The "focus out" event would case the input method reset all states and the selected words are also canceled. Maybe I should try to find other information about this topic in the QInputContext or QWSInputMethod.
Sibevin Wang