如何在Qt中打破小部件的标签顺序链
How to break the tab order chain of widgets in Qt?
在Qt中,您可以使用Qt设计器或使用c++来定义制表符顺序。小部件之间的关系是相对设置的,所以没有索引之类的东西。我现在想要的是"打破"小部件的循环链,这样我就得到了链的开始和结束。
圆形制表符顺序为:
A - B
| |
D - C
我想(注意A和D之间缺少链接):
A - B
|
D - C
更像一条线而不是一个圆:
A - B - C - D
所以用户在一端"停止",必须从另一个方向返回。
更新:我现在有另一个想法。如果我重新实现:
bool QWidget::focusNextPrevChild(bool next)
根据文档,可以使用它来实现自定义焦点行为。
在我的动态场景中,GUI中的按钮在运行时进行调整,我将不得不重载函数并设置,例如,内部标志allowFocusNext和allowFocusPrev,然后在必要时忽略焦点请求。我试过之后会回来报告的。同时,欢迎任何评论!?: -)
我找到了一个解决方案,但它有点粗糙。QWidget::setTabOrder
不允许将小部件与自身链接,所以这种方法没有帮助(即使您使用焦点代理)
但是,你可以定义一个"焦点转发器":
class FocusForwarder : public QWidget
{
public:
explicit FocusForwarder(QWidget *proxy) :
QWidget((QWidget *) proxy->parent()),
m_proxy(proxy)
{
setFocusPolicy(Qt::TabFocus);
}
protected:
void focusInEvent(QFocusEvent *) {
m_proxy->setFocus();
}
private:
QWidget *m_proxy;
};
并将它们添加到链的开头和结尾:
FocusForwarder *w1 = new FocusForwarder(ui->bA);
FocusForwarder *w2 = new FocusForwarder(ui->bD);
QWidget::setTabOrder(w1, ui->bA);
QWidget::setTabOrder(ui->bA, ui->bB);
QWidget::setTabOrder(ui->bB, ui->bC);
QWidget::setTabOrder(ui->bC, ui->bD);
QWidget::setTabOrder(ui->bD, w2);
<标题> 详细信息要使setTabOrder
工作,小部件必须在同一个窗口中。为了确保这一点,转发器被放置在代理的父节点中(在初始化列表中)。
对于这种机制,焦点方向(Tab或Shit+Tab)无关紧要。focusforwarder一旦接收到焦点,就会将焦点"转发"给它的代理。方向是由Qt内部处理的。你只需在你的链条上添加"哨兵"。
在QtDesigner中使用
当您想在QtDesigner中使用它时,您将创建一个Widget并将其推广到转发器。由于不能直接设置代理,因此可以为代理的名称添加一个动态属性,如下所示:
class FocusForwarderDesigner : public QWidget
{
Q_OBJECT
Q_PROPERTY(QString proxyName READ proxyName WRITE setProxyName)
public:
QString proxyName() {
return (m_proxy) ? m_proxy->objectName() : QString::null;
}
void setProxyName(QString name) {
m_proxy = parent()->findChild<QWidget *>(name);
}
explicit FocusForwarderDesigner(QWidget *parent = NULL) :
QWidget(parent) {}
protected:
void focusInEvent(QFocusEvent *) {
if (m_proxy) m_proxy->setFocus();
}
private:
QWidget *m_proxy;
}
在设计器中,您将添加名称为proxyName
的字符串属性,并将其设置为代理的名称。不要忘记在设计器中将focus policy
设置为Tab Focus
。
经过一些额外的思考,我发布了一个回答我自己的问题,因为它是一个工作的解决方案,但它不是理想的。因此,我还在寻找一个更好的!值得一提的是,我的应用程序主要依靠鼠标滚轮交互来改变小部件的焦点。
在我的问题中我提到了重写:
bool focusNextPrevChild(bool next)
可能导致一个工作系统。如果焦点被标记为"最后一项"或"第一项","接收"小部件将通过返回"true"来忽略焦点,而"next"参数将导致循环行为。虽然这适用于tab和空格+tab键组合,但在某些情况下,focusNextPrevChild没有被显式调用。在我的例子中,它不调用与鼠标滚轮事件相关的焦点更改。
我所做的是重写:
void wheelEvent(QWheelEvent* event)
这使我能够直接控制与鼠标滚轮相关的所有焦点事件。我的重写函数看起来像这样:
void SelectionIconButton::wheelEvent(QWheelEvent* event)
{
bool next = event->delta() > 0;
if (m_IsLastInFocusChain && next) {
event->accept();
return;
}
if (m_IsFirstInFocusChain && !next) {
event->accept();
return;
}
QPushButton::wheelEvent(event);
}
所以这个系统的要求是:
- 每个小部件必须以某种方式实现两个bool并处理它们状态。
- 这些小部件必须在启动时配置或者在应用程序使用 期间的动态屏幕中
- 只听wheelEvent不允许我处理tab键和空格+tab键
您可以看到此解决方案是有效的,但是要将其应用到大型应用程序中需要付出一些努力。我在想一个更一般的解决方案。也许是一个全局列表,当屏幕发生变化时更新。然后,这个全局列表将以某种方式决定是否允许焦点更改。不幸的是,这对于鼠标滚轮事件来说也是有问题的,因为一些小部件是"活动的",而滚轮事件甚至不想改变焦点,而是改变输入字段中的值,例如,
编辑:我可能不得不补充说,QWidget::wheelEvent()
和QPushButton::wheelEvent()
以及更多Qt-Widgets的默认实现只是通过设置event->ignore()
来忽略事件。在我的应用程序中,所有被忽略的事件都被一个高级小部件捕获,然后该小部件解释QWheelEvent
并使用其增量来调用focusPreNextChild()
适当的时间。
- CMake-按正确顺序将项目与C运行时对象文件链接
- 函数调用中参数的顺序重要吗
- 为什么不;名字在地图上是按顺序排列的吗
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 数到第n个楼梯的路(顺序无关紧要)
- 优先顺序:智能指针和类析构函数
- 在循环中按顺序遍历成员变量
- 独立读取-修改-写入顺序
- QML按钮点击功能执行顺序
- C++中数据类型修饰符的顺序
- 当比特(而不是字节)的顺序至关重要时的持久性
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 通过选项卡的文本设置QTabWidget顺序
- c++11评估顺序(未定义的行为)
- 如何在C++中递归地按相反顺序打印集合
- 给定顺序中的事件处理
- 具有包含其他对象的类的对象创建顺序
- vim 标签导航,使用 VIM 或 CTAG 更改排序顺序
- 并非按顺序(MC_OUT_OF_ORDER_TAG)发行并发标签
- 如何在Qt中打破小部件的标签顺序链