Куриное поведение в qt

Я работаю в kubuntu 20.04 с создателем qt. Я кодирую простой список виджетов, расположенных в QVBoxLayout который состоит из 3, a QLabel, нестандартный парик и еще один финал QPushButton. Основной класс ButtonList, настраиваемый виджет IteratingWidget который содержит два DirectionButtonс в QHBoxLayout

DirectionButton.h

      #pragma once

#include <utility>
#include <QPoint>
#include <QWidget>
#include <QPushButton>
#include <QStyleOption>
#include <QPainter>
#include <QScreen>
#include <QGuiApplication>

//--------------------------------------------------------------------------

struct RightArrow {
    static constexpr unsigned int b = 0;
    static constexpr unsigned int c = 1;
    static constexpr unsigned int d = 2;
    static constexpr unsigned int f = 3;
    static constexpr unsigned int g = 4;
    static constexpr unsigned int h = 5;
    static constexpr unsigned int i = 6;
    static constexpr unsigned int j = 7;
    static std::function<void(QWidget*, int*)> setCoordinates;
    static std::function<void(int*, QPoint*)> setVector;
};

//--------------------------------------------------------------------------

struct LeftArrow {
    static constexpr unsigned int b = 0;
    static constexpr unsigned int c = 1;
    static constexpr unsigned int d = 2;
    static constexpr unsigned int f = 3;
    static constexpr unsigned int g = 4;
    static constexpr unsigned int h = 5;
    static constexpr unsigned int i = 6;
    static constexpr unsigned int j = 7;
    static std::function<void(QWidget*, int*)> setCoordinates;
    static std::function<void(int*, QPoint*)> setVector;
};

//--------------------------------------------------------------------------

class DirectionButton : public QPushButton {
    Q_OBJECT
    using set_coordinates_function_type = std::function<void(QWidget*, int*)>;
    using set_points_function_type = std::function<void(int*, QPoint*)>;
public:
    DirectionButton(
            set_coordinates_function_type& f_set_coordinates,
            set_points_function_type& f_set_points,
            QWidget* parent = nullptr
            );
protected:
    void paintEvent(QPaintEvent*);
private slots:
    void onPressed();
    void onReleased();
private:
    constexpr static unsigned int COORDINATES_SIZE = 8;
    constexpr static unsigned int POINTS_SIZE = 7;
    set_coordinates_function_type set_coordinates;
    set_points_function_type set_points;
    int coordinates[COORDINATES_SIZE];
    QPoint points[POINTS_SIZE];
};

DirectionButton.cpp

      #include "DirectionButton.h"


//Arrow----------------------------------------------------------------
/*
 *
LEFT ARROW
        a(tot)
|--------------------|                                      a = 20/20
|          b                                                b = 18/20
|-----------------|------------------------                 c =  6/20
|   c             |                       |                 d =  2/20
|------|__________|____________________   |                 e = 12/12
|      B          |________________   |   |                 f = 10/12
|d   **C**********D               |   |   |e(tot)           g =  8/12
|-|A***************------------   |   |f  |                 h =  6/12
     **F**********E________   |   |g  |   |                 i =  4/12
       G_______________   |   |h  |   |   |                 j =  2/12
                      |j  |i  |   |   |   |
___________________________________________
coorddinates = { b, c, d, f, g, h, i, j }
points = { A(d,h), B(c,f), C(c,g), D(b,g), E(b,i), F(c,i), G(c,j) }
*/

std::function<void(QWidget*, int*)> LeftArrow::setCoordinates = [](QWidget* widget, int* coordinates) {
    int x = widget->size().width();
    coordinates[b] = x*18/20;
    coordinates[c] = x*6/20;
    coordinates[d] = x*2/20;
    int y = widget->size().height();
    coordinates[f] = y*10/12;
    coordinates[g] = y*8/12;
    coordinates[h] = y*6/12;
    coordinates[i] = y*4/12;
    coordinates[j] = y*2/12;
};

