子类化 QLabel 以显示本机“鼠标悬停按钮指示器”

发布于 2024-12-28 13:27:48 字数 1570 浏览 2 评论 0原文

我有一个带有“StyledPanel,凸起”框架的 QLabel。
通过子类化 QLabel,它是可点击的;

class InteractiveLabel(QtGui.QLabel):
    def __init__(self, parent):  
        QtGui.QLabel.__init__(self, parent)

    def mouseReleaseEvent(self, event):  
        self.emit(QtCore.SIGNAL('clicked()'))

然而,普遍的观点是这个“框”不容易被识别为可点击。
为了提高可用性,我希望“框”显示当鼠标悬停在其上时可以单击它。
显然,通过连接 mouseHoverEvent 可以轻松实现对鼠标悬停的反应。

但是,“按钮指示器”必须是本机继承的,因为我的 Qt 应用程序允许用户更改样式(在 Windows XP、Windows 7、plastique、motif、cde 之外)。

该图像以两种不同的风格显示了我想要的特定小部件(右下角)和鼠标悬停美学。

显示“Box”以及 plastique 和 Win7 样式的悬停指示器的图像

当鼠标悬停在“Box”上时,我希望它能够像组合框在顶部、中间那样做出响应。
(“响应”在美学上是原生的,并且出现在所有 Qt 按钮中,除了“CDE”和“motif”样式。)。

有没有办法用 PyQt4 来实现这个?
(我认为非本机解决方案将涉及 QGradient 并检查本机样式,但这很糟糕。)

更新:
lol4t0 的 QLabel 和 QPushButton 的想法。

这是我的 Python 实现,信号正常工作,并且具有所有适当的按钮美观。 RichTextBox 是您要嵌入到程序中的小部件。

from PyQt4 import QtCore, QtGui

class RichTextButton(QtGui.QPushButton):
    def __init__(self, parent=None):  
        QtGui.QPushButton.__init__(self, parent)
        self.UnitText = QtGui.QLabel(self)
        self.UnitText.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
        self.UnitText.setAlignment(QtCore.Qt.AlignCenter)
        self.UnitText.setMouseTracking(False)
        self.setLayout(QtGui.QVBoxLayout())
        self.layout().setMargin(0)
        self.layout().addWidget(self.UnitText)

谢谢!


规格:
- 蟒蛇2.7.2
- Windows 7
-PyQt4

I have a QLabel with a 'StyledPanel, raised' frame.
It is clickable, by subclassing QLabel;

class InteractiveLabel(QtGui.QLabel):
    def __init__(self, parent):  
        QtGui.QLabel.__init__(self, parent)

    def mouseReleaseEvent(self, event):  
        self.emit(QtCore.SIGNAL('clicked()'))

However, a general opinion is that this 'Box' is not easily recognised as clickable.
In an effort toward usability, I'd like the 'Box' to show it is clickable when the mouse is hovered over it.
Obviously a reaction to a mouse hover is easily achieved by connecting the mouseHoverEvent.

However, the 'button indicator' must be natively inherited, since my Qt application allows the User to change the style (out of Windows XP, Windows 7, plastique, motif, cde).

This image shows the particular widget (bottom right corner) and the mouseHover aesthetics I desire in two different styles.

Image showing the 'Box' and the hover indicators of the plastique and Win7 styles

When a mouse is hovered over 'Box', I'd like it to respond like the combobox has in the top, middle.
(The 'response' is aesthetically native and occurs with all Qt buttons, except in 'CDE' and 'motif'styles.).

