【问题标题】:How to customize QListWidget with different highlight bar and spacing如何使用不同的高亮条和间距自定义 QListWidget
【发布时间】:2025-11-25 18:40:01
【问题描述】:

我正在开发一个应用程序,该应用程序需要在屏幕左侧有一个包含多个项目(文本)的菜单。我想要显示的唯一项目是实际文本和突出显示栏。我还想修改突出显示栏,以便: 一种。我可以为它制作动画,并将其从一个选择滑到下一个 湾。我可以使用带有圆角的自定义像素图而不是默认的突出显示颜色

我尝试过使用 QListWidget 和样式表并取得了一些成功,但我不相信使用这种方法可以使我的高亮栏的角落变圆。我也不确定我是否可以为栏从一个项目移动到下一个项目设置动画:

preset_list_view->setStyleSheet("QListView {color: rgb(230, 230, 230); background-color: rgba(0,0,0,0); border-style: none} QListView::item:selected {background-image: url(:/ui_resources/elements-preset_select/highlight_bar_270x30-black_bg.bmp)}");

我在网上查遍了,但没有找到太多。有人提到修改 QListWidget 的委托,但描述含糊不清。我也不确定这是否能解决我的动画问题。

有什么想法吗?

【问题讨论】:

  • QML 示例(QtSDK/Examples/4.7/declarative/modelviews/listview/highlightranges/qml/highlightranges.qml,您使用qmlviewer 运行)中的内容接近您想要的内容。基本上它是一个带有动画透明选择指示器的列表,可以平滑移动。

标签: qt qlistwidget


【解决方案1】:

您可以在 QListWidget 顶部放置一个半透明的惰性小部件,并在选择更改时对其进行动画处理。 但是您还需要一个委托来禁用正常选择指示器。

一个工作示例:

#include <QListWidget>
#include <QFrame>
#include <QPropertyAnimation>
#include <QStyledItemDelegate>

class RemoveSelectionDelegate : public QStyledItemDelegate {
public:
    RemoveSelectionDelegate(QObject *parent = 0)
        : QStyledItemDelegate(parent) {
    }

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const {
        // Call the original paint method with the selection state cleared
        // to prevent painting the original selection background
        QStyleOptionViewItemV4 optionV4 =
            *qstyleoption_cast<const QStyleOptionViewItemV4 *>(&option);
        optionV4.state &= ~QStyle::State_Selected;
        QStyledItemDelegate::paint(painter, optionV4, index);
    }
};

class ListWidget : public QListWidget {
    Q_OBJECT
public:
    ListWidget(QWidget *parent = 0)
        : QListWidget(parent)
        , selectionFrame(this)
        , animation(&selectionFrame, "geometry") {
        // Create a semi-transparent frame that doesn't interact with anything
        selectionFrame.setAttribute(Qt::WA_TransparentForMouseEvents);
        selectionFrame.setFocusPolicy(Qt::NoFocus);

        // You can put your transparent image in that stylesheet
        selectionFrame.setStyleSheet("background: solid rgba(0, 0, 125, 25%);");
        selectionFrame.hide();
        animation.setDuration(250);
        animation.setEasingCurve(QEasingCurve::InOutBack);

        connect(this,
                SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
                SLOT(updateSelection(QListWidgetItem*)) );        
        setItemDelegate(new RemoveSelectionDelegate(this));
    }

private slots:
    void resizeEvent(QResizeEvent *e) {
        QListWidget::resizeEvent(e);
        updateSelection(currentItem());
    }

    void updateSelection(QListWidgetItem* current) {
        animation.stop();
        if (!current) {
            selectionFrame.hide();
            return;
        }
        if (!selectionFrame.isVisible()) {
            selectionFrame.setGeometry(visualItemRect(current));
            selectionFrame.show();
            return;
        }
        animation.setStartValue(selectionFrame.geometry());
        animation.setEndValue(visualItemRect(current));
        animation.start();
    }
private:
    QFrame selectionFrame;
    QPropertyAnimation animation;
};

【讨论】:

  • 感谢 alexisdm,我会试一试(在我花了几分钟试图绕开它之后!)。我有点失望,Qt 没有以更简单的方式提供这个功能,尽管我有什么资格抱怨完全免费的软件?
【解决方案2】:

因此,如果它只是文本,那么为什么不使用带有 QLabels 的 QDockwidget。

例如,看一下左侧的'Qt Designer's 'Widget Box',您可以将其拖放到顶部。这就是你要找的吗?

您可以随意移动码头小部件。

【讨论】:

  • 这不是一个糟糕的主意,尽管我应该提到我需要能够轻松地从列表中添加/删除项目,并且它需要是可滚动的,以及在项目被选中。当我收到信号(来自硬件按钮)时,我还需要能够在菜单中选择下一个或上一个项目。 QListWidget 很好地包含了所有这些功能,因此根据我的需要对其进行修改似乎是最简单的。
  • 您有示例或图片说明您正在努力实现的目标吗?
  • 嗨,blueskin,我认为我无法提供我正在做的事情的实际图像,因为它是为客户服务的(尽管我相信它将来会开源)。想象一个 QListBox,其中唯一可见的是列表中的项目,选择栏是自定义位图,选择栏从一个项目滑到下一个项目。如果项目的数量超过屏幕的大小,列表将随着所选项目的变化而滚动。
  • 我的意思是 QListWidget,而不是 QListBox。
  • 好的,那么基本上你不能创建一个小部件,它可以动画并做你想要的所有东西,并使用 setItemWidget 将它放在列表小部件中。 doc.qt.nokia.com/latest/qlistwidget.html#setItemWidget
最近更新 更多