2

I must create a QPushButton that contains an icon and 2 lines of text.

Ideally I should be able to put the icon either on the left side (on one design) or in the center, above the text (for another design in another view).

The 2 lines of text I need to be able to set separately (and even with different text size). Not text wrap.

I am going to subclass a QPushButton, set a grid layout, and add the icon and 2 QLabels. Add a setText2() and text2(). Seems simple.

I have seen people suggesting this "just subclass xx control and add your own layout" but never with an actual non-breaking example.

My question:

What must I do to take advantage of all the built-in properties and events of the QPushButton ? What must I do to ensure I have the correct resize events, and that the icon and label I add for the first line of text are the QPushButton's actual icon and text so that they will be applied correctly ?

I have been searching and I cannot find the drawing elements of the QPushButton (the containers for the QIcon and text) - it would help me if at least I could find those, so I can make my own layout using them.

p-a-o-l-o
  • 9,807
  • 2
  • 22
  • 35
Thalia
  • 13,637
  • 22
  • 96
  • 190
  • 1
    Why can't you do simply this: `QPushButton button("Line1\nLine2");`? – vahancho Mar 23 '18 at 15:38
  • @vahancho: If I can't make a custom button, it will be what I have to do. But my requirements include custom layout (text under icon as an option) and different font sizes for the 2 lines, which I can't accomplish with plain text – Thalia Mar 23 '18 at 16:00

1 Answers1

2

Before subclassing, I would try adding a layout to a QpushButton, and add the needed widgets to the layout. To keep things together, I'd rather subclass QWidget and have a class like this:

class CustomButton : public QWidget
{
public:
  explicit CustomButton(QWidget * parent);

private:
  QPushButton button;
  QLabel * icon;
  QLabel * line1;
  QLabel * line2;
};

Just add public methods to set the icon and the text lines:

public:
  void setTextLines(QString & l1, QString & l2)
  {
    line1->setText(l1);
    line2->setText(l2);
  }

  void setIcon(QPixmap & pixmap)
  {
    icon->setPixmap(pixmap);
  }

and a custom signal:

signals:
  void clicked();

This is a possible constructor, where widgets are instantiated and the signal directly connected to the push button signal:

CustomButton::CustomButton(QWidget *parent)
{
  button = new QPushButton();
  icon = new QLabel(); //use a label to host the icon
  line1 = new QLabel();
  line2 = new QLabel();

  connect(button, SIGNAL(clicked(bool)), this, SIGNAL(clicked()));

  QHBoxLayout * hl = new QHBoxLayout();
  hl->addWidget(icon);

  QVBoxLayout * vl = new QVBoxLayout();
  vl->addWidget(line1);
  vl->addWidget(line2);

  hl->addLayout(vl);
  button->setLayout(hl);

  QGridLayout * gl = new QGridLayout();
  gl->addWidget(button);

  setLayout(gl);
}

The code to arrange the widgets can be moved in specialized methods.

Why not to subclass QPushButton or QAbstractButton, which seem the logical choices? The most practical reason is: methods like setText and setIcon have no meaning anymore in this class (and are dangerous, even). Way better to expose the labels and the button methods (and signals) through a safe proxy, and only the needed ones.

p-a-o-l-o
  • 9,807
  • 2
  • 22
  • 35
  • It is what I am trying to do - but I need to be able to set the texts and icon to the button during execution... which means that I must have the icon be the button's known icon, and the texts be also part of the button. – Thalia Mar 23 '18 at 17:48
  • 1
    @Thalia I edited the answer to address your concern. – p-a-o-l-o Mar 23 '18 at 19:23
  • I must really use a QPushButton or QAbstractButton at the least. This object is used, among other things, as a member in a list of QAbstractButtonList, as a choice in a QButtonGroup, as a push button inside another pushbutton... I do not choose my types at random. My entire question was: how can I use the parent button icon and text - because reading the qt code, there does not seem to be any hook to them unless I rewrite the paint and many other functions.. Your answer, as far as I understand it, is that I can't and should not even try. – Thalia Mar 26 '18 at 16:29
  • @Thalia of course you can subclass `QPushButton` and override the paint event. I suggested a less complicated way, but unfortunately it looks like it doesn't fit your needs. – p-a-o-l-o Mar 27 '18 at 09:12