std::function<void(int*, QPoint*)> LeftArrow::setVector = [](int *coordinates, QPoint* points) {
        points[0] = QPoint(coordinates[d], coordinates[h]); //A
        points[1] = QPoint(coordinates[c], coordinates[f]); //B
        points[2] = QPoint(coordinates[c], coordinates[g]); //C
        points[3] = QPoint(coordinates[b], coordinates[g]); //D
        points[4] = QPoint(coordinates[b], coordinates[i]); //E
        points[5] = QPoint(coordinates[c], coordinates[i]); //F
        points[6] = QPoint(coordinates[c], coordinates[j]); //G
};

//RightArrow----------------------------------------------------------------

/*
RIGHT ARROW
        a(tot)
|--------------------|                                      a = 20/20
|          b                                                b = 18/20
|-----------------|------------------------                 c = 14/20
|      c          |                       |                 d =  2/20
|-------------|___|____________________   |                 e = 12/12
|             B   |________________   |   |                 f = 10/12
|d D**********C** |               |   |   |e(tot)           g =  8/12
|-|***************A------------   |   |f  |                 h =  6/12
   E**********F**__________   |   |g  |   |                 i =  4/12
              G________   |   |h  |   |   |                 j =  2/12
                      |j  |i  |   |   |   |
___________________________________________
coorddinates = { b, c, d, f, g, h, i, j }
points = { A(b,h), B(c,f), C(c,g), D(d,g), E(d,i), F(c,i), G(c,j) }
*/

std::function<void(QWidget*, int*)> RightArrow::setCoordinates = [](QWidget* widget, int* coordinates) {
    int x = widget->size().width();
    coordinates[0] = x*18/20;
    coordinates[1] = x*14/20;
    coordinates[2] = x*2/20;
    int y = widget->size().height();
    coordinates[3] = y*10/12;
    coordinates[4] = y*8/12;
    coordinates[5] = y*6/12;
    coordinates[6] = y*4/12;
    coordinates[7] = y*2/12;
};

std::function<void(int*, QPoint*)> RightArrow::setVector = [](int *coordinates, QPoint* points) {
        points[0] = QPoint(coordinates[b], coordinates[h]); //A
        points[1] = QPoint(coordinates[c], coordinates[f]); //B
        points[2] = QPoint(coordinates[c], coordinates[g]); //C
        points[3] = QPoint(coordinates[d], coordinates[g]); //D
        points[4] = QPoint(coordinates[d], coordinates[i]); //E
        points[5] = QPoint(coordinates[c], coordinates[i]); //F
        points[6] = QPoint(coordinates[c], coordinates[j]); //G
};

//--------------------------------------------------------------------------

DirectionButton::DirectionButton(
        DirectionButton::set_coordinates_function_type& f_set_coordinates,
        DirectionButton::set_points_function_type& f_set_points,
        QWidget* parent
        ) :
    QPushButton(parent),
    set_coordinates(f_set_coordinates),
    set_points(f_set_points)
{
    setStyleSheet(
                //"border-width: 1px;"
                "border-radius: 10px;"
                "background-color: lightGray;"
                );
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    connect(this, SIGNAL(pressed()), SLOT(onPressed()));
    connect(this, SIGNAL(released()), SLOT(onReleased()));
}

//protected

void DirectionButton::paintEvent(QPaintEvent *) {
    set_coordinates(this, coordinates);
    set_points(coordinates, points);
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    p.setBrush(QBrush(Qt::black));
    p.setPen(QPen(Qt::black));
    p.drawPolygon(points, POINTS_SIZE);
}

//private slots

void DirectionButton::onPressed() {
    setStyleSheet(
                //"border-width: 1px;"
                "border-radius: 10px;"
                "background-color: rgba(255, 150, 150, 128);"
    );
}

void DirectionButton::onReleased() {
    setStyleSheet(
                //"border-width: 1px;"
                "border-radius: 10px;"
                "background-color: lightGray;"
    );
}

ButtonList.h

      #pragma once

#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QStyleOption>
#include <QPainter>
#include <QScreen>
#include <QGuiApplication>

#include "DirectionButton.h"

//--------------------------------------------------------------------------

