Подтвердить что ты не робот

Почему QHBoxLayout приводит к перекрытию виджета?

Мне нужно разместить несколько экземпляров пользовательского подкласса QPushButton, смежных друг с другом. По какой-то причине кнопки накладываются друг на друга при окрашивании. Ниже приведен упрощенный пример проблемы.

Вот (неправильный) вывод:

overlapping

Вот код:

#include <QtGui>

class MyButton : public QPushButton {
public:
  explicit MyButton(Qt::GlobalColor color, QWidget *parent = NULL)
    : QPushButton(parent), color_(color) {
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  }
  QSize sizeHint() const {
    return QSize(50, 25);
  }
protected:
  void paintEvent(QPaintEvent *) {
    QPainter painter(this);
    painter.setOpacity(0.5);
    painter.fillRect(0, 0, width(), height(), color_);
  }
private:
  Qt::GlobalColor color_;
};

int main(int argc, char **argv) {
  QApplication app(argc, argv);
  QWidget widget;
  QHBoxLayout *layout = new QHBoxLayout;
  layout->setSpacing(0);
  MyButton *w1 = new MyButton(Qt::red);
  MyButton *w2 = new MyButton(Qt::green);
  MyButton *w3 = new MyButton(Qt::blue);
  layout->addWidget(w1);
  layout->addWidget(w2);
  layout->addWidget(w3);
  widget.setLayout(layout);
  widget.show();
  return app.exec();
}

Что вызывает это, и как его исправить? Кстати, я пробовал что-то подобное с обычными подклассами QWidget (вместо подклассов QPushButton), и проблем нет. Это нечто особенное для QPushButton.

ОБНОВЛЕНИЕ: Я сейчас думаю, что это ошибка. Я отправил его в Qt Bug Tracker; мы посмотрим, что думают Тролли. В любом случае, исходя из QAbstractButton исправляет проблему рисования... Мне просто пришлось повторно реализовать некоторые из необходимых мне функций.

ОБНОВЛЕНИЕ 2: Тролли в Qt предоставили решение (обходной путь?); Я опубликовал их исправление в качестве ответа ниже. Я оставляю их в своей команде, чтобы определить, является ли это особенностью или ошибкой. По-видимому, он ведет себя по-разному на Mac.

4b9b3361

Ответ 1

Решение состоит в том, чтобы добавить в подкласс следующее:

setAttribute(Qt::WA_LayoutUsesWidgetRect);

По-видимому, это необходимо только на платформе Mac; Windows и Linux отображают макет, как ожидалось.

Ответ 2

Вместо вызова setSizePolicy() и reimplement sizeHint() я попытался бы просто вызвать

setFixedSize(50, 25)

в вашем конструкторе. Это должно обновить sizeHint самостоятельно.

Надеюсь, что это поможет.

Ответ 3

Ваш код отлично работает для меня. Я протестировал его. Какую версию вы используете? Я использую Qt 4.6.3, и это нормально.