Is there a way to implement this with PyQt4?
(I suppose non-native solutions would involve QGradient and checking the native style, but that's yucky.)

UPDATE:
lol4t0's idea of a QLabel over a QPushButton.

Here's my pythonic implementation with signals working properly and all the appropriate button aesthetics.
The RichTextBox is the widget you would embed into the program.

from PyQt4 import QtCore, QtGui

class RichTextButton(QtGui.QPushButton):
    def __init__(self, parent=None):  
        QtGui.QPushButton.__init__(self, parent)
        self.UnitText = QtGui.QLabel(self)
        self.UnitText.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
        self.UnitText.setAlignment(QtCore.Qt.AlignCenter)
        self.UnitText.setMouseTracking(False)
        self.setLayout(QtGui.QVBoxLayout())
        self.layout().setMargin(0)
        self.layout().addWidget(self.UnitText)

Thanks!


Specs:
- python 2.7.2
- Windows 7
- PyQt4

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

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

发布评论

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

评论(2

美人迟暮 2025-01-04 13:27:48

主要思想

您可以在QPushButton上方添加QLabel(使QLabel成为QPushButton的子级)并在标签中显示富文本,而点击和装饰可以用QPushButton来处理

实验

好吧,我是一个C++程序员,但没有什么复杂的,我希望,你理解代码

  • 实现主要思想

    QLabel * label = new QLabel(pushButton);
    label->setText("sss");
    标签->setAlignment(Qt::AlignCenter);
    标签->setMouseTracking(false);
    pushButton->setLayout(new QVBoxLayout(pushButton));
    PushButton->layout()->setMargin(0);
    PushButton->layout()->addWidget(label);
    

    几乎有效!唯一的一个愚蠢的错误(或我的全局误解)是,当您用鼠标按下按钮然后释放它时,它保持按下状态

- 所以,看来我们需要在 label 中重新实现 mouseReleaseEvent 来修复总是按下问题:

很确定,有一个更优雅的解决方案,但我现在懒得找到它,所以,我做了以下操作:

    class TransperentLabel: public QLabel
    {
    public:
        TransperentLabel(QWidget* parent):QLabel(parent) {}
    protected:
        void mouseReleaseEvent(QMouseEvent *ev)
        {
            /*
            QApplication::sendEvent(parent(), ev); -- does not help :(
            */
            static_cast<QPushButton*>(parent())->setDown(false);
            static_cast<QPushButton*>(parent())->click(); //fixing click signal issues
        }
    };

  • 正如 @Roku 所说,要解决这个问题,我们必须添加

    label->setTextInteractionFlags(Qt::NoTextInteraction);
    

Main idea

You can add QLabelabove QPushButton (make QLabel child of QPushButton) and show rich text in label, while clicks and decorations can be processed with QPushButton

Experiment

Well, I am a C++ programmer, but there is nothing complicated, I hope, you understand the code

  • Implementing main idea:

    QLabel * label = new QLabel(pushButton);
    label->setText("<strong>sss</strong>");
    label->setAlignment(Qt::AlignCenter);
    label->setMouseTracking(false);
    pushButton->setLayout(new QVBoxLayout(pushButton));
    pushButton->layout()->setMargin(0);
    pushButton->layout()->addWidget(label);
    

    And this almost works! The only one silly bug (or my global misunderstanding) is that when you press button with mouse and then release it, it remains pressed.

- So, it seems we need to reimplement mouseReleaseEvent in our label to fix always pressed issue:

I'm pretty sure, there is a bit more elegant solution, but I'm too lazy to find it now, so, I made following:

    class TransperentLabel: public QLabel
    {
    public:
        TransperentLabel(QWidget* parent):QLabel(parent) {}
    protected:
        void mouseReleaseEvent(QMouseEvent *ev)
        {
            /*
            QApplication::sendEvent(parent(), ev); -- does not help :(
            */
            static_cast<QPushButton*>(parent())->setDown(false);
            static_cast<QPushButton*>(parent())->click(); //fixing click signal issues
        }
    };

  • As @Roku said, to fix that issue, we have to add

    label->setTextInteractionFlags(Qt::NoTextInteraction);
    
彻夜缠绵 2025-01-04 13:27:48

@Lol4t0,我对你的方法做了一些改进...

这是我的头文件:

#ifndef QLABELEDPUSHBUTTON_H
#define QLABELEDPUSHBUTTON_H

#include <QPushButton>

class QLabel;

class QLabeledPushButton : public QPushButton
{
    Q_OBJECT

    QLabel * m_label;

public:
    QLabeledPushButton(QWidget * parent = 0);

    QString text() const;
    void setText(const QString & text);

protected:
    void resizeEvent(QResizeEvent * event);
};

#endif // QLABELEDPUSHBUTTON_H

还有我的cpp文件:

#include <QLabel>
#include <QVBoxLayout>
#include <QResizeEvent>
#include "QLabeledPushButton.h"

QLabeledPushButton::QLabeledPushButton(QWidget * parent)
    : QPushButton(parent)
    , m_label(new QLabel(this))
{
    m_label->setWordWrap(true);
    m_label->setMouseTracking(false);
    m_label->setAlignment(Qt::AlignCenter);
    m_label->setTextInteractionFlags(Qt::NoTextInteraction);
    m_label->setGeometry(QRect(4, 4, width()-8, height()-8));
}

QString QLabeledPushButton::text() const
{
    return m_label->text();
}

void QLabeledPushButton::setText(const QString & text)
{
    m_label->setText(text);
}

void QLabeledPushButton::resizeEvent(QResizeEvent * event)
{
    if (width()-8 < m_label->sizeHint().width())
        setMinimumWidth(event->oldSize().width());
    if (height()-8 < m_label->sizeHint().height())
        setMinimumHeight(event->oldSize().height());

    m_label->setGeometry(QRect(4, 4, width()-8, height()-8));
}

所以QLabel上的文本始终可见。 QPushButton 不能太小而无法隐藏部分文本。我觉得这种方式用起来比较舒服...

@Lol4t0, i have some improvements for your method...

This is my header file:

#ifndef QLABELEDPUSHBUTTON_H
#define QLABELEDPUSHBUTTON_H

#include <QPushButton>

class QLabel;

class QLabeledPushButton : public QPushButton
{
    Q_OBJECT

    QLabel * m_label;

public:
    QLabeledPushButton(QWidget * parent = 0);

    QString text() const;
    void setText(const QString & text);

protected:
    void resizeEvent(QResizeEvent * event);
};

#endif // QLABELEDPUSHBUTTON_H

And there is my cpp file:

#include <QLabel>
#include <QVBoxLayout>
#include <QResizeEvent>
#include "QLabeledPushButton.h"

QLabeledPushButton::QLabeledPushButton(QWidget * parent)
    : QPushButton(parent)
    , m_label(new QLabel(this))
{
    m_label->setWordWrap(true);
    m_label->setMouseTracking(false);
    m_label->setAlignment(Qt::AlignCenter);
    m_label->setTextInteractionFlags(Qt::NoTextInteraction);
    m_label->setGeometry(QRect(4, 4, width()-8, height()-8));
}

QString QLabeledPushButton::text() const
{
    return m_label->text();
}

void QLabeledPushButton::setText(const QString & text)
{
    m_label->setText(text);
}

void QLabeledPushButton::resizeEvent(QResizeEvent * event)
{
    if (width()-8 < m_label->sizeHint().width())
        setMinimumWidth(event->oldSize().width());
    if (height()-8 < m_label->sizeHint().height())
        setMinimumHeight(event->oldSize().height());

    m_label->setGeometry(QRect(4, 4, width()-8, height()-8));
}

So text on QLabel is always visible. QPushButton can't be too small to hide part of text. I think this way is more comfortable to use...

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