class IteratingWidget : public QWidget {
    Q_OBJECT
public:
    IteratingWidget(QWidget* parent = nullptr);
    DirectionButton* backward_button();
    DirectionButton* forward_button();
    constexpr static size_t MARGIN = 0;
    constexpr static size_t SPACING = 0;
protected:
    void resizeEvent(QResizeEvent*);
private:
    constexpr static size_t BUTTONS_WIDTH(size_t w) { return (w - (MARGIN*2) - SPACING) / 2; }
    constexpr static size_t BUTTONS_HEIGHT(size_t h) { return h-(MARGIN*2); }
    void init_buttons();
    void init_layout();
    void init_widget();
    DirectionButton* _backward,
                   * _forward;
    QHBoxLayout* h_layout;
};

//--------------------------------------------------------------------------

class ButtonList : public QWidget
{
    Q_OBJECT
public:
    explicit ButtonList(QWidget *parent = nullptr);

    QPushButton* reset();
    QPushButton* shuffle();
    QPushButton* solve();
    QPushButton* threeDView();
    QLabel* moves_label();
    IteratingWidget* iterator();
    constexpr static unsigned int MARGIN = 0;
    constexpr static unsigned int SPACING = 0;
    constexpr static unsigned int MINIMUM_BUTTON_HEIGHT = 30;
    constexpr static unsigned int MINIMUM_LABEL_HEIGHT = MINIMUM_BUTTON_HEIGHT*3;
    constexpr static unsigned int MINIMUM_WIDGET_WIDTH = 80;
    constexpr static unsigned int MINIMUM_HEIGHT = MINIMUM_BUTTON_HEIGHT*5+MINIMUM_LABEL_HEIGHT+SPACING*5+MARGIN*2;
    constexpr static unsigned int MINIMUM_WIDTH = MINIMUM_WIDGET_WIDTH+MARGIN*2;

protected:

    void resizeEvent(QResizeEvent*);

private:

    QPushButton* init_button(const QString& text);
    void init_m_label();
    void init_iterator();
    void init_layout();
    void init_widget();

    void resizeLabel(int, int);
    void resizeButton(QPushButton*, int, int);
    void resizeIterator(int, int);

    constexpr static size_t BUTTON_WIDTH(size_t w) { return w-MARGIN*2; }
    constexpr static size_t LABEL_WIDTH(size_t w) { return BUTTON_WIDTH(w); }
    constexpr static size_t BUTTON_HEIGHT(size_t h) { return ( h - (MARGIN*2) - (SPACING*5) )/8; }
    constexpr static size_t LABEL_HEIGHT(size_t h) { return BUTTON_HEIGHT(h)*3; }

    QVBoxLayout* v_layout;//main layout
    QPushButton* _reset,
               * _shuffle,
               * _solve,
               * _3dview;
    IteratingWidget* _iterator;
    QLabel* m_label;
};

//   _____________________
//  |                     |
//  |        RESET        | 1x
//  |_____________________|
//  |                     |
//  |       SHUFFLE       | 1x
//  |_____________________|
//  |                     |
//  |        SOLVE        | 1x
//  |_____________________|
//  |                     |
//  |        LABEL        | 3x
//  |_____________________|
//  |          |          |
//  |  FORWARD | BACKWARD | 1x
//  |_____________________|
//  |                     |
//  |       3D VIEW       | 1x
//  |_____________________|

ButtonList.cpp

      #include "ButtonList.h"

//IteratingWidget

IteratingWidget::IteratingWidget(QWidget* parent) :
    QWidget(parent)
{
    init_buttons();
    init_layout();
    init_widget();
}

DirectionButton* IteratingWidget::backward_button() { return _backward; }
DirectionButton* IteratingWidget::forward_button() { return _forward; }

//protected

void IteratingWidget::resizeEvent(QResizeEvent*) {
    _backward->resize(BUTTONS_WIDTH(size().width()), BUTTONS_HEIGHT(size().height()));
    _forward->resize(BUTTONS_WIDTH(size().width()), BUTTONS_HEIGHT(size().height()));
}

//private

void IteratingWidget::init_buttons() {
    _backward = new DirectionButton(LeftArrow::setCoordinates, LeftArrow::setVector);
    _forward = new DirectionButton(RightArrow::setCoordinates, RightArrow::setVector);
    _backward->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _forward->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}

void IteratingWidget::init_layout() {
    h_layout = new QHBoxLayout();
    h_layout->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
    h_layout->setSpacing(SPACING);
    h_layout->addWidget(_backward);
    h_layout->addWidget(_forward);
}

void IteratingWidget::init_widget() {
    setLayout(h_layout);
}

//ButtonList

ButtonList::ButtonList(QWidget *parent) : QWidget(parent)
{

    _reset =    init_button("RESET");
    _shuffle =  init_button("SHUFFLE");
    _solve =    init_button("SOLVE");
                init_m_label();
                init_iterator();
    _3dview =   init_button("3D VIEW");
                init_layout();
                init_widget();

    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    setMinimumSize(86, 246);

}

QPushButton* ButtonList::reset() { return _reset; }
QPushButton* ButtonList::shuffle() { return _shuffle; }
QPushButton* ButtonList::solve() { return _solve; }
QPushButton* ButtonList::threeDView() { return _3dview; }
QLabel* ButtonList::moves_label() { return m_label; }
IteratingWidget* ButtonList::iterator() { return _iterator; }

//protected

void ButtonList::resizeEvent(QResizeEvent *) {
    int w = size().width(), h = size().height();
    resizeButton(_reset, w, h);
    resizeButton(_shuffle, w, h);
    resizeButton(_solve, w, h);
    resizeLabel(w, h);
    resizeIterator(w, h);
    resizeButton(_3dview, w, h);
    //_iterator->backward_button()->setStyleSheet("background-color: lightGray;");
}

//private

QPushButton* ButtonList::init_button(const QString& text) {
    QPushButton *button = new QPushButton(text);
    button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    button->setMinimumSize(80, 30);
    QFont f;
    f.setPixelSize(button->size().height()*3/7);
    button->setFont(f);
    return button;
}

void ButtonList::init_m_label() {
    m_label = new QLabel("U2");
    m_label->setAlignment(Qt::AlignCenter);
    m_label->setMinimumSize(80, 90);
    QFont f;
    f.setPixelSize(m_label->size().height()*6/7);
    m_label->setFont(f);
}

void ButtonList::init_iterator() {
    _iterator = new IteratingWidget();
    _iterator->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _iterator->setMinimumSize(80, 30);
}

void ButtonList::init_layout() {
    v_layout = new QVBoxLayout();
    v_layout->setContentsMargins(MARGIN, MARGIN, MARGIN, MARGIN);
    v_layout->setSpacing(SPACING);
    v_layout->setAlignment(Qt::AlignCenter);
    v_layout->addWidget(_reset);
    v_layout->addWidget(_shuffle);
    v_layout->addWidget(_solve);
    v_layout->addWidget(m_label);
    v_layout->addWidget(_iterator);
    v_layout->addWidget(_3dview);
}

void ButtonList::init_widget() {
    setLayout(v_layout);
    setMinimumSize(MINIMUM_WIDTH, MINIMUM_HEIGHT);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}

void ButtonList::resizeLabel(int w, int h) {
    m_label->resize(LABEL_WIDTH(w), LABEL_HEIGHT(h));
    QFont f;
    f.setPixelSize(m_label->size().height()*6/7);
    m_label->setFont(f);
}

void ButtonList::resizeIterator(int w, int h) {
    _iterator->resize(BUTTON_WIDTH(w), BUTTON_HEIGHT(h));
}

void ButtonList::resizeButton(QPushButton *button, int w, int h) {
    button->resize(BUTTON_WIDTH(w), BUTTON_HEIGHT(h));
    QFont f;
    f.setPixelSize(button->size().height()*3/7);
    button->setFont(f);
}

Когда я изменяю размер виджетов, некоторые из них накладываются друг на друга

Если я нажму стрелку влево или вправо, окно будет исправлено.

Сигналы 2 кнопок со стрелками pressed() а также released() подключены к 2 пользовательским слотам, которые меняют цвет фона через setStyleSheet(...). Чтобы исправить это, я попытался добавить ListButton::resizeEvent(QResizeEvent*) линия _iterator->backward_button()->setStyleSheet("background-color: lightGray")и это сработало. Кто-нибудь может мне объяснить, что происходит?

0 ответов

Другие вопросы по тегам