如何自定义具有不同高亮条和间距的QListWidget

发布于 2024-12-02 16:13:51 字数 597 浏览 2 评论 0原文

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

我尝试使用 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 的委托,但描述很模糊。我也不确定这是否能解决我的动画问题。

有什么想法吗?

I'm working on an application that needs to have a menu on the left side of the screen containing multiple items (text). The only items I want to be visible are the actual text and the highlight bar. I would also like to modify the highlight bar so that:
a. I can animate it, and slide it from one selection to the next
b. I can use a custom pixmap with rounded corners instead of the default highlight color

I've tried using a QListWidget and stylesheets and had some success, but I don't believe it's possible to round the corners of my highlight bar using this method. I'm also not sure I can animate the movement of the bar from one item to the next:

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)}");

I've looked all over online and not found much. There is some mention of modifying the delegate of the QListWidget, but the descriptions have been vague. I'm also not sure if this would solve my animation problem.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蘑菇王子 2024-12-09 16:13:51

您可以在 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;
};

You can place a semi transparent inert widget on top of the QListWidget, and animate it when the selection changes.
But you also need a delegate to disable the normal selection indicator.

A working example:

#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;
};
他夏了夏天 2024-12-09 16:13:51

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

例如,看一下左侧的“Qt Designer 的“小部件框””,您可以将其拖动并将其放在顶部。这就是您要找的吗?

您可以根据需要移动停靠小部件。

So if its just text then why not have a QDockwidget with QLabels.

For example, take a look at the 'Qt Designer's 'Widget Box' on the left, you can drag that and place it on the top. Is that what you are looking for?

You can move the dockwidget as you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文