「Qtの基礎 - ウインドウ」の版間の差分

ナビゲーションに移動 検索に移動
351行目: 351行目:
     setTexture(palette, QPalette::Mid, midImage);
     setTexture(palette, QPalette::Mid, midImage);
     setTexture(palette, QPalette::Window, backgroundImage);
     setTexture(palette, QPalette::Window, backgroundImage);
}
</syntaxhighlight>
<br>
==== ウインドウおよびウィジェットの形状を変更する ====
ウインドウおよびウィジェットの形状を変更するには、ウィジェットの形状をプログラムで全て記述する必要がある。<br>
<br>
例えば、ボタンの形状を変更する場合、外形を描画するだけではなく、<br>
ボタンが立体的に見えるように陰影の描画、ボタン押下時の陰影の変化等も記述する必要がある。<br>
(或いは、QSS + 背景画像で形状を変更できる可能性がある)<br>
<br>
ウインドウおよびウィジェットの形状を記述するには、<code>QStyle</code>クラスを継承した派生クラスを作成して、<br>
<code>QStyle</code>クラスの<code>drawPrimitive</code>メソッドをオーバーライドする。<br>
<br>
以下の例では、ボタンの形状を変更している。<br>
Qtに付属しているサンプルを参考にしている。(<Qtのインストールディレクトリ>/examples/widgets/styles/norwegianwoodstyle.cppファイル)<br>
<syntaxhighlight lang="c++">
void MyStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
    switch(element)
    {
      // ウィジェットのPrimitiveの種類を指定する(ウィジェットの種類ではない)
      case PE_PanelButtonCommand:
          int delta = (option->state & State_MouseOver) ? 64 : 0;
          QColor slightlyOpaqueBlack(0, 0, 0, 63);
          QColor semiTransparentWhite(255, 255, 255, 127 + delta);
          QColor semiTransparentBlack(0, 0, 0, 127 - delta);
          int x, y, width, height;
          option->rect.getRect(&x, &y, &width, &height);
          // 以下の3行のみ追記する
          // ボタンの形状を楕円にする
          QPainterPath path;
          path.addEllipse(option->rect);
          // これ以降の記述はコピーである
          // ボタンの押下時と非押下時の陰影等を記述する
          // 様々な形状に対応している
          int radius = qMin(width, height) / 2;
          QBrush brush;
          bool darker;
          const QStyleOptionButton *buttonOption = qstyleoption_cast<const QStyleOptionButton *>(option);
          if(buttonOption && (buttonOption->features & QStyleOptionButton::Flat))
          {
            brush = option->palette.background();
            darker = (option->state & (State_Sunken | State_On));
          }
          else
          {
            if(option->state & (State_Sunken | State_On))
            {
                brush = option->palette.mid();
                darker = !(option->state & State_Sunken);
            }
            else
            {
                brush = option->palette.button();
                darker = false;
            }
          }
          painter->save();
          painter->setRenderHint(QPainter::Antialiasing, true);
          painter->fillPath(path, brush);
          if(darker)
          {
            painter->fillPath(path, slightlyOpaqueBlack);
          }
          int penWidth;
          if(radius < 10)
            penWidth = 3;
          else if (radius < 20)
            penWidth = 5;
          else
            penWidth = 7;
          QPen topPen(semiTransparentWhite, penWidth);
          QPen bottomPen(semiTransparentBlack, penWidth);
          if(option->state & (State_Sunken | State_On))
          {
            qSwap(topPen, bottomPen);
          }
          int x1 = x;
          int x2 = x + radius;
          int x3 = x + width - radius;
          int x4 = x + width;
          if(option->direction == Qt::RightToLeft)
          {
            qSwap(x1, x4);
            qSwap(x2, x3);
          }
          QPolygon topHalf;
          topHalf << QPoint(x1, y) << QPoint(x4, y) << QPoint(x3, y + radius) << QPoint(x2, y + height - radius) << QPoint(x1, y + height);
          painter->setClipPath(path);
          painter->setClipRegion(topHalf, Qt::IntersectClip);
          painter->setPen(topPen);
          painter->drawPath(path);
          QPolygon bottomHalf = topHalf;
          bottomHalf[0] = QPoint(x4, y + height);
          painter->setClipPath(path);
          painter->setClipRegion(bottomHalf, Qt::IntersectClip);
          painter->setPen(bottomPen);
          painter->drawPath(path);
          painter->setPen(option->palette.foreground().color());
          painter->setClipping(false);
          painter->drawPath(path);
          painter->restore();
          break;
      default:
          // ボタン以外はMotifStyleの形状を採用
          QMotifStyle::drawPrimitive(element, option, painter, widget);
          break;
    }
  }
  }
  </syntaxhighlight>
  </syntaxhighlight>

案内メニュー