【Qt】Custom shaped dialog


【目的】

  • 顯示不規則視窗。
  • 如果要寫一個手機模擬器的話,一般視窗會有一個 border(中間圖形),
    我們希望能把視窗的外框拿掉,讓使用者有一個更真實的感覺(右邊部分)。
    • 左圖: 原始圖(170x334),拿來當底圖。
    • 中圖: 一般執行結果。
    • 右圖: 使用setMask ,將 Dialog 外框拿掉。
    • 原本手機有四顆按鈕(Verizon字串下方),我們也在這邊實現第一顆按鈕的功能。
      你可以看到右圖和左圖下方第一顆按鈕是不一樣的,當使用者按下第一顆按鈕,則會關掉視窗。
      按鈕外型通常會顯示跟左圖第一個按鈕一樣, 但此處不特別作處理。
    • 圖形由網路隨機抓取示範,本人並非圖形作者。

      image image image 

【環境】

  • Windows Vista。

【程式】
創造一個Dialog。放置一個 pushButton。 並加入下面的程式碼。其中重要的部分如下。

  • dialog.cpp ( 使用 setMask 來遮罩出所需圖形)
    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
      this->setGeometry(0, 0, 170, 334);
      this->setStyleSheet("background-image: url(background.jpg)");
      this->setMask(QRegion(0, 0, 170, 334, QRegion::Rectangle));
      //this->setAcceptDrops(true);
      //this->setAutoFillBackground(true);
      //setWindowOpacity(1);
      ui->setupUi(this);
    }
    void Dialog::on_pushButton_clicked()
    {
      close();
    }
  • dialog.h ( 當使用者按下第一顆按鈕,將整個應用程式關閉)
    class Dialog : public QDialog {
        Q_OBJECT
    ...
        void on_pushButton_clicked();
    };
  • dialog.ui (此處直接定義出 pushButton 位置)
    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>Dialog</class>
     <widget class="QDialog" name="Dialog">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>397</width>
        <height>489</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Emulator</string>
      </property>
      <widget class="QPushButton" name="pushButton">
       <property name="geometry">
        <rect>
         <x>18</x>
         <y>305</y>
         <width>30</width>
         <height>10</height>
        </rect>
       </property>
       <property name="text">
        <string/>
       </property>
      </widget>
     </widget>
     <layoutdefault spacing="6" margin="11"/>
     <resources/>
     <connections/>
    </ui>
    結果 123

【結果】

  • 同上圖最右方。

【問題】

  • 如何產生更真實效果,如把四個角落的邊都修成圓弧形(RoundRectangle)或更不規則外框。
    A: 由於QRegion目前只支援Rectangle/Ellipse,並沒有支援RoundRect。
    如需實現更不規則外框,請參考 Qt | Tux 這個範例。以下提示程式重點部分。
    主要就是把圖形的輪廓遮罩成視窗的外框。
    main.c (圖片來至 http://upload.wikimedia.org/wikipedia/commons/3/3e/Tux-G2.png
    #include <QPixmap>
    #include <QPalette>
    #include <QBrush>
    #include <QFile>
    #include <QBitmap>
    
    int main(int argc, char *argv[])
    {
      QApplication a(argc, argv);
      Dialog w;
      QString fn = "../tux.png";
    
      if (!QFile::exists(fn))
      exit(1);
    
      QPixmap pixmap("../tux.png");
      QPalette palette;
      palette.setBrush(w.backgroundRole(), QBrush(pixmap));
      w.setPalette(palette);
      w.setFixedSize( pixmap.size() );
      w.setMask(pixmap.mask());
      w.show();
      return a.exec();
    }
    呈現結果 (底下的小企鵝就是整個不規則視窗)
    image
  • 因為外框遮罩掉後,導致無法移動視窗位置。如何實現拖曳功能。
    A: 需自行定義 mousePressEvent/mouseMoveEvent。
  • 除了 Dialog ,如何產生不規則外型元件(如不規則的 pushButton)。
    • 直接設定 Icon,將 Text 拿掉 。
    • 設定 Flat 。
    • 將 pushButton size 設成跟 Icon 大小一樣。
  • 以上方式和下面方式有何不同?
    setWindowFlags(Qt::FramelessWindowHint);

【參考】

 

Ed32. Copyright 2008 All Rights Reserved Revolution Two Church theme by Brian Gardner Converted into Blogger Template by Bloganol dot com