Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.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中打破小部件的标签顺序链? 在QT中,可以使用Qt设计器或使用C++定义选项卡顺序。小部件之间的关系是相对设置的,因此没有索引之类的东西。我现在想要的是“打破”小部件的循环链,以便获得链的起点和终点_C++_Qt - Fatal编程技术网

如何在Qt中打破小部件的标签顺序链? 在QT中,可以使用Qt设计器或使用C++定义选项卡顺序。小部件之间的关系是相对设置的,因此没有索引之类的东西。我现在想要的是“打破”小部件的循环链,以便获得链的起点和终点

如何在Qt中打破小部件的标签顺序链? 在QT中,可以使用Qt设计器或使用C++定义选项卡顺序。小部件之间的关系是相对设置的,因此没有索引之类的东西。我现在想要的是“打破”小部件的循环链,以便获得链的起点和终点,c++,qt,C++,Qt,循环选项卡顺序为: A - B | | D - C 我想要(注意A和D之间缺少链接): 这更像是一条线而不是一个圆: A - B - C - D 因此,用户在一端“停止”,必须使用另一个方向返回 更新:我现在有另一个想法。如果我重新实现: bool QWidget::focusNextPrevChild(bool next) 根据这个例子,可以使用它来实现定制的焦点行为 在我的动态场景中,GUI中的按钮在运行时被调整,我将不得不重载函数并设置一个内部标志allowFocusNext

循环选项卡顺序为:

A - B 
|   |
D - C
我想要(注意A和D之间缺少链接):

这更像是一条线而不是一个圆:

A - B - C - D
因此,用户在一端“停止”,必须使用另一个方向返回


更新:我现在有另一个想法。如果我重新实现:

bool QWidget::focusNextPrevChild(bool next)
根据这个例子,可以使用它来实现定制的焦点行为


在我的动态场景中,GUI中的按钮在运行时被调整,我将不得不重载函数并设置一个内部标志allowFocusNext和allowFocusPrev,如有必要,它将忽略焦点请求。当我试过之后,我会在这里汇报。同时,欢迎发表任何意见!?:-)

我找到了一个解决方案,但它有点粗糙。
QWidget::setTabOrder
将不允许将小部件与自身链接,因此这种方法不会有帮助(即使您使用的是焦点代理)

但是,您可以定义“焦点转发器”:

并将它们添加到链的开头和结尾:

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)并不重要。一旦FocusFowarder接收到焦点,它将“转发”到其代理。 方向由Qt内部处理。你只要在你的链条上加上“哨兵”

在QtDesigner中使用 当您想在QtDesigner中使用它时,您需要创建一个小部件并将其升级到转发器。由于无法直接设置代理,因此可以为代理名称添加动态属性,如下所示:

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;
}
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);
}
class FocusForwarderDesigner:公共QWidget
{
Q_对象
Q_属性(QString proxyName READ proxyName WRITE setProxyName)
公众:
QString proxyName(){
返回(m_proxy)→m_proxy->objectName():QString::null;
}
void setProxyName(QString名称){
m_proxy=parent()->findChild(名称);
}
显式FocusForwarderDesigner(QWidget*parent=NULL):
QWidget(父项){}
受保护的:
无效聚焦事件(QFocusEvent*){
if(m_proxy)m_proxy->setFocus();
}
私人:
QWidget*m_代理;
}

在设计器中,您将添加一个名为
proxyName
的字符串属性,并将其设置为代理的名称。别忘了在designer中将
焦点策略
设置为
选项卡焦点

经过一些思考后,我发布了我自己问题的答案,因为这是一个可行的解决方案,但并不理想。所以,我还在寻找更好的!值得注意的是,我的应用程序主要依靠鼠标滚轮交互来改变小部件的焦点

在我的问题中,我提到:

bool focusNextPrevChild(bool next)
void wheelEvent(QWheelEvent* event)
可能导致一个工作系统。如果“receiving”小部件被标记为“last item”或“first item”,那么“receiving”小部件将通过返回“true”忽略焦点,“next”参数将导致循环行为。尽管这适用于tab和space+tab键组合,但在某些情况下,focusNextPrevChild不会被显式调用。在我的例子中,不需要与鼠标滚轮事件相关的焦点更改

相反,我所做的是覆盖:

bool focusNextPrevChild(bool next)
void wheelEvent(QWheelEvent* event)
这使我可以直接控制与鼠标滚轮相关的所有焦点事件。我的重写函数如下所示:

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;
}
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::wheeleevent()
QPushButton::wheeleevent()
以及更多Qt小部件的默认实现只是通过设置
event->ignore()
来忽略事件。
在我的应用程序中,所有这些被忽略的事件都被捕获在一个高级小部件中,该小部件随后解释
QWheelEvent
,并使用其增量调用
FocusRenextChild()

您是否尝试过
QWidget::setTabOrder(D,D)
?补充:@king_nak:这似乎是个好主意。我报告它最终是否有效:-)我已经尝试过你的方法,它适用于只创建一次小部件的静态情况。在使用hide()和show()更改UI外观的动态情况下,FocusForwarder仅在其目标可见时才工作。我猜当小部件被隐藏时,Qt会在内部改变焦点链。因此,当最后一个小部件(指向最终焦点转发器)被隐藏时,Qt会按照自己的意愿将“下一个焦点”重定向到第一个小部件,因此它再次是循环的。我认为必须有一种方法将循环行为改变为线性行为:-(