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