Куриное поведение в 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")
и это сработало. Кто-нибудь может мне объяснить, что происходит?