Подкласс QLabel, чтобы показать собственный индикатор Mouse Hover Button - PullRequest
3 голосов
/ 22 января 2012

У меня есть QLabel с рамкой 'StyledPanel, поднятая'.
Это кликабельно, если создать подкласс QLabel;

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

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

Однако, общее мнение состоит в том, что этот "ящик" не так простопризнан интерактивным.
В целях удобства использования я хотел бы, чтобы в поле "Box" было показано, что на него можно нажимать, когда над ним наведена мышь.
Очевидно, что реакция на зависание мыши легко достигается путем подключенияmouseHoverEvent.

Однако «индикатор кнопки» должен быть унаследован, поскольку мое приложение Qt позволяет пользователю изменять стиль (из Windows XP, Windows 7, plastique, motif, cde).

Это изображение показывает конкретный виджет (нижний правый угол) и желаемую эстетику mouseHover, которую я желаю, в двух разных стилях.

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

Когда мышь наведена на «Box»,Я бы хотел, чтобы он отвечал так, как у выпадающего списка вверху, по центру.
(«Отклик» эстетичен и встречается со всеми кнопками Qt, кроме стилей «CDE» и «motif».).

Есть ли способ реализовать это с помощью PyQt4?
(Полагаю, что для неродных решений потребуется QGradient и проверка нативного стиля, но это противно.)

ОБНОВЛЕНИЕ:
Идея lol4t0 о QLabel над QPushButton.

Вот моя питоническая реализация с сигналами, работающими должным образом и всей соответствующей эстетикой кнопок.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)

Спасибо!


Характеристики:
- python 2.7.2
- Windows 7
- PyQt4

Ответы [ 2 ]

5 голосов
/ 22 января 2012

Основная идея

Вы можете добавить QLabel выше QPushButton (сделать QLabel дочерним по отношению к QPushButton) и отображать форматированный текст в метке, в то время как клики и украшения можно обрабатывать с помощью QPushButton

Эксперимент

Ну, я C++ программист, но в этом нет ничего сложного, надеюсь, вы понимаете код

  • Реализация основная идея :

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

    И это почти работает!Единственная глупая ошибка ( или мое глобальное недопонимание ) заключается в том, что когда вы нажимаете кнопку мышью, а затем отпускаете ее, она остается нажатой .

- Итак, похоже, нам нужно переопределить mouseReleaseEvent в нашем label, чтобы исправить всегда нажата проблема:

Я почти уверен, что есть немногоболее элегантное решение, но мне сейчас лень его найти, поэтому я сделал следующее:

    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 сказал, чтобы исправить эту проблему, мы должны добавить

    label->setTextInteractionFlags(Qt::NoTextInteraction);
    
1 голос
/ 02 июня 2012

@ 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 не может быть слишком маленьким, чтобы скрыть часть текста. Я думаю, что этот способ удобнее использовать ...

...