【问题标题】:How to create scrollbar in QtQuick 2.0?如何在 QtQuick 2.0 中创建滚动条?
【发布时间】:2013-07-23 21:00:33
【问题描述】:

我正在尝试在 QtQuick 2.0 中创建滚动条,

我发现Scrollbar 组件在 QtQuick 1.0 中可用,但我在 QtQuick 2.0 中找不到这样的组件。如何在 QtQuick 2.0 中为ListView 创建滚动条?

有什么帮助吗?提前致谢。

【问题讨论】:

    标签: qt qml qtquick2


    【解决方案1】:

    喜欢 TheBootro 的解决方案(为他 +1!),但仅在几天前通过对最近一个问题的评论找到了他的解决方案。 同时,我已经为我正在从事的项目独立开发了我的解决方案,我将在这里分享这样的解决方案。希望它能有用。 :)

    我的滚动条有(某种)“OS X 感觉”(有意),例如它不包括侧面的滚动箭头。

    代码如下:

    import QtQuick 2.0
    
    Item {
       id: scrollbar
    
        property Flickable flk : undefined
        property int basicWidth: 10
        property int expandedWidth: 20
        property alias color : scrl.color
        property alias radius : scrl.radius
    
        width: basicWidth
        anchors.right: flk.right;
        anchors.top: flk.top
        anchors.bottom: flk.bottom
    
        clip: true
        visible: flk.visible
        z:1
    
        Binding {
            target: scrollbar
            property: "width"
            value: expandedWidth
            when: ma.drag.active || ma.containsMouse
        }
        Behavior on width {NumberAnimation {duration: 150}}
    
        Rectangle {
            id: scrl
            clip: true
            anchors.left: parent.left
            anchors.right: parent.right
            height: flk.visibleArea.heightRatio * flk.height
            visible: flk.visibleArea.heightRatio < 1.0
            radius: 10
            color: "gray"
    
            opacity: ma.pressed ? 1 : ma.containsMouse ? 0.65 : 0.4
            Behavior on opacity {NumberAnimation{duration: 150}}
    
            Binding {
                target: scrl
                property: "y"
                value: !isNaN(flk.visibleArea.heightRatio) ? (ma.drag.maximumY * flk.contentY) / (flk.contentHeight * (1 - flk.visibleArea.heightRatio)) : 0
                when: !ma.drag.active
            }
    
            Binding {
                target: flk
                property: "contentY"
                value: ((flk.contentHeight * (1 - flk.visibleArea.heightRatio)) * scrl.y) / ma.drag.maximumY
                when: ma.drag.active && flk !== undefined
            }
    
            MouseArea {
                id: ma
                anchors.fill: parent
                hoverEnabled: true
                drag.target: parent
                drag.axis: Drag.YAxis
                drag.minimumY: 0
                drag.maximumY: flk.height - scrl.height
                preventStealing: true
            }
        }
    }
    

    这是使用它的代码。显然,所有字段都是可选的。设置的值是默认值:

    ScrollBar {
        flk: privacyFlick
        radius: 10          // Optional
        basicWidth: 10      // Optional
        expandedWidth: 20   // Optional
        color: "grey"       // Optional
    }
    

    【讨论】:

    • +1 - 非常感谢您发布您的解决方案!很长时间以来,我一直在寻找一个简单的、始终可见的没有背景的滚动条。有一些(所谓的)解决方案,但这是第一个有效的解决方案,即使是开箱即用。最重要的是,它很容易适应我自己的需要。干得好
    • 此滚动条中不考虑页脚和页眉
    • 你是说箭头@MahdiKhalili?我猜这是关于 OSX 感觉的描述中有意和暗示的。
    • 它使用锚来定位它在列表视图中由于页脚和页眉而无法正常工作,我用这个docs.huihoo.com/qt/5.x/…解决了它
    • 哦,我现在明白了。好吧,老实说,不记得细节。但如果你自己修好了。
    【解决方案2】:

    Qt 5.6 引入了新控件作为技术预览“Qt Labs Controls”。除其他外,控件引入了内置的ScrollBar 类型(交互式)和ScrollIndicator 类型(非交互式)。

    在 Qt 5.7 中,新控件退出了技术预览,现在重命名为“Quick Controls 2”,以强调它们取代了以前的控件。

    如果您使用的是 Qt 5.6,它是一个 LTS 版本并且将存在相当长的一段时间,ScrollBar 可以按如下方式使用:

    import QtQuick 2.6
    import Qt.labs.controls 1.0
    import QtQuick.Window 2.2
    
    ApplicationWindow {
        visible: true
        width: 400
        height: 600
    
        Flickable {
            anchors.fill: parent
            contentWidth: image.width
            contentHeight: image.height
    
            //ScrollIndicator.vertical: ScrollIndicator { }  // uncomment to test
            ScrollBar.vertical: ScrollBar { }
            ScrollBar.horizontal: ScrollBar { }
    
            Image {
                id: image
                source: "http://i.ytimg.com/vi/tntOCGkgt98/maxresdefault.jpg"
            }
        }
    }
    

    而在 Qt 5.7 及更高版本中,您可以使用 ScrollBarScrollIndicator,如下所示:

    import QtQuick 2.6
    import QtQuick.Controls 2.0
    import QtQuick.Window 2.2
    
    ApplicationWindow {
        visible: true
        width: 600
        height: 300
    
        Flickable {
            anchors.fill: parent
            contentWidth: image.width
            contentHeight: image.height
    
            ScrollIndicator.vertical: ScrollIndicator { }
            //ScrollBar.vertical: ScrollBar { }       // uncomment to test    
    
            Image {
                id: image
                source: "http://s-media-cache-ak0.pinimg.com/736x/92/9d/3d/929d3d9f76f406b5ac6020323d2d32dc.jpg"
            }
        }
    }
    

    用法语法几乎相同,而在样式代码中发生了重大重构,例如Labs Controls ScrollIndicator customization page 与 Quick Controls 2 ScrollIndicator customization page 的对比。

    【讨论】:

      【解决方案3】:

      我认为这可以解决问题

      http://qt-project.org/doc/qt-5.1/qtquickcontrols/qml-qtquick-controls1-scrollview.html

      import QtQuick 2.0
      import QtQuick.Controls 1.0
      ScrollView{
          ListView {
              ...
          }
      }
      

      【讨论】:

      【解决方案4】:

      ScrollBar/ScrollIndicator 简单易做,QQ1 或 QQ2 代码相同(导入除外):

      ///////// ScrollBar.qml /////////////

      import QtQuick 2.0;
      
      Item {
          id: scrollbar;
          width: (handleSize + 2 * (backScrollbar.border.width +1));
          visible: (flickable.visibleArea.heightRatio < 1.0);
          anchors {
              top: flickable.top;
              right: flickable.right;
              bottom: flickable.bottom;
              margins: 1;
          }
      
          property Flickable flickable               : null;
          property int       handleSize              : 20;
      
          function scrollDown () {
              flickable.contentY = Math.min (flickable.contentY + (flickable.height / 4), flickable.contentHeight - flickable.height);
          }
          function scrollUp () {
              flickable.contentY = Math.max (flickable.contentY - (flickable.height / 4), 0);
          }
      
         Binding {
              target: handle;
              property: "y";
              value: (flickable.contentY * clicker.drag.maximumY / (flickable.contentHeight - flickable.height));
              when: (!clicker.drag.active);
          }
          Binding {
              target: flickable;
              property: "contentY";
              value: (handle.y * (flickable.contentHeight - flickable.height) / clicker.drag.maximumY);
              when: (clicker.drag.active || clicker.pressed);
          }
          Rectangle {
              id: backScrollbar;
              radius: 2;
              antialiasing: true;
              color: Qt.rgba(0.5, 0.5, 0.5, 0.85);
              border {
                  width: 1;
                  color: "darkgray";
              }
              anchors { fill: parent; }
      
              MouseArea {
                  anchors.fill: parent;
                  onClicked: { }
              }
          }
          MouseArea {
              id: btnUp;
              height: width;
              anchors {
                  top: parent.top;
                  left: parent.left;
                  right: parent.right;
                  margins: (backScrollbar.border.width +1);
              }
              onClicked: { scrollUp (); }
      
              Text {
                  text: "V";
                  color: (btnUp.pressed ? "blue" : "black");
                  rotation: -180;
                  anchors.centerIn: parent;
              }
          }
          MouseArea {
              id: btnDown;
              height: width;
              anchors {
                  left: parent.left;
                  right: parent.right;
                  bottom: parent.bottom;
                  margins: (backScrollbar.border.width +1);
              }
              onClicked: { scrollDown (); }
      
              Text {
                  text: "V";
                  color: (btnDown.pressed ? "blue" : "black");
                  anchors.centerIn: parent;
              }
          }
          Item {
              id: groove;
              clip: true;
              anchors {
                  fill: parent;
                  topMargin: (backScrollbar.border.width +1 + btnUp.height +1);
                  leftMargin: (backScrollbar.border.width +1);
                  rightMargin: (backScrollbar.border.width +1);
                  bottomMargin: (backScrollbar.border.width +1 + btnDown.height +1);
              }
      
              MouseArea {
                  id: clicker;
                  drag {
                      target: handle;
                      minimumY: 0;
                      maximumY: (groove.height - handle.height);
                      axis: Drag.YAxis;
                  }
                  anchors { fill: parent; }
                  onClicked: { flickable.contentY = (mouse.y / groove.height * (flickable.contentHeight - flickable.height)); }
              }
              Item {
                  id: handle;
                  height: Math.max (20, (flickable.visibleArea.heightRatio * groove.height));
                  anchors {
                      left: parent.left;
                      right: parent.right;
                  }
      
                  Rectangle {
                      id: backHandle;
                      color: (clicker.pressed ? "blue" : "black");
                      opacity: (flickable.moving ? 0.65 : 0.35);
                      anchors { fill: parent; }
      
                      Behavior on opacity { NumberAnimation { duration: 150; } }
                  }
              }
          }
      }
      

      使用它:

      import QtQuick 2.0;
      
      Rectangle {
          width: 400;
          height: 300;
      
          ListView {
              id: list;
              anchors.fill: parent;
              model: 100;
              delegate: Rectangle {
                  height: 50;
                  width: parent.width;
                  color: (model.index %2 === 0 ? "darkgray" : "lightgray");
              }
          }
          ScrollBar {
              flickable: list;
          }
      }
      

      享受吧!

      【讨论】:

      • 非常感谢!非常灵活和高效的解决方案。它唯一缺少的是水平方向。由于 ListView 支持它,我将添加一个属性绑定以水平滚动
      • 如果我们对委托数量进行交互式更改,则检测到绑定循环:Binding { target: flickable; property: "contentY"; value: (handle.y * (flickable.contentHeight - flickable.height) / clicker.drag.maximumY); when: (clicker.drag.active || clicker.pressed); } 然后整个滚动被破坏。我们可以滚动父亲然后 contentHeight。你能帮忙吗?
      • 它可以工作,但是每当我拖动句柄时,都会向日志中发送垃圾邮件“QML 绑定:检测到属性“值”的绑定循环”。有什么解决办法吗?
      • 非常有用,谢谢。但我得到了相同的绑定循环警告。
      • 很好的解决方案,但是我注意到当元素被动态插入到列表中时滚动条的位置会出错(在我的例子中是在顶部)。
      猜你喜欢
      • 1970-01-01
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      相关资源
      最近更新 更多