Search code examples
qmlscrollviewscrollbarstyling

Styling QtQuick2 ScrollView results in visible artifacts


I have asked this question already directly on the Qt forum, but no reactions till now, hopefully I have more luck here.

We are currently updating from Qt5.12.12 to Qt5.15.8 and have to update our ScrollView component to match our design.

The problem is, that we now see artifacts that look like an ScrollBar without styling when hovering the ScrollBar. You can see an artifact in the left corner of the horizontal ScrollBar when hovering over the vertical one and vice versa. When timed correctly both artifacts are visible at the same time.

The problem only occurs when the styled ScrollView itself is used as an component. Either in an extra file or as inline component. I attached a minimal broken example in the code below. The left most ScrollView shows the artifacts.

I'm thankful to everyone who can confirm this problem and even more if you have an suggestion on how to fix it. Thank you.

Example:

Example output with artifacts

import QtQuick 2.15
import QtQml 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15

Window {
  id: window
  width: 750
  height: 300
  
  readonly property int scrollBarWidth: 15
  
  //////////////////////////////
  
  component MyStyledScrollBar: ScrollBar {
    id: myScrollBarRoot
    //parent: myScrollViewRoot

    opacity: 0.4

    x: myScrollBarRoot.horizontal
      ? parent.leftPadding
      : parent.width - width
    y: myScrollBarRoot.horizontal
      ? parent.height - height
      : parent.topPadding

    width: myScrollBarRoot.horizontal
     ? parent.availableWidth
     : window.scrollBarWidth
    height: myScrollBarRoot.horizontal
     ? window.scrollBarWidth
     : parent.availableHeight

    contentItem: Rectangle {
      color: "green"
    } //Rectangle
  } //component StyledScrollBar: ScrollBar

  component MyScrollView: ScrollView {
    id: myScrollViewRoot

    clip: true

    rightPadding: window.scrollBarWidth
    rightInset: window.scrollBarWidth
    bottomPadding: window.scrollBarWidth
    bottomInset: window.scrollBarWidth

    ScrollBar.vertical: MyStyledScrollBar {
      parent: myScrollViewRoot
      policy: ScrollBar.AlwaysOn
      active: myScrollViewRoot.ScrollBar.horizontal.active
    } //ScrollBar.vertical: MyStyledScrollBar

    ScrollBar.horizontal: MyStyledScrollBar {
      parent: myScrollViewRoot
      policy: ScrollBar.AlwaysOn
      active: myScrollViewRoot.ScrollBar.vertical.active
    } //ScrollBar.vertical: MyStyledScrollBar
  } //component MyScrollView: ScrollView
  
  //////////////////////////////
  
  GridLayout {
    flow: GridLayout.TopToBottom
    rows: 2
    columnSpacing: 15
    rowSpacing: 5

    //////////////////////////////

    Text {
      text: "Inline Component"
    } //Text
  
    MyScrollView {
      Layout.preferredWidth: 200
      Layout.preferredHeight: 200
  
      Label {
        text: "ABC"
        font.pixelSize: 224
      } //Label
    } //MyScrollView
  
    //////////////////////////////
  
    Text {
      text: "Direct Styling"
    } //Text
  
    ScrollView {
      id: scrollViewRoot
      Layout.preferredWidth: 200
      Layout.preferredHeight: 200

      Label {
        text: "ABC"
        font.pixelSize: 224
      } //Label

      clip: true

      rightPadding: window.scrollBarWidth
      rightInset: window.scrollBarWidth
      bottomPadding: window.scrollBarWidth
      bottomInset: window.scrollBarWidth

      ScrollBar.vertical: MyStyledScrollBar {
        policy: ScrollBar.AlwaysOn
        active: scrollViewRoot.ScrollBar.horizontal.active
      } //ScrollBar.vertical: MyStyledScrollBar

      ScrollBar.horizontal: MyStyledScrollBar {
        policy: ScrollBar.AlwaysOn
        active: scrollViewRoot.ScrollBar.vertical.active
      } //ScrollBar.vertical: MyStyledScrollBar
    } //ScrollView
  
    //////////////////////////////
  
    Text {
      text: "ScrollView default"
    } //Text
  
    ScrollView {
      ScrollBar.horizontal.policy: ScrollBar.AlwaysOn
      ScrollBar.vertical.policy: ScrollBar.AlwaysOn
  
      clip: true
  
      Layout.preferredWidth: 200
      Layout.preferredHeight: 200
  
      Label {
        text: "ABC"
        font.pixelSize: 224
      } //Label
    } //MyScrollView
  } //GridLayout
} //Window

ps: In Qt6 the ScrollView looks a lot different to Qt5.15 more like it was in QtQuick1, with increase/decrease buttons which we need to add manually with Qt5.15 ... . But we can not yet make the jump Qt6


Solution

  • Use QtQuick templates namely T.ScrollView. This will ensure there is no visual part left from the QtQuick.Controls implementation of ScrollView.

    import QtQuick.Templates 2.15 as T
    ...
    component MyScrollView: T.ScrollView {
        ...
    }