首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

QT 圖形視圖框架:基於 QGraphicsWidget 實現多狀態 Button 控件

     編輯:關於C語言

實現 Button 與 Label 類似,差別在於 Button 擁有 Normal、Hover、Pressed 三種狀態,針對三種狀態分別實現即可。支援三種樣式:純圖標、純文字、圖文混排(文字在圖標旁或下)。

核心類設計:ShowButton

class ShowButton : public QGraphicsWidget {
  Q_OBJECT
public:
  enum State { NormalState, HoverState, PressedState };
  enum Style { TextOnly, IconOnly, TextBesidesIcon, TextUnderIcon };
  
  ShowButton(const QPixmap&, const QPixmap&, const QPixmap&);
  void setText(const QString&, const QFont&, const QColor&);
  void setIcon(const QPixmap&);
  void setStyle(Style);
  QString getText();
signals:
  void clicked();
protected:
  void mousePressEvent(QGraphicsSceneMouseEvent*);
  void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
  void hoverEnterEvent(QGraphicsSceneHoverEvent*);
  void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
  virtual QRectF boundingRect();
  virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget* = 0);
private:
  void setPixmap(State);
  // 成員變數:三種狀態圖片、圖標、文字、字體、顏色、樣式等
};

關鍵實現細節

1. 狀態切換

void ShowButton::setPixmap(State state) {
  switch (state) {
    case NormalState: m_pixmap = m_normalPixmap; break;
    case HoverState: m_pixmap = m_hoverPixmap; break;
    case PressedState: m_pixmap = m_pressedPixmap; break;
  }
}
void ShowButton::mousePressEvent(QGraphicsSceneMouseEvent* e) {
  if (e->button() == Qt::LeftButton) {
    m_isPressed = true; setPixmap(PressedState); update();
  }
}
void ShowButton::mouseReleaseEvent(QGraphicsSceneMouseEvent* e) {
  if (e->button() == Qt::LeftButton && m_isPressed) {
    m_cnt++; m_isPressed = false; setPixmap(NormalState); update(); emit clicked();
  }
}
void ShowButton::hoverEnterEvent(QGraphicsSceneHoverEvent*) {
  if (!m_isPressed) { setPixmap(HoverState); update(); }
}
void ShowButton::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
  if (!m_isPressed) { setPixmap(NormalState); update(); }
}

2. 繪製邏輯(支援四種樣式)

void ShowButton::paint(QPainter* painter, ...) {
  QRect rect = boundingRect().toRect();
  setPreferredSize(rect.width(), rect.height());
  painter->drawPixmap(rect, m_pixmap); // 畫背景
  
  // 僅圖標 / 僅文字
  if (m_iconOn && !m_icon.isNull()) { ... }
  else if (m_textOn && !m_text.isEmpty()) { ... }
  
  // 圖文混排
  if (m_textOn && m_iconOn && !m_icon.isNull() && !m_text.isEmpty()) {
    if (TextBesidesIcon == m_style) { // 文字在圖標右側
      QRect mixRect(0, 0, m_icon.size().width(), rect.height());
      painter->drawPixmap(mixRect, m_icon);
      QRect textRect(m_icon.size().width(), 0, rect.width() - m_icon.size().width(), rect.height());
      painter->drawText(textRect, Qt::AlignCenter, m_text);
    }
    if (TextUnderIcon == m_style) { // 文字在圖標下方
      QRect mixRect(0, 0, rect.width(), m_icon.size().height());
      painter->drawPixmap(mixRect, m_icon);
      QRect textRect(0, m_icon.size().height(), rect.width(), rect.height() - m_icon.size().height());
      painter->drawText(textRect, Qt::AlignCenter, m_text);
    }
  }
}

3. 尺寸計算

QRectF ShowButton::boundingRect() {
  // 根據 m_style 計算總寬高:文字尺寸 + 圖標尺寸
  // TextBesidesIcon: 寬 = 文字寬 + 圖標寬,高 = max(文字高, 圖標高)
  // TextUnderIcon: 寬 = max(文字寬, 圖標寬),高 = 文字高 + 圖標高
  return QRectF(0, 0, totalWidth, totalHeight);
}

信號槽分離設計

Button 僅發射 clicked() 信號,具體業務邏輯封裝於 ClickHandler 類:

class ClickHandler : public QObject {
  Q_OBJECT
public: ClickHandler(QObject* parent);
private slots:
  void on_linkOpen();   // 開啟網址
  void on_messageBox(); // 彈出訊息框
};

主程式組裝

ShowButton *btn1 = new ShowButton(normal, hover, pressed);
btn1->setStyle(ShowButton::IconOnly);
btn1->setIcon(icon); btn1->setMaximumSize(icon.size());

ShowButton *btn2 = new ShowButton(normal, hover, pressed);
btn2->setStyle(ShowButton::TextOnly);
btn2->setText("YY", font, color);
btn2->setMaximumSize(textWidth, textHeight);

ShowButton *btn3 = new ShowButton(normal, hover, pressed);
btn3->setStyle(ShowButton::TextUnderIcon);
btn3->setText("YY", font, color);
btn3->setIcon(icon);
btn3->setMaximumSize(textWidth + icon.width(), textHeight + icon.height());

// 佈局
QGraphicsWidget *widget = new QGraphicsWidget;
QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
layout->addItem(btn1); layout->addItem(btn2); layout->addItem(btn3);
widget->setLayout(layout);
scene->addItem(widget);

本文出自「賣萌程序員」博客,轉載請保留出處:https://7677869.blog.51cto.com/7667869/1265278

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved