Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt 使浮动QDockWidget不可聚焦_Qt - Fatal编程技术网

Qt 使浮动QDockWidget不可聚焦

Qt 使浮动QDockWidget不可聚焦,qt,Qt,我正在QDockWidget中创建一个简单的虚拟键盘… 当小部件停靠在QMain窗口中时,所选小部件(例如qdoublespinbox)将高亮显示,如果我单击虚拟键盘clearFocus(),它将工作 当QDockWidget在窗口上方浮动时,我单击一个按钮,clearFocus不工作,我在QMainWindow中看不到聚焦的widget 如何强制QDockWidget完全没有焦点 谢谢:-) 代码如下: // class MyVirtualKeyboard : public QDockWidg

我正在QDockWidget中创建一个简单的虚拟键盘…
当小部件停靠在QMain窗口中时,所选小部件(例如qdoublespinbox)将高亮显示,如果我单击虚拟键盘clearFocus(),它将工作

当QDockWidget在窗口上方浮动时,我单击一个按钮,clearFocus不工作,我在QMainWindow中看不到聚焦的widget

如何强制QDockWidget完全没有焦点

谢谢:-)

代码如下:

// class MyVirtualKeyboard : public QDockWidget

void MyVirtualKeyboard::sendKey(Qt::Key key, Qt::KeyboardModifier mod)
{
    this->clearFocus();

    QMainWindow *w = dynamic_cast<QMainWindow *>(this->parent());
    if(w == NULL) return;

    QWidget *widget = w->focusWidget();

    QString repr = QKeySequence(key).toString();

    QKeyEvent *pressEvent = new QKeyEvent(QEvent::KeyPress, key, mod, repr);
    QKeyEvent *releaseEvent = new QKeyEvent(QEvent::KeyRelease, key, mod, repr);

    qDebug("%s", pressEvent->text().toAscii().data());

    MyApplication *app = MyApplication::myInstance();

    app->postEvent(widget, pressEvent);
    app->postEvent(widget, releaseEvent);
}

void MyVirtualKeyboard::on_BTN_1_clicked()
{
    sendKey(Qt::Key_1);
}

...
//类MyVirtualKeyboard:公共QDockWidget
void MyVirtualKeyboard::sendKey(Qt::Key,Qt::KeyboardMod)
{
这->clearFocus();
QMainWindow*w=dynamic_cast(this->parent());
如果(w==NULL)返回;
QWidget*widget=w->focusWidget();
QString repr=QKeySequence(key).toString();
QKeyEvent*pressEvent=新的QKeyEvent(QEvent::按键、按键、mod、repr);
QKeyEvent*releaseEvent=新的QKeyEvent(QEvent::KeyRelease,key,mod,repr);
qDebug(“%s”,按事件->文本().toAscii().data());
MyApplication*app=MyApplication::myInstance();
app->postEvent(小部件,按事件);
app->postEvent(小部件,releaseEvent);
}
void MyVirtualKeyboard::在点击1时()
{
sendKey(Qt::Key_1);
}
...
应该不需要调用
clearFocus()。您的dock小部件及其所有小部件必须具有
Qt::NoFocus
策略

下面的代码显示了如何执行此操作

// https://github.com/KubaO/stackoverflown/tree/master/questions/vkb-focus-18558664
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif

class Keyboard : public QDockWidget {
   Q_OBJECT
   QWidget m_widget;
   QGridLayout m_layout{&m_widget};
   QToolButton m_buttons[10];
   void sendKey(Qt::Key key, Qt::KeyboardModifier mod)
   {
      if (! parentWidget()) return;
      auto target = parentWidget()->focusWidget();
      if (! target) return;

      auto repr = QKeySequence(key).toString();
      auto pressEvent = new QKeyEvent(QEvent::KeyPress, key, mod, repr);
      auto releaseEvent = new QKeyEvent(QEvent::KeyRelease, key, mod, repr);
      qApp->postEvent(target, pressEvent);
      qApp->postEvent(target, releaseEvent);
      qDebug() << repr;
   }
   Q_SLOT void clicked() {
      auto key = sender()->property("key");
      if (key.isValid()) sendKey((Qt::Key)key.toInt(), Qt::NoModifier);
   }
public:
   explicit Keyboard(const QString & title, QWidget *parent = nullptr) : Keyboard(parent) {
      setWindowTitle(title);
   }
   explicit Keyboard(QWidget *parent = nullptr) : QDockWidget(parent) {
      int i{};
      for (auto & btn : m_buttons) {
         btn.setText(QString::number(i));
         btn.setProperty("key", Qt::Key_0 + i);
         m_layout.addWidget(&btn, 0, i, 1, 1);
         connect(&btn, SIGNAL(clicked()), SLOT(clicked()));
         btn.setFocusPolicy(Qt::NoFocus);
         ++i;
      }
      setWidget(&m_widget);
      setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
   }
};

int main(int argc, char ** argv)
{
   QApplication a(argc, argv);
   QMainWindow w;
   w.setCentralWidget(new QLineEdit);
   w.addDockWidget(Qt::TopDockWidgetArea, new Keyboard("Keyboard", &w));
   w.show();
   return a.exec();
}

#include "main.moc"

//https://github.com/KubaO/stackoverflown/tree/master/questions/vkb-focus-18558664
#包括
#如果QT\u版本>=QT\u版本检查(5,0,0)
#包括
#恩迪夫
类键盘:公共QDockWidget{
Q_对象
QWidget-mu-widget;
QGridLayout m_布局{&m_小部件};
QToolButton m_按钮[10];
void sendKey(Qt::Key,Qt::KeyboardModifier)
{
如果(!parentWidget())返回;
auto target=parentWidget()->focusWidget();
如果(!target)返回;
auto repr=QKeySequence(key).toString();
auto pressEvent=新的QKeyEvent(QEvent::按键、按键、mod、repr);
自动释放事件=新的QKeyEvent(QEvent::KeyRelease,key,mod,repr);
qApp->postEvent(目标,按事件);
qApp->postEvent(目标、发布事件);
qDebug()属性(“键”);
if(key.isValid())sendKey((Qt::key)key.toInt(),Qt::NoModifier);
}
公众:
显式键盘(常量QString&title,QWidget*parent=nullptr):键盘(parent){
设置窗口标题(标题);
}
显式键盘(QWidget*parent=nullptr):QDockWidget(parent){
int i{};
用于(自动和btn:m_按钮){
btn.setText(QString::number(i));
btn.setProperty(“key”,Qt::key_0+i);
m_layout.addWidget(&btn,0,i,1,1);
连接(&btn,信号(单击()),插槽(单击());
btn.setFocusPolicy(Qt::NoFocus);
++一,;
}
setWidget(&m_widget);
setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
}
};
int main(int argc,字符**argv)
{
质量保证申请a(argc、argv);
qmainw窗口;
w、 setCentralWidget(新QLineEdit);
w、 addDockWidget(Qt::TopDockWidgetArea,新键盘(“键盘”、&w));
w、 show();
返回a.exec();
}
#包括“main.moc”

通过设置=,可以防止小部件聚焦

然而,这里有两个混合的概念——聚焦控件(每个窗口)和活动窗口(每个桌面)。我认为在您描述的场景中(一个被撕掉的弹出窗口),OS窗口管理器可能仍然会更改活动的顶级窗口,即使Qt没有设置聚焦控件。这将导致没有人拥有键盘焦点(这是一个有效状态!)

所以我认为你的问题的完整答案将涉及一些不可移植的比特。我不知道您使用的是什么GUI环境,但我知道Win32的一些答案,因此我将继续讨论,希望这会有用:

Win32 文章中对MSDN上Win32的状态跟踪进行了很好的讨论。我不知道Qt会做任何事情来包装这个级别,所以您必须使用或进入低级别事件。如果您可以对窗口进行子类化,我更喜欢前者,因为它更独立

bool FooWidget::nativeEvent(const QByteArray & eventType, void * message, long * result)
{
#ifdef Q_OS_WIN
    if(eventType == "windows_generic_MSG") {
        const MSG *msg = reinterpret_cast<MSG *>(message);
        if(msg->message == WM_MOUSEACTIVATE) {
            *result = MA_NOACTIVATE;
            return true;
        }
    }
#else
    #error Need platform-specific code to suppress click-activation
#endif
    return false;
}
boolfoowidget::nativeEvent(常量QByteArray和事件类型、void*消息、long*结果)
{
#如果你赢了
if(eventType==“windows\u generic\u MSG”){
const MSG*MSG=reinterpret_cast(消息);
如果(消息->消息==WM_MOUSEACTIVATE){
*结果=无激活;
返回true;
}
}
#否则
#错误:需要特定于平台的代码来抑制单击激活
#恩迪夫
返回false;
}
这将阻止点击激活窗口(
MA_NOACTIVATE
),阻止Qt进一步处理它(
return true
),同时将其他所有事件(包括点击,因为我们没有使用
MA_noactivateat
来阻止它)正常处理为QEvents和Qt信号(
在末尾返回false

如果您需要进一步的低级访问(尽管我认为您不会),请参阅和

非常感谢您的回答

我的建议:查看KDE Plasma中的虚拟键盘代码:

看起来键是setWindowFlags(Qt::X11ByPassWindowManagerInt)和setFocusPolicy(Qt::NoFocus)


我想我找到了更好的方法! 只需使用
this->setAttribute(Qt::WA_x11donotaceptfocus);

例如:

MyVirtualKeyboard::MyVirtualKeyboard(QWidget *parent) :
    QDockWidget(parent),
    ui(new Ui::MyVirtualKeyboard)
{
    ui->setupUi(this);
    this->setAttribute(Qt::WA_X11DoNotAcceptFocus);
}

我有点像这样的问题:如何防止点击浮动窗口(QFrame)中的按钮来从主应用程序窗口转移焦点?目前我只需将焦点返回主窗口,
mainwindow.activateWidow()
。但肯定会产生令人不快的标题栏闪烁效果。这能解决吗?我相信过滤WM\u MOUSEACTIVATE/MA\u NOACTIVATE的技术也能解决这一问题。我已经
MyVirtualKeyboard::MyVirtualKeyboard(QWidget *parent) :
    QDockWidget(parent),
    ui(new Ui::MyVirtualKeyboard)
{
    ui->setupUi(this);
    this->setAttribute(Qt::WA_X11DoNotAcceptFocus